Skip to content

Commit

Permalink
Unrolled build for rust-lang#122123
Browse files Browse the repository at this point in the history
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
  • Loading branch information
rust-timer committed Mar 7, 2024
2 parents 52f8aec + 850cc34 commit 1ea23b3
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 50 deletions.
80 changes: 36 additions & 44 deletions compiler/rustc_hir_analysis/src/astconv/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
dummy_self,
&mut bounds,
false,
// FIXME: This should be `true`, but we don't really handle
// associated type bounds or type aliases in objects in a way
// that makes this meaningful, I think.
OnlySelfBounds(false),
// True so we don't populate `bounds` with associated type bounds, even
// though they're disallowed from object types.
OnlySelfBounds(true),
) {
potential_assoc_types.extend(cur_potential_assoc_types);
}
Expand Down Expand Up @@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let expanded_traits =
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));

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

for (base_trait_ref, span) in regular_traits_refs_spans {
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);

let bound_predicate = pred.kind();
Expand Down Expand Up @@ -312,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
})
});

let existential_projections = projection_bounds
.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| {
assert_eq!(b.projection_ty.self_ty(), dummy_self);
let existential_projections = projection_bounds.iter().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
// parameters.
let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
if arg.walk().any(|arg| arg == dummy_self.into()) {
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);
// Like for trait refs, verify that `dummy_self` did not leak inside default type
// parameters.
let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
if arg.walk().any(|arg| arg == dummy_self.into()) {
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);
}

ty::ExistentialProjection::erase_self_ty(tcx, b)
})
});
ty::ExistentialProjection::erase_self_ty(tcx, b)
})
});

let regular_trait_predicates = existential_trait_refs
.map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
}

// 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);

let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
|
LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | associated types `Item`, `IntoIter` must be specified
| associated types `Item`, `IntoIter` must be specified
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>`

error[E0223]: ambiguous associated type
--> $DIR/overlaping-bound-suggestion.rs:7:13
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/traits/alias/only-require-assocs-from-supertraits.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 1ea23b3

Please sign in to comment.