Skip to content

Commit 850cc34

Browse files
Don't require specifying unrelated assoc types when trait alias is in dyn type
1 parent 7d3702e commit 850cc34

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)