Rollup merge of #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 #122118
This commit is contained in:
commit
bb582c6d0f
4 changed files with 55 additions and 50 deletions
|
@ -45,10 +45,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
dummy_self,
|
dummy_self,
|
||||||
&mut bounds,
|
&mut bounds,
|
||||||
false,
|
false,
|
||||||
// FIXME: This should be `true`, but we don't really handle
|
// True so we don't populate `bounds` with associated type bounds, even
|
||||||
// associated type bounds or type aliases in objects in a way
|
// though they're disallowed from object types.
|
||||||
// that makes this meaningful, I think.
|
OnlySelfBounds(true),
|
||||||
OnlySelfBounds(false),
|
|
||||||
) {
|
) {
|
||||||
potential_assoc_types.extend(cur_potential_assoc_types);
|
potential_assoc_types.extend(cur_potential_assoc_types);
|
||||||
}
|
}
|
||||||
|
@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
let expanded_traits =
|
let expanded_traits =
|
||||||
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
|
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
|
||||||
|
|
||||||
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
|
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
|
||||||
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
|
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
|
||||||
.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
|
|
||||||
if regular_traits.len() > 1 {
|
if regular_traits.len() > 1 {
|
||||||
let first_trait = ®ular_traits[0];
|
let first_trait = ®ular_traits[0];
|
||||||
let additional_trait = ®ular_traits[1];
|
let additional_trait = ®ular_traits[1];
|
||||||
|
@ -158,7 +156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
|
|
||||||
for (base_trait_ref, span) in regular_traits_refs_spans {
|
for (base_trait_ref, span) in regular_traits_refs_spans {
|
||||||
let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
|
let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
|
||||||
for pred in traits::elaborate(tcx, [base_pred]) {
|
for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() {
|
||||||
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
|
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
|
||||||
|
|
||||||
let bound_predicate = pred.kind();
|
let bound_predicate = pred.kind();
|
||||||
|
@ -312,12 +310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let existential_projections = projection_bounds
|
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
||||||
.iter()
|
|
||||||
// We filter out traits that don't have `Self` as their self type above,
|
|
||||||
// we need to do the same for projections.
|
|
||||||
.filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
|
|
||||||
.map(|(bound, _)| {
|
|
||||||
bound.map_bound(|mut b| {
|
bound.map_bound(|mut b| {
|
||||||
assert_eq!(b.projection_ty.self_ty(), dummy_self);
|
assert_eq!(b.projection_ty.self_ty(), dummy_self);
|
||||||
|
|
||||||
|
@ -330,10 +323,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
if references_self {
|
if references_self {
|
||||||
let guar = tcx.dcx().span_delayed_bug(
|
let guar = tcx
|
||||||
span,
|
.dcx()
|
||||||
"trait object projection bounds reference `Self`",
|
.span_delayed_bug(span, "trait object projection bounds reference `Self`");
|
||||||
);
|
|
||||||
let args: Vec<_> = b
|
let args: Vec<_> = b
|
||||||
.projection_ty
|
.projection_ty
|
||||||
.args
|
.args
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get components of trait alias.
|
// Get components of trait alias.
|
||||||
let predicates = tcx.implied_predicates_of(trait_ref.def_id());
|
let predicates = tcx.super_predicates_of(trait_ref.def_id());
|
||||||
debug!(?predicates);
|
debug!(?predicates);
|
||||||
|
|
||||||
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
|
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
error[E0191]: the value of the associated types `Item`, `Item`, `IntoIter` and `IntoIter` in `IntoIterator` must be specified
|
error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIterator` must be specified
|
||||||
--> $DIR/overlaping-bound-suggestion.rs:7:13
|
--> $DIR/overlaping-bound-suggestion.rs:7:13
|
||||||
|
|
|
|
||||||
LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
|
LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>`
|
||||||
| | |
|
|
||||||
| | associated types `Item`, `IntoIter` must be specified
|
|
||||||
| associated types `Item`, `IntoIter` must be specified
|
|
||||||
|
|
||||||
error[E0223]: ambiguous associated type
|
error[E0223]: ambiguous associated type
|
||||||
--> $DIR/overlaping-bound-suggestion.rs:7:13
|
--> $DIR/overlaping-bound-suggestion.rs:7:13
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(trait_alias)]
|
||||||
|
|
||||||
|
trait Foo<T> {}
|
||||||
|
trait Bar { type Assoc; }
|
||||||
|
|
||||||
|
trait Alias<T: Bar> = Foo<T>;
|
||||||
|
|
||||||
|
// Check that an alias only requires us to specify the associated types
|
||||||
|
// of the principal's supertraits. For example, we shouldn't require
|
||||||
|
// specifying the type `Assoc` on trait `Bar` just because we have some
|
||||||
|
// `T: Bar` where clause on the alias... because that makes no sense.
|
||||||
|
fn use_alias<T: Bar>(x: &dyn Alias<T>) {}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue