Skip to content

Commit bb582c6

Browse files
Rollup merge of rust-lang#122123 - compiler-errors:object-trait-alias-bounds, r=oli-obk
Don't require specifying unrelated assoc types when trait alias is in `dyn` type Object types must specify the associated types for all of the principal trait ref's supertraits. However, we weren't doing elaboration properly, so we incorrectly errored with erroneous suggestions to specify associated types that were unrelated to that principal trait ref. To fix this, use proper supertrait elaboration when expanding trait aliases in `conv_object_ty_poly_trait_ref`. **NOTE**: Please use the ignore-whitespace option when reviewing. This only touches a handful of lines. r? oli-obk or please feel free to reassign. Fixes rust-lang#122118
2 parents 9bda4e4 + 850cc34 commit bb582c6

File tree

4 files changed

+55
-50
lines changed

4 files changed

+55
-50
lines changed

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+36-44
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4545
dummy_self,
4646
&mut bounds,
4747
false,
48-
// FIXME: This should be `true`, but we don't really handle
49-
// associated type bounds or type aliases in objects in a way
50-
// that makes this meaningful, I think.
51-
OnlySelfBounds(false),
48+
// True so we don't populate `bounds` with associated type bounds, even
49+
// though they're disallowed from object types.
50+
OnlySelfBounds(true),
5251
) {
5352
potential_assoc_types.extend(cur_potential_assoc_types);
5453
}
@@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
8382
let expanded_traits =
8483
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
8584

86-
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
87-
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
88-
.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
85+
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
86+
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
8987
if regular_traits.len() > 1 {
9088
let first_trait = &regular_traits[0];
9189
let additional_trait = &regular_traits[1];
@@ -158,7 +156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
158156

159157
for (base_trait_ref, span) in regular_traits_refs_spans {
160158
let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
161-
for pred in traits::elaborate(tcx, [base_pred]) {
159+
for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() {
162160
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
163161

164162
let bound_predicate = pred.kind();
@@ -312,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
312310
})
313311
});
314312

315-
let existential_projections = projection_bounds
316-
.iter()
317-
// We filter out traits that don't have `Self` as their self type above,
318-
// we need to do the same for projections.
319-
.filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
320-
.map(|(bound, _)| {
321-
bound.map_bound(|mut b| {
322-
assert_eq!(b.projection_ty.self_ty(), dummy_self);
313+
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
314+
bound.map_bound(|mut b| {
315+
assert_eq!(b.projection_ty.self_ty(), dummy_self);
323316

324-
// Like for trait refs, verify that `dummy_self` did not leak inside default type
325-
// parameters.
326-
let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
327-
if arg.walk().any(|arg| arg == dummy_self.into()) {
328-
return true;
329-
}
330-
false
331-
});
332-
if references_self {
333-
let guar = tcx.dcx().span_delayed_bug(
334-
span,
335-
"trait object projection bounds reference `Self`",
336-
);
337-
let args: Vec<_> = b
338-
.projection_ty
339-
.args
340-
.iter()
341-
.map(|arg| {
342-
if arg.walk().any(|arg| arg == dummy_self.into()) {
343-
return Ty::new_error(tcx, guar).into();
344-
}
345-
arg
346-
})
347-
.collect();
348-
b.projection_ty.args = tcx.mk_args(&args);
317+
// Like for trait refs, verify that `dummy_self` did not leak inside default type
318+
// parameters.
319+
let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
320+
if arg.walk().any(|arg| arg == dummy_self.into()) {
321+
return true;
349322
}
323+
false
324+
});
325+
if references_self {
326+
let guar = tcx
327+
.dcx()
328+
.span_delayed_bug(span, "trait object projection bounds reference `Self`");
329+
let args: Vec<_> = b
330+
.projection_ty
331+
.args
332+
.iter()
333+
.map(|arg| {
334+
if arg.walk().any(|arg| arg == dummy_self.into()) {
335+
return Ty::new_error(tcx, guar).into();
336+
}
337+
arg
338+
})
339+
.collect();
340+
b.projection_ty.args = tcx.mk_args(&args);
341+
}
350342

351-
ty::ExistentialProjection::erase_self_ty(tcx, b)
352-
})
353-
});
343+
ty::ExistentialProjection::erase_self_ty(tcx, b)
344+
})
345+
});
354346

355347
let regular_trait_predicates = existential_trait_refs
356348
.map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));

compiler/rustc_trait_selection/src/traits/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
127127
}
128128

129129
// Get components of trait alias.
130-
let predicates = tcx.implied_predicates_of(trait_ref.def_id());
130+
let predicates = tcx.super_predicates_of(trait_ref.def_id());
131131
debug!(?predicates);
132132

133133
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {

tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
error[E0191]: the value of the associated types `Item`, `Item`, `IntoIter` and `IntoIter` in `IntoIterator` must be specified
1+
error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIterator` must be specified
22
--> $DIR/overlaping-bound-suggestion.rs:7:13
33
|
44
LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
| | |
7-
| | associated types `Item`, `IntoIter` must be specified
8-
| associated types `Item`, `IntoIter` must be specified
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>`
96

107
error[E0223]: ambiguous associated type
118
--> $DIR/overlaping-bound-suggestion.rs:7:13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ check-pass
2+
3+
#![feature(trait_alias)]
4+
5+
trait Foo<T> {}
6+
trait Bar { type Assoc; }
7+
8+
trait Alias<T: Bar> = Foo<T>;
9+
10+
// Check that an alias only requires us to specify the associated types
11+
// of the principal's supertraits. For example, we shouldn't require
12+
// specifying the type `Assoc` on trait `Bar` just because we have some
13+
// `T: Bar` where clause on the alias... because that makes no sense.
14+
fn use_alias<T: Bar>(x: &dyn Alias<T>) {}
15+
16+
fn main() {}

0 commit comments

Comments
 (0)