mirror of https://github.com/rust-lang/rust.git
Don't require specifying unrelated assoc types when trait alias is in dyn type
This commit is contained in:
parent
7d3702e472
commit
850cc34da2
|
@ -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,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let existential_projections = projection_bounds
|
let existential_projections = projection_bounds.iter().map(|(bound, _)| {
|
||||||
.iter()
|
bound.map_bound(|mut b| {
|
||||||
// We filter out traits that don't have `Self` as their self type above,
|
assert_eq!(b.projection_ty.self_ty(), dummy_self);
|
||||||
// we need to do the same for projections.
|
|
||||||
.filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
|
|
||||||
.map(|(bound, _)| {
|
|
||||||
bound.map_bound(|mut b| {
|
|
||||||
assert_eq!(b.projection_ty.self_ty(), dummy_self);
|
|
||||||
|
|
||||||
// Like for trait refs, verify that `dummy_self` did not leak inside default type
|
// Like for trait refs, verify that `dummy_self` did not leak inside default type
|
||||||
// parameters.
|
// parameters.
|
||||||
let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
|
let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
|
||||||
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
false
|
|
||||||
});
|
|
||||||
if references_self {
|
|
||||||
let guar = tcx.dcx().span_delayed_bug(
|
|
||||||
span,
|
|
||||||
"trait object projection bounds reference `Self`",
|
|
||||||
);
|
|
||||||
let args: Vec<_> = b
|
|
||||||
.projection_ty
|
|
||||||
.args
|
|
||||||
.iter()
|
|
||||||
.map(|arg| {
|
|
||||||
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
|
||||||
return Ty::new_error(tcx, guar).into();
|
|
||||||
}
|
|
||||||
arg
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
b.projection_ty.args = tcx.mk_args(&args);
|
|
||||||
}
|
}
|
||||||
|
false
|
||||||
|
});
|
||||||
|
if references_self {
|
||||||
|
let guar = tcx
|
||||||
|
.dcx()
|
||||||
|
.span_delayed_bug(span, "trait object projection bounds reference `Self`");
|
||||||
|
let args: Vec<_> = b
|
||||||
|
.projection_ty
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|arg| {
|
||||||
|
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||||
|
return Ty::new_error(tcx, guar).into();
|
||||||
|
}
|
||||||
|
arg
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
b.projection_ty.args = tcx.mk_args(&args);
|
||||||
|
}
|
||||||
|
|
||||||
ty::ExistentialProjection::erase_self_ty(tcx, b)
|
ty::ExistentialProjection::erase_self_ty(tcx, b)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let regular_trait_predicates = existential_trait_refs
|
let regular_trait_predicates = existential_trait_refs
|
||||||
.map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
|
.map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
|
||||||
|
|
|
@ -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…
Reference in New Issue