Skip to content

Commit 86880c9

Browse files
committed
Fix ICE in fn_delegation when child segment resolves to a trait
When a delegation path like `reuse Trait::<> as bar4` has a child segment that resolves to a trait instead of a function, the compiler would ICE because `lower_generic_args_of_path` asserts that `self_ty` is `Some` when `has_self` is true and `parent` is `None`. Fix this by filtering out non-function child segments early using `.filter()` in the method chain, so that when the child segment resolves to a trait (error recovery for E0423), we skip generic args computation entirely and return an empty list via `unwrap_or_default()`. Also make `get_segment` return `Option` by using `opt_def_id()` instead of `def_id()` to gracefully handle unresolved segments.
1 parent 3b1b0ef commit 86880c9

3 files changed

Lines changed: 51 additions & 24 deletions

File tree

compiler/rustc_hir_analysis/src/delegation.rs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -597,31 +597,35 @@ fn get_delegation_user_specified_args<'tcx>(
597597
.as_slice()
598598
});
599599

600-
let child_args = info.child_args_segment_id.and_then(get_segment).map(|(segment, def_id)| {
601-
let parent_args = if let Some(parent_args) = parent_args {
602-
parent_args
603-
} else {
604-
let parent = tcx.parent(def_id);
605-
if matches!(tcx.def_kind(parent), DefKind::Trait) {
606-
ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
600+
let child_args = info
601+
.child_args_segment_id
602+
.and_then(get_segment)
603+
.filter(|(_, def_id)| matches!(tcx.def_kind(*def_id), DefKind::Fn | DefKind::AssocFn))
604+
.map(|(segment, def_id)| {
605+
let parent_args = if let Some(parent_args) = parent_args {
606+
parent_args
607607
} else {
608-
&[]
609-
}
610-
};
611-
612-
let args = lowerer
613-
.lower_generic_args_of_path(
614-
segment.ident.span,
615-
def_id,
616-
parent_args,
617-
segment,
618-
None,
619-
GenericArgPosition::Value,
620-
)
621-
.0;
622-
623-
&args[parent_args.len()..]
624-
});
608+
let parent = tcx.parent(def_id);
609+
if matches!(tcx.def_kind(parent), DefKind::Trait) {
610+
ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
611+
} else {
612+
&[]
613+
}
614+
};
615+
616+
let args = lowerer
617+
.lower_generic_args_of_path(
618+
segment.ident.span,
619+
def_id,
620+
parent_args,
621+
segment,
622+
None,
623+
GenericArgPosition::Value,
624+
)
625+
.0;
626+
627+
&args[parent_args.len()..]
628+
});
625629

626630
(parent_args.unwrap_or_default(), child_args.unwrap_or_default())
627631
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ needs-rustc-debug-assertions
2+
#![feature(fn_delegation)]
3+
#![allow(incomplete_features)]
4+
5+
trait Trait {
6+
fn bar4();
7+
}
8+
9+
impl Trait for () {
10+
reuse Trait::<> as bar4;
11+
//~^ ERROR expected function, found trait `Trait`
12+
}
13+
14+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0423]: expected function, found trait `Trait`
2+
--> $DIR/reuse-trait-path-with-empty-generics.rs:10:11
3+
|
4+
LL | reuse Trait::<> as bar4;
5+
| ^^^^^^^^^ not a function
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0423`.

0 commit comments

Comments
 (0)