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 2a0ede8

Browse files
committedNov 27, 2024
Fix ICE when multiple supertrait substitutions need assoc but only one is provided
1 parent 81e2107 commit 2a0ede8

10 files changed

+78
-36
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

+30-20
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
717717
pub(crate) fn complain_about_missing_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
) {
@@ -726,24 +726,32 @@ 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 = false;
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() {
745-
report_dyn_incompatibility(tcx, principal_span, None, trait_def_id, &violations)
746-
.emit();
747+
report_dyn_incompatibility(
748+
tcx,
749+
principal_span,
750+
None,
751+
trait_ref.def_id(),
752+
&violations,
753+
)
754+
.emit();
747755
dyn_compatibility_violations = true;
748756
}
749757
}
@@ -791,6 +799,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
791799
.into_iter()
792800
.map(|(trait_, mut assocs)| {
793801
assocs.sort();
802+
let trait_ = trait_.print_trait_sugared();
794803
format!("{} in `{trait_}`", match &assocs[..] {
795804
[] => String::new(),
796805
[only] => format!("`{only}`"),
@@ -818,19 +827,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
818827
let mut already_has_generics_args_suggestion = false;
819828

820829
let mut names: UnordMap<_, usize> = Default::default();
821-
for item in &missing_assoc_types {
830+
for (item, _) in &missing_assoc_types {
822831
types_count += 1;
823832
*names.entry(item.name).or_insert(0) += 1;
824833
}
825834
let mut dupes = false;
826835
let mut shadows = false;
827-
for item in &missing_assoc_types {
836+
for (item, trait_ref) in &missing_assoc_types {
828837
let prefix = if names[&item.name] > 1 {
829-
let trait_def_id = item.container_id(tcx);
838+
let trait_def_id = trait_ref.def_id();
830839
dupes = true;
831840
format!("{}::", tcx.def_path_str(trait_def_id))
832841
} else if bound_names.get(&item.name).is_some_and(|x| *x != item) {
833-
let trait_def_id = item.container_id(tcx);
842+
let trait_def_id = trait_ref.def_id();
834843
shadows = true;
835844
format!("{}::", tcx.def_path_str(trait_def_id))
836845
} else {
@@ -869,8 +878,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
869878
} else if let (Ok(snippet), false, false) =
870879
(tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
871880
{
872-
let types: Vec<_> =
873-
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();
874885
let code = if snippet.ends_with('>') {
875886
// The user wrote `Trait<'a>` or similar and we don't have a type we can
876887
// suggest, but at least we can clue them to the correct syntax
@@ -902,15 +913,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
902913
if suggestions.len() != 1 || already_has_generics_args_suggestion {
903914
// We don't need this label if there's an inline suggestion, show otherwise.
904915
let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
905-
for item in &missing_assoc_types {
916+
for (item, _) in &missing_assoc_types {
906917
types_count += 1;
907918
*names.entry(item.name).or_insert(0) += 1;
908919
}
909920
let mut label = vec![];
910-
for item in &missing_assoc_types {
921+
for (item, trait_ref) in &missing_assoc_types {
911922
let postfix = if names[&item.name] > 1 {
912-
let trait_def_id = item.container_id(tcx);
913-
format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
923+
format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
914924
} else {
915925
String::new()
916926
};

‎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);
@@ -40,7 +40,7 @@ help: if this is a dyn-compatible trait, use `dyn`
4040
LL | let g = <dyn BitXor>::bitor;
4141
| ++++ +
4242

43-
error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
43+
error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified
4444
--> $DIR/issue-28344.rs:10:13
4545
|
4646
LL | let g = BitXor::bitor;

0 commit comments

Comments
 (0)
Failed to load comments.