Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 24da053

Browse files
committedDec 3, 2024
Fix ICE when multiple supertrait substitutions need assoc but only one is provided
1 parent 5bef8ce commit 24da053

10 files changed

+71
-35
lines changed
 

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
145145
let bound_predicate = pred.kind();
146146
match bound_predicate.skip_binder() {
147147
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
148-
let pred = bound_predicate.rebind(pred);
148+
// FIXME(negative_bounds): Handle this correctly...
149+
let trait_ref =
150+
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
149151
needed_associated_types.extend(
150-
tcx.associated_items(pred.def_id())
152+
tcx.associated_items(trait_ref.def_id())
151153
.in_definition_order()
152154
.filter(|item| item.kind == ty::AssocKind::Type)
153155
.filter(|item| !item.is_impl_trait_in_trait())
154156
// If the associated type has a `where Self: Sized` bound,
155157
// we do not need to constrain the associated type.
156158
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
157-
.map(|item| item.def_id),
159+
.map(|item| (item.def_id, trait_ref)),
158160
);
159161
}
160162
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
@@ -206,7 +208,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
206208
// corresponding `Projection` clause
207209
for (projection_bound, span) in &projection_bounds {
208210
let def_id = projection_bound.projection_def_id();
209-
needed_associated_types.swap_remove(&def_id);
211+
let trait_ref = tcx.anonymize_bound_vars(
212+
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
213+
);
214+
needed_associated_types.swap_remove(&(def_id, trait_ref));
210215
if tcx.generics_require_sized_self(def_id) {
211216
tcx.emit_node_span_lint(
212217
UNUSED_ASSOCIATED_TYPE_BOUNDS,

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
717717
pub(crate) fn check_for_required_assoc_tys(
718718
&self,
719719
principal_span: Span,
720-
missing_assoc_types: FxIndexSet<DefId>,
720+
missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
721721
potential_assoc_types: Vec<usize>,
722722
trait_bounds: &[hir::PolyTraitRef<'_>],
723723
) -> Result<(), ErrorGuaranteed> {
@@ -726,27 +726,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
726726
}
727727

728728
let tcx = self.tcx();
729-
let missing_assoc_types: Vec<_> =
730-
missing_assoc_types.into_iter().map(|def_id| tcx.associated_item(def_id)).collect();
731-
let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default();
729+
// FIXME: This logic needs some more care w.r.t handling of conflicts
730+
let missing_assoc_types: Vec<_> = missing_assoc_types
731+
.into_iter()
732+
.map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
733+
.collect();
734+
let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default();
732735
let mut names_len = 0;
733736

734737
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
735738
// `issue-22560.rs`.
736739
let mut dyn_compatibility_violations = Ok(());
737-
for assoc_item in &missing_assoc_types {
738-
let trait_def_id = assoc_item.container_id(tcx);
739-
names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name);
740+
for (assoc_item, trait_ref) in &missing_assoc_types {
741+
names.entry(trait_ref).or_default().push(assoc_item.name);
740742
names_len += 1;
741743

742744
let violations =
743-
dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
745+
dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item);
744746
if !violations.is_empty() {
745747
dyn_compatibility_violations = Err(report_dyn_incompatibility(
746748
tcx,
747749
principal_span,
748750
None,
749-
trait_def_id,
751+
trait_ref.def_id(),
750752
&violations,
751753
)
752754
.emit());
@@ -797,6 +799,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
797799
.into_iter()
798800
.map(|(trait_, mut assocs)| {
799801
assocs.sort();
802+
let trait_ = trait_.print_trait_sugared();
800803
format!("{} in `{trait_}`", match &assocs[..] {
801804
[] => String::new(),
802805
[only] => format!("`{only}`"),
@@ -824,19 +827,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
824827
let mut already_has_generics_args_suggestion = false;
825828

826829
let mut names: UnordMap<_, usize> = Default::default();
827-
for item in &missing_assoc_types {
830+
for (item, _) in &missing_assoc_types {
828831
types_count += 1;
829832
*names.entry(item.name).or_insert(0) += 1;
830833
}
831834
let mut dupes = false;
832835
let mut shadows = false;
833-
for item in &missing_assoc_types {
836+
for (item, trait_ref) in &missing_assoc_types {
834837
let prefix = if names[&item.name] > 1 {
835-
let trait_def_id = item.container_id(tcx);
838+
let trait_def_id = trait_ref.def_id();
836839
dupes = true;
837840
format!("{}::", tcx.def_path_str(trait_def_id))
838841
} else if bound_names.get(&item.name).is_some_and(|x| *x != item) {
839-
let trait_def_id = item.container_id(tcx);
842+
let trait_def_id = trait_ref.def_id();
840843
shadows = true;
841844
format!("{}::", tcx.def_path_str(trait_def_id))
842845
} else {
@@ -875,8 +878,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
875878
} else if let (Ok(snippet), false, false) =
876879
(tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
877880
{
878-
let types: Vec<_> =
879-
missing_assoc_types.iter().map(|item| format!("{} = Type", item.name)).collect();
881+
let types: Vec<_> = missing_assoc_types
882+
.iter()
883+
.map(|(item, _)| format!("{} = Type", item.name))
884+
.collect();
880885
let code = if snippet.ends_with('>') {
881886
// The user wrote `Trait<'a>` or similar and we don't have a type we can
882887
// suggest, but at least we can clue them to the correct syntax
@@ -908,15 +913,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
908913
if suggestions.len() != 1 || already_has_generics_args_suggestion {
909914
// We don't need this label if there's an inline suggestion, show otherwise.
910915
let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
911-
for item in &missing_assoc_types {
916+
for (item, _) in &missing_assoc_types {
912917
types_count += 1;
913918
*names.entry(item.name).or_insert(0) += 1;
914919
}
915920
let mut label = vec![];
916-
for item in &missing_assoc_types {
921+
for (item, trait_ref) in &missing_assoc_types {
917922
let postfix = if names[&item.name] > 1 {
918-
let trait_def_id = item.container_id(tcx);
919-
format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
923+
format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
920924
} else {
921925
String::new()
922926
};

‎tests/ui/associated-types/missing-associated-types.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ LL | type Bat<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Fine<Rhs>;
4242
= help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add<Rhs> + Sub<Rhs> + Fine<Rhs> {}`
4343
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
4444

45-
error[E0191]: the value of the associated types `Output` in `Div`, `Output` in `Mul` must be specified
45+
error[E0191]: the value of the associated types `Output` in `Div<Rhs>`, `Output` in `Mul<Rhs>` must be specified
4646
--> $DIR/missing-associated-types.rs:20:21
4747
|
4848
LL | type Bal<Rhs> = dyn X<Rhs>;
49-
| ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified
49+
| ^^^^^^ associated types `Output` (from trait `Div<Rhs>`), `Output` (from trait `Mul<Rhs>`) must be specified
5050
|
5151
= help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types
5252

‎tests/ui/dyn-compatibility/assoc_type_bounds.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Foo<T> {
77
trait Cake {}
88
impl Cake for () {}
99

10-
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
11-
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
10+
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified
11+
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified
1212

1313
fn main() {}

‎tests/ui/dyn-compatibility/assoc_type_bounds.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
1+
error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified
22
--> $DIR/assoc_type_bounds.rs:10:16
33
|
44
LL | type Bar
@@ -7,7 +7,7 @@ LL | type Bar
77
LL | fn foo(_: &dyn Foo<()>) {}
88
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
99

10-
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
10+
error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
1111
--> $DIR/assoc_type_bounds.rs:11:16
1212
|
1313
LL | type Bar

‎tests/ui/dyn-compatibility/assoc_type_bounds2.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Foo<T> {
77
trait Cake {}
88
impl Cake for () {}
99

10-
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
11-
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
10+
fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified
11+
fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified
1212

1313
fn main() {}

‎tests/ui/dyn-compatibility/assoc_type_bounds2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
1+
error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified
22
--> $DIR/assoc_type_bounds2.rs:10:16
33
|
44
LL | type Bar
@@ -7,7 +7,7 @@ LL | type Bar
77
LL | fn foo(_: &dyn Foo<()>) {}
88
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
99

10-
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
10+
error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
1111
--> $DIR/assoc_type_bounds2.rs:11:16
1212
|
1313
LL | type Bar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
trait Sup<T> {
2+
type Assoc: Default;
3+
}
4+
5+
impl<T: Default> Sup<T> for () {
6+
type Assoc = T;
7+
}
8+
impl<T: Default, U: Default> Dyn<T, U> for () {}
9+
10+
trait Dyn<A, B>: Sup<A, Assoc = A> + Sup<B> {}
11+
12+
fn main() {
13+
let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default();
14+
//~^ ERROR the value of the associated type `Assoc` in `Sup<u32>` must be specified
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0191]: the value of the associated type `Assoc` in `Sup<u32>` must be specified
2+
--> $DIR/require-assoc-for-all-super-substs.rs:13:17
3+
|
4+
LL | type Assoc: Default;
5+
| ------------------- `Assoc` defined here
6+
...
7+
LL | let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default();
8+
| ^^^^^^^^^^^^^ help: specify the associated type: `Dyn<i32, u32, Assoc = Type>`
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0191`.

‎tests/ui/issues/issue-28344.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ help: if this is a dyn-compatible trait, use `dyn`
1212
LL | let x: u8 = <dyn BitXor>::bitor(0 as u8, 0 as u8);
1313
| ++++ +
1414

15-
error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
15+
error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified
1616
--> $DIR/issue-28344.rs:4:17
1717
|
1818
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
@@ -31,7 +31,7 @@ help: if this is a dyn-compatible trait, use `dyn`
3131
LL | let g = <dyn BitXor>::bitor;
3232
| ++++ +
3333

34-
error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
34+
error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified
3535
--> $DIR/issue-28344.rs:9:13
3636
|
3737
LL | let g = BitXor::bitor;

0 commit comments

Comments
 (0)
Failed to load comments.