1
Fork 0

Auto merge of #107614 - compiler-errors:allow-elaborator-to-filter-only-super-traits, r=oli-obk

Split implied and super predicate queries, then allow elaborator to filter only supertraits

Split the `super_predicates_of` query into a new `implied_predicates_of` query. The former now only returns the *real* supertraits of a trait alias, and the latter now returns the implied predicates (which include all of the `where` clauses of the trait alias). The behavior of these queries is identical for regular traits.

Now that the two queries are split, we can add a new filter method to the elaborator, `filter_only_self()`, which can be used in instances that we need only the *supertrait* predicates, such as during the elaboration used in closure signature deduction. This toggles the usage of `super_predicates_of` instead of `implied_predicates_of` during elaboration of a trait predicate.

This supersedes #104745, and fixes the four independent bugs identified in that PR.
Fixes #104719
Fixes #106238
Fixes #110023
Fixes #109514

r? types
This commit is contained in:
bors 2023-04-12 08:39:19 +00:00
commit 9be9b5e09a
28 changed files with 307 additions and 149 deletions

View file

@ -1663,7 +1663,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}) })
}); });
let existential_projections = projection_bounds.iter().map(|(bound, _)| { 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| { bound.map_bound(|mut b| {
assert_eq!(b.projection_ty.self_ty(), dummy_self); assert_eq!(b.projection_ty.self_ty(), dummy_self);
@ -1676,9 +1681,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
false false
}); });
if references_self { if references_self {
let guar = tcx let guar = tcx.sess.delay_span_bug(
.sess span,
.delay_span_bug(span, "trait object projection bounds reference `Self`"); "trait object projection bounds reference `Self`",
);
let substs: Vec<_> = b let substs: Vec<_> = b
.projection_ty .projection_ty
.substs .substs

View file

@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) {
predicates_defined_on, predicates_defined_on,
explicit_predicates_of: predicates_of::explicit_predicates_of, explicit_predicates_of: predicates_of::explicit_predicates_of,
super_predicates_of: predicates_of::super_predicates_of, super_predicates_of: predicates_of::super_predicates_of,
implied_predicates_of: predicates_of::implied_predicates_of,
super_predicates_that_define_assoc_type: super_predicates_that_define_assoc_type:
predicates_of::super_predicates_that_define_assoc_type, predicates_of::super_predicates_that_define_assoc_type,
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds, trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
@ -596,6 +597,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
} }
hir::ItemKind::TraitAlias(..) => { hir::ItemKind::TraitAlias(..) => {
tcx.ensure().generics_of(def_id); tcx.ensure().generics_of(def_id);
tcx.at(it.span).implied_predicates_of(def_id);
tcx.at(it.span).super_predicates_of(def_id); tcx.at(it.span).super_predicates_of(def_id);
tcx.ensure().predicates_of(def_id); tcx.ensure().predicates_of(def_id);
} }

View file

@ -125,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// on a trait we need to add in the supertrait bounds and bounds found on // on a trait we need to add in the supertrait bounds and bounds found on
// associated types. // associated types.
if let Some(_trait_ref) = is_trait { if let Some(_trait_ref) = is_trait {
predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
} }
// In default impls, we can assume that the self type implements // In default impls, we can assume that the self type implements
@ -534,6 +534,19 @@ pub(super) fn explicit_predicates_of<'tcx>(
} }
} }
#[derive(Copy, Clone, Debug)]
pub enum PredicateFilter {
/// All predicates may be implied by the trait
All,
/// Only traits that reference `Self: ..` are implied by the trait
SelfOnly,
/// Only traits that reference `Self: ..` and define an associated type
/// with the given ident are implied by the trait
SelfThatDefines(Ident),
}
/// Ensures that the super-predicates of the trait with a `DefId` /// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that /// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted. /// the transitive super-predicates are converted.
@ -541,24 +554,42 @@ pub(super) fn super_predicates_of(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
trait_def_id: LocalDefId, trait_def_id: LocalDefId,
) -> ty::GenericPredicates<'_> { ) -> ty::GenericPredicates<'_> {
tcx.super_predicates_that_define_assoc_type((trait_def_id.to_def_id(), None)) implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
}
pub(super) fn super_predicates_that_define_assoc_type(
tcx: TyCtxt<'_>,
(trait_def_id, assoc_name): (DefId, Ident),
) -> ty::GenericPredicates<'_> {
implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name))
}
pub(super) fn implied_predicates_of(
tcx: TyCtxt<'_>,
trait_def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
if tcx.is_trait_alias(trait_def_id.to_def_id()) {
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
} else {
tcx.super_predicates_of(trait_def_id)
}
} }
/// Ensures that the super-predicates of the trait with a `DefId` /// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that /// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted. /// the transitive super-predicates are converted.
pub(super) fn super_predicates_that_define_assoc_type( pub(super) fn implied_predicates_with_filter(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
(trait_def_id, assoc_name): (DefId, Option<Ident>), trait_def_id: DefId,
filter: PredicateFilter,
) -> ty::GenericPredicates<'_> { ) -> ty::GenericPredicates<'_> {
let Some(trait_def_id) = trait_def_id.as_local() else { let Some(trait_def_id) = trait_def_id.as_local() else {
// if `assoc_name` is None, then the query should've been redirected to an // if `assoc_name` is None, then the query should've been redirected to an
// external provider // external provider
assert!(assoc_name.is_some()); assert!(matches!(filter, PredicateFilter::SelfThatDefines(_)));
return tcx.super_predicates_of(trait_def_id); return tcx.super_predicates_of(trait_def_id);
}; };
debug!("local trait");
let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id); let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id);
let Node::Item(item) = tcx.hir().get(trait_hir_id) else { let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
@ -573,40 +604,58 @@ pub(super) fn super_predicates_that_define_assoc_type(
let icx = ItemCtxt::new(tcx, trait_def_id); let icx = ItemCtxt::new(tcx, trait_def_id);
// Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
let self_param_ty = tcx.types.self_param; let self_param_ty = tcx.types.self_param;
let superbounds1 = if let Some(assoc_name) = assoc_name { let (superbounds, where_bounds_that_match) = match filter {
icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name) PredicateFilter::All => (
} else { // Convert the bounds that follow the colon (or equal in trait aliases)
icx.astconv().compute_bounds(self_param_ty, bounds) icx.astconv().compute_bounds(self_param_ty, bounds),
}; // Also include all where clause bounds
icx.type_parameter_bounds_in_generics(
let superbounds1 = superbounds1.predicates();
// Convert any explicit superbounds in the where-clause,
// e.g., `trait Foo where Self: Bar`.
// In the case of trait aliases, however, we include all bounds in the where-clause,
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
// as one of its "superpredicates".
let is_trait_alias = tcx.is_trait_alias(trait_def_id.to_def_id());
let superbounds2 = icx.type_parameter_bounds_in_generics(
generics, generics,
item.owner_id.def_id, item.owner_id.def_id,
self_param_ty, self_param_ty,
OnlySelfBounds(!is_trait_alias), OnlySelfBounds(false),
assoc_name, None,
); ),
),
PredicateFilter::SelfOnly => (
// Convert the bounds that follow the colon (or equal in trait aliases)
icx.astconv().compute_bounds(self_param_ty, bounds),
// Include where clause bounds for `Self`
icx.type_parameter_bounds_in_generics(
generics,
item.owner_id.def_id,
self_param_ty,
OnlySelfBounds(true),
None,
),
),
PredicateFilter::SelfThatDefines(assoc_name) => (
// Convert the bounds that follow the colon (or equal) that reference the associated name
icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
// Include where clause bounds for `Self` that reference the associated name
icx.type_parameter_bounds_in_generics(
generics,
item.owner_id.def_id,
self_param_ty,
OnlySelfBounds(true),
Some(assoc_name),
),
),
};
// Combine the two lists to form the complete set of superbounds: // Combine the two lists to form the complete set of superbounds:
let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2)); let implied_bounds = &*tcx
debug!(?superbounds); .arena
.alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match));
debug!(?implied_bounds);
// Now require that immediate supertraits are converted, // Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits. // which will, in turn, reach indirect supertraits.
if assoc_name.is_none() { if matches!(filter, PredicateFilter::SelfOnly) {
// Now require that immediate supertraits are converted, // Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits. // which will, in turn, reach indirect supertraits.
for &(pred, span) in superbounds { for &(pred, span) in implied_bounds {
debug!("superbound: {:?}", pred); debug!("superbound: {:?}", pred);
if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() { if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() {
tcx.at(span).super_predicates_of(bound.def_id()); tcx.at(span).super_predicates_of(bound.def_id());
@ -614,7 +663,7 @@ pub(super) fn super_predicates_that_define_assoc_type(
} }
} }
ty::GenericPredicates { parent: None, predicates: superbounds } ty::GenericPredicates { parent: None, predicates: implied_bounds }
} }
/// Returns the predicates defined on `item_def_id` of the form /// Returns the predicates defined on `item_def_id` of the form

View file

@ -1749,8 +1749,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
if trait_defines_associated_type_named(def_id) { if trait_defines_associated_type_named(def_id) {
break Some(bound_vars.into_iter().collect()); break Some(bound_vars.into_iter().collect());
} }
let predicates = let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
let bound_predicate = pred.kind(); let bound_predicate = pred.kind();
match bound_predicate.skip_binder() { match bound_predicate.skip_binder() {

View file

@ -210,7 +210,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// and we want to keep inference generally in the same order of // and we want to keep inference generally in the same order of
// the registered obligations. // the registered obligations.
predicates.rev(), predicates.rev(),
) { )
// We only care about self bounds
.filter_only_self()
{
debug!(?pred); debug!(?pred);
let bound_predicate = pred.kind(); let bound_predicate = pred.kind();

View file

@ -69,6 +69,7 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
pub struct Elaborator<'tcx, O> { pub struct Elaborator<'tcx, O> {
stack: Vec<O>, stack: Vec<O>,
visited: PredicateSet<'tcx>, visited: PredicateSet<'tcx>,
only_self: bool,
} }
/// Describes how to elaborate an obligation into a sub-obligation. /// Describes how to elaborate an obligation into a sub-obligation.
@ -170,7 +171,8 @@ pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
obligations: impl IntoIterator<Item = O>, obligations: impl IntoIterator<Item = O>,
) -> Elaborator<'tcx, O> { ) -> Elaborator<'tcx, O> {
let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) }; let mut elaborator =
Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx), only_self: false };
elaborator.extend_deduped(obligations); elaborator.extend_deduped(obligations);
elaborator elaborator
} }
@ -185,14 +187,25 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate()))); self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate())));
} }
/// Filter to only the supertraits of trait predicates, i.e. only the predicates
/// that have `Self` as their self type, instead of all implied predicates.
pub fn filter_only_self(mut self) -> Self {
self.only_self = true;
self
}
fn elaborate(&mut self, elaboratable: &O) { fn elaborate(&mut self, elaboratable: &O) {
let tcx = self.visited.tcx; let tcx = self.visited.tcx;
let bound_predicate = elaboratable.predicate().kind(); let bound_predicate = elaboratable.predicate().kind();
match bound_predicate.skip_binder() { match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
// Get predicates declared on the trait. // Get predicates implied by the trait, or only super predicates if we only care about self predicates.
let predicates = tcx.super_predicates_of(data.def_id()); let predicates = if self.only_self {
tcx.super_predicates_of(data.def_id())
} else {
tcx.implied_predicates_of(data.def_id())
};
let obligations = let obligations =
predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| { predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| {
@ -350,18 +363,16 @@ pub fn supertraits<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> { ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx); elaborate(tcx, [trait_ref.to_predicate(tcx)]).filter_only_self().filter_to_traits()
FilterToTraits::new(elaborate(tcx, [pred]))
} }
pub fn transitive_bounds<'tcx>( pub fn transitive_bounds<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> { ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
FilterToTraits::new(elaborate( elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx)))
tcx, .filter_only_self()
trait_refs.map(|trait_ref| -> ty::Predicate<'tcx> { trait_ref.to_predicate(tcx) }), .filter_to_traits()
))
} }
/// A specialized variant of `elaborate` that only elaborates trait references that may /// A specialized variant of `elaborate` that only elaborates trait references that may
@ -381,10 +392,8 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
while let Some(trait_ref) = stack.pop() { while let Some(trait_ref) = stack.pop() {
let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref); let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref);
if visited.insert(anon_trait_ref) { if visited.insert(anon_trait_ref) {
let super_predicates = tcx.super_predicates_that_define_assoc_type(( let super_predicates =
trait_ref.def_id(), tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), assoc_name));
Some(assoc_name),
));
for (super_predicate, _) in super_predicates.predicates { for (super_predicate, _) in super_predicates.predicates {
let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() {
@ -404,18 +413,18 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
// Other // Other
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
impl<'tcx> Elaborator<'tcx, ty::Predicate<'tcx>> {
fn filter_to_traits(self) -> FilterToTraits<Self> {
FilterToTraits { base_iterator: self }
}
}
/// A filter around an iterator of predicates that makes it yield up /// A filter around an iterator of predicates that makes it yield up
/// just trait references. /// just trait references.
pub struct FilterToTraits<I> { pub struct FilterToTraits<I> {
base_iterator: I, base_iterator: I,
} }
impl<I> FilterToTraits<I> {
fn new(base: I) -> FilterToTraits<I> {
FilterToTraits { base_iterator: base }
}
}
impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> { impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
type Item = ty::PolyTraitRef<'tcx>; type Item = ty::PolyTraitRef<'tcx>;

View file

@ -255,6 +255,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned()) elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned())
// We only care about self bounds for the impl-trait
.filter_only_self()
.find_map(|(pred, _span)| { .find_map(|(pred, _span)| {
// We only look at the `DefId`, so it is safe to skip the binder here. // We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Clause(ty::Clause::Trait( if let ty::PredicateKind::Clause(ty::Clause::Trait(

View file

@ -254,6 +254,18 @@ provide! { tcx, def_id, other, cdata,
.map(|lazy| lazy.decode((cdata, tcx))) .map(|lazy| lazy.decode((cdata, tcx)))
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys"))) .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
} }
implied_predicates_of => {
cdata
.root
.tables
.implied_predicates_of
.get(cdata, def_id.index)
.map(|lazy| lazy.decode((cdata, tcx)))
.unwrap_or_else(|| {
debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
tcx.super_predicates_of(def_id)
})
}
associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array } associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }

View file

@ -1316,9 +1316,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let default = self.tcx.object_lifetime_default(def_id); let default = self.tcx.object_lifetime_default(def_id);
record!(self.tables.object_lifetime_default[def_id] <- default); record!(self.tables.object_lifetime_default[def_id] <- default);
} }
if let DefKind::Trait | DefKind::TraitAlias = def_kind { if let DefKind::Trait = def_kind {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
} }
if let DefKind::TraitAlias = def_kind {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
record!(self.tables.implied_predicates_of[def_id] <- self.tcx.implied_predicates_of(def_id));
}
if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
self.encode_info_for_adt(def_id); self.encode_info_for_adt(def_id);
} }

View file

@ -372,6 +372,9 @@ define_tables! {
explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>, explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
generics_of: Table<DefIndex, LazyValue<ty::Generics>>, generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>, super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
// As an optimization, we only store this for trait aliases,
// since it's identical to super_predicates_of for traits.
implied_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<Ty<'static>>>>, type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<Ty<'static>>>>,
variances_of: Table<DefIndex, LazyArray<ty::Variance>>, variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
@ -383,7 +386,6 @@ define_tables! {
mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>, mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>, mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>,
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>, promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
// FIXME(compiler-errors): Why isn't this a LazyArray?
thir_abstract_const: Table<DefIndex, LazyValue<ty::Const<'static>>>, thir_abstract_const: Table<DefIndex, LazyValue<ty::Const<'static>>>,
impl_parent: Table<DefIndex, RawDefId>, impl_parent: Table<DefIndex, RawDefId>,
impl_polarity: Table<DefIndex, ty::ImplPolarity>, impl_polarity: Table<DefIndex, ty::ImplPolarity>,

View file

@ -230,7 +230,7 @@ impl Key for (LocalDefId, LocalDefId) {
} }
} }
impl Key for (DefId, Option<Ident>) { impl Key for (DefId, Ident) {
type CacheSelector = DefaultCacheSelector<Self>; type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span { fn default_span(&self, tcx: TyCtxt<'_>) -> Span {

View file

@ -627,14 +627,20 @@ rustc_queries! {
separate_provide_extern separate_provide_extern
} }
query implied_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
/// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query /// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the /// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
/// subset of super-predicates that reference traits that define the given associated type. /// subset of super-predicates that reference traits that define the given associated type.
/// This is used to avoid cycles in resolving types like `T::Item`. /// This is used to avoid cycles in resolving types like `T::Item`.
query super_predicates_that_define_assoc_type(key: (DefId, Option<rustc_span::symbol::Ident>)) -> ty::GenericPredicates<'tcx> { query super_predicates_that_define_assoc_type(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the super traits of `{}`{}", desc { |tcx| "computing the super traits of `{}` with associated type name `{}`",
tcx.def_path_str(key.0), tcx.def_path_str(key.0),
if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() }, key.1
} }
} }

View file

@ -505,7 +505,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
let own_bounds: FxIndexSet<_> = let own_bounds: FxIndexSet<_> =
bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect(); bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect();
for assumption in elaborate(tcx, own_bounds.iter().copied()) { for assumption in elaborate(tcx, own_bounds.iter().copied())
// we only care about bounds that match the `Self` type
.filter_only_self()
{
// FIXME: Predicates are fully elaborated in the object type's existential bounds // FIXME: Predicates are fully elaborated in the object type's existential bounds
// list. We want to only consider these pre-elaborated projections, and not other // list. We want to only consider these pre-elaborated projections, and not other
// projection predicates that we reach by elaborating the principal trait ref, // projection predicates that we reach by elaborating the principal trait ref,

View file

@ -115,7 +115,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
} }
// Get components of trait alias. // Get components of trait alias.
let predicates = tcx.super_predicates_of(trait_ref.def_id()); let predicates = tcx.implied_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)| {

View file

@ -5,7 +5,7 @@ LL | trait Baz: Foo + Bar<Self::Item> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: ...which immediately requires computing the super traits of `Baz` with associated type name `Item` again = note: ...which immediately requires computing the super traits of `Baz` with associated type name `Item` again
note: cycle used when computing the super traits of `Baz` note: cycle used when computing the super predicates of `Baz`
--> $DIR/ambiguous-associated-type2.rs:7:1 --> $DIR/ambiguous-associated-type2.rs:7:1
| |
LL | trait Baz: Foo + Bar<Self::Item> {} LL | trait Baz: Foo + Bar<Self::Item> {}

View file

@ -5,7 +5,7 @@ LL | pub trait Processor: Subscriber<Input = Self::Input> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: ...which immediately requires computing the super traits of `Processor` with associated type name `Input` again = note: ...which immediately requires computing the super traits of `Processor` with associated type name `Input` again
note: cycle used when computing the super traits of `Processor` note: cycle used when computing the super predicates of `Processor`
--> $DIR/issue-20825.rs:5:1 --> $DIR/issue-20825.rs:5:1
| |
LL | pub trait Processor: Subscriber<Input = Self::Input> { LL | pub trait Processor: Subscriber<Input = Self::Input> {

View file

@ -0,0 +1,14 @@
// check-pass
// Makes sure that we only consider `Self` supertrait predicates while
// elaborating during closure signature deduction.
#![feature(trait_alias)]
trait Confusing<F> = Fn(i32) where F: Fn(u32);
fn alias<T: Confusing<F>, F>(_: T, _: F) {}
fn main() {
alias(|_| {}, |_| {});
}

View file

@ -1,15 +1,10 @@
error[E0391]: cycle detected when computing the super predicates of `Chromosome` error[E0391]: cycle detected when computing the super predicates of `Chromosome`
--> $DIR/cycle-trait-supertrait-direct.rs:3:1
|
LL | trait Chromosome: Chromosome {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires computing the super traits of `Chromosome`...
--> $DIR/cycle-trait-supertrait-direct.rs:3:19 --> $DIR/cycle-trait-supertrait-direct.rs:3:19
| |
LL | trait Chromosome: Chromosome { LL | trait Chromosome: Chromosome {
| ^^^^^^^^^^ | ^^^^^^^^^^
= note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle |
= note: ...which immediately requires computing the super predicates of `Chromosome` again
note: cycle used when collecting item types in top-level module note: cycle used when collecting item types in top-level module
--> $DIR/cycle-trait-supertrait-direct.rs:3:1 --> $DIR/cycle-trait-supertrait-direct.rs:3:1
| |

View file

@ -1,26 +1,16 @@
error[E0391]: cycle detected when computing the super predicates of `B` error[E0391]: cycle detected when computing the super predicates of `B`
--> $DIR/cycle-trait-supertrait-indirect.rs:7:1
|
LL | trait B: C {
| ^^^^^^^^^^
|
note: ...which requires computing the super traits of `B`...
--> $DIR/cycle-trait-supertrait-indirect.rs:7:10 --> $DIR/cycle-trait-supertrait-indirect.rs:7:10
| |
LL | trait B: C { LL | trait B: C {
| ^ | ^
note: ...which requires computing the super predicates of `C`...
--> $DIR/cycle-trait-supertrait-indirect.rs:11:1
| |
LL | trait C: B { } note: ...which requires computing the super predicates of `C`...
| ^^^^^^^^^^
note: ...which requires computing the super traits of `C`...
--> $DIR/cycle-trait-supertrait-indirect.rs:11:10 --> $DIR/cycle-trait-supertrait-indirect.rs:11:10
| |
LL | trait C: B { } LL | trait C: B { }
| ^ | ^
= note: ...which again requires computing the super predicates of `B`, completing the cycle = note: ...which again requires computing the super predicates of `B`, completing the cycle
note: cycle used when computing the super traits of `A` note: cycle used when computing the super predicates of `A`
--> $DIR/cycle-trait-supertrait-indirect.rs:4:10 --> $DIR/cycle-trait-supertrait-indirect.rs:4:10
| |
LL | trait A: B { LL | trait A: B {

View file

@ -1,30 +1,15 @@
error[E0391]: cycle detected when computing the super predicates of `T1` error[E0391]: cycle detected when computing the super predicates of `T1`
--> $DIR/infinite-trait-alias-recursion.rs:3:1
|
LL | trait T1 = T2;
| ^^^^^^^^
|
note: ...which requires computing the super traits of `T1`...
--> $DIR/infinite-trait-alias-recursion.rs:3:12 --> $DIR/infinite-trait-alias-recursion.rs:3:12
| |
LL | trait T1 = T2; LL | trait T1 = T2;
| ^^ | ^^
note: ...which requires computing the super predicates of `T2`...
--> $DIR/infinite-trait-alias-recursion.rs:6:1
| |
LL | trait T2 = T3; note: ...which requires computing the super predicates of `T2`...
| ^^^^^^^^
note: ...which requires computing the super traits of `T2`...
--> $DIR/infinite-trait-alias-recursion.rs:6:12 --> $DIR/infinite-trait-alias-recursion.rs:6:12
| |
LL | trait T2 = T3; LL | trait T2 = T3;
| ^^ | ^^
note: ...which requires computing the super predicates of `T3`... note: ...which requires computing the super predicates of `T3`...
--> $DIR/infinite-trait-alias-recursion.rs:8:1
|
LL | trait T3 = T1 + T3;
| ^^^^^^^^
note: ...which requires computing the super traits of `T3`...
--> $DIR/infinite-trait-alias-recursion.rs:8:12 --> $DIR/infinite-trait-alias-recursion.rs:8:12
| |
LL | trait T3 = T1 + T3; LL | trait T3 = T1 + T3;

View file

@ -1,20 +1,10 @@
error[E0391]: cycle detected when computing the super predicates of `T1` error[E0391]: cycle detected when computing the super predicates of `T1`
--> $DIR/issue-12511.rs:1:1
|
LL | trait T1 : T2 {
| ^^^^^^^^^^^^^
|
note: ...which requires computing the super traits of `T1`...
--> $DIR/issue-12511.rs:1:12 --> $DIR/issue-12511.rs:1:12
| |
LL | trait T1 : T2 { LL | trait T1 : T2 {
| ^^ | ^^
note: ...which requires computing the super predicates of `T2`...
--> $DIR/issue-12511.rs:5:1
| |
LL | trait T2 : T1 { note: ...which requires computing the super predicates of `T2`...
| ^^^^^^^^^^^^^
note: ...which requires computing the super traits of `T2`...
--> $DIR/issue-12511.rs:5:12 --> $DIR/issue-12511.rs:5:12
| |
LL | trait T2 : T1 { LL | trait T2 : T1 {

View file

@ -5,7 +5,7 @@ LL | trait T : Iterator<Item=Self::Item>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: ...which immediately requires computing the super traits of `T` with associated type name `Item` again = note: ...which immediately requires computing the super traits of `T` with associated type name `Item` again
note: cycle used when computing the super traits of `T` note: cycle used when computing the super predicates of `T`
--> $DIR/issue-20772.rs:1:1 --> $DIR/issue-20772.rs:1:1
| |
LL | trait T : Iterator<Item=Self::Item> LL | trait T : Iterator<Item=Self::Item>

View file

@ -0,0 +1,15 @@
// check-pass
// Make sure that we only consider *Self* supertrait predicates
// in the `unused_must_use` lint.
#![feature(trait_alias)]
#![deny(unused_must_use)]
trait Foo<T> = Sized where T: Iterator;
fn test<T: Iterator>() -> impl Foo<T> {}
fn main() {
test::<std::iter::Once<()>>();
}

View file

@ -0,0 +1,10 @@
#![feature(trait_alias)]
use std::future::Future;
trait F<Fut: Future<Output = usize>> = Fn() -> Fut;
fn f<Fut>(a: dyn F<Fut>) {}
//~^ ERROR the size for values of type `(dyn Fn() -> Fut + 'static)` cannot be known at compilation time
fn main() {}

View file

@ -0,0 +1,20 @@
error[E0277]: the size for values of type `(dyn Fn() -> Fut + 'static)` cannot be known at compilation time
--> $DIR/dont-elaborate-non-self.rs:7:11
|
LL | fn f<Fut>(a: dyn F<Fut>) {}
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Fn() -> Fut + 'static)`
= help: unsized fn params are gated as an unstable feature
help: you can use `impl Trait` as the argument type
|
LL | fn f<Fut>(a: impl F<Fut>) {}
| ~~~~
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | fn f<Fut>(a: &dyn F<Fut>) {}
| +
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,33 @@
#![feature(trait_upcasting)]
#![feature(trait_alias)]
// Although we *elaborate* `T: Alias` to `i32: B`, we should
// not consider `B` to be a supertrait of the type.
trait Alias = A where i32: B;
trait A {}
trait B {
fn test(&self);
}
trait C: Alias {}
impl A for () {}
impl C for () {}
impl B for i32 {
fn test(&self) {
println!("hi {self}");
}
}
fn test(x: &dyn C) -> &dyn B {
x
//~^ ERROR mismatched types
}
fn main() {
let x: &dyn C = &();
}

View file

@ -0,0 +1,14 @@
error[E0308]: mismatched types
--> $DIR/alias-where-clause-isnt-supertrait.rs:27:5
|
LL | fn test(x: &dyn C) -> &dyn B {
| ------ expected `&dyn B` because of return type
LL | x
| ^ expected trait `B`, found trait `C`
|
= note: expected reference `&dyn B`
found reference `&dyn C`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,15 +1,10 @@
error[E0391]: cycle detected when computing the super predicates of `A` error[E0391]: cycle detected when computing the super predicates of `A`
--> $DIR/cyclic-trait-resolution.rs:1:1
|
LL | trait A: B + A {}
| ^^^^^^^^^^^^^^
|
note: ...which requires computing the super traits of `A`...
--> $DIR/cyclic-trait-resolution.rs:1:14 --> $DIR/cyclic-trait-resolution.rs:1:14
| |
LL | trait A: B + A {} LL | trait A: B + A {}
| ^ | ^
= note: ...which again requires computing the super predicates of `A`, completing the cycle |
= note: ...which immediately requires computing the super predicates of `A` again
note: cycle used when collecting item types in top-level module note: cycle used when collecting item types in top-level module
--> $DIR/cyclic-trait-resolution.rs:1:1 --> $DIR/cyclic-trait-resolution.rs:1:1
| |