1
Fork 0

Split item bounds and item super predicates

This commit is contained in:
Michael Goulet 2024-03-20 12:52:48 -04:00
parent a128516cf9
commit aa39dbb962
20 changed files with 186 additions and 46 deletions

View file

@ -716,7 +716,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.copied() .copied()
.find_map(find_fn_kind_from_did), .find_map(find_fn_kind_from_did),
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
.explicit_item_bounds(def_id) .explicit_item_super_predicates(def_id)
.iter_instantiated_copied(tcx, args) .iter_instantiated_copied(tcx, args)
.find_map(|(clause, span)| find_fn_kind_from_did((clause, span))), .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
ty::Closure(_, args) => match args.as_closure().kind() { ty::Closure(_, args) => match args.as_closure().kind() {

View file

@ -431,7 +431,7 @@ fn fn_sig_suggestion<'tcx>(
let asyncness = if tcx.asyncness(assoc.def_id).is_async() { let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
output = if let ty::Alias(_, alias_ty) = *output.kind() { output = if let ty::Alias(_, alias_ty) = *output.kind() {
tcx.explicit_item_bounds(alias_ty.def_id) tcx.explicit_item_super_predicates(alias_ty.def_id)
.iter_instantiated_copied(tcx, alias_ty.args) .iter_instantiated_copied(tcx, alias_ty.args)
.find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty()) .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
.unwrap_or_else(|| { .unwrap_or_else(|| {

View file

@ -61,6 +61,9 @@ pub fn provide(providers: &mut Providers) {
type_alias_is_lazy: type_of::type_alias_is_lazy, type_alias_is_lazy: type_of::type_alias_is_lazy,
item_bounds: item_bounds::item_bounds, item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds, explicit_item_bounds: item_bounds::explicit_item_bounds,
item_super_predicates: item_bounds::item_super_predicates,
explicit_item_super_predicates: item_bounds::explicit_item_super_predicates,
item_non_self_assumptions: item_bounds::item_non_self_assumptions,
generics_of: generics_of::generics_of, generics_of: generics_of::generics_of,
predicates_of: predicates_of::predicates_of, predicates_of: predicates_of::predicates_of,
predicates_defined_on, predicates_defined_on,
@ -633,7 +636,9 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
tcx.ensure().generics_of(def_id); tcx.ensure().generics_of(def_id);
tcx.ensure().predicates_of(def_id); tcx.ensure().predicates_of(def_id);
tcx.ensure().explicit_item_bounds(def_id); tcx.ensure().explicit_item_bounds(def_id);
tcx.ensure().explicit_item_super_predicates(def_id);
tcx.ensure().item_bounds(def_id); tcx.ensure().item_bounds(def_id);
tcx.ensure().item_super_predicates(def_id);
} }
hir::ItemKind::TyAlias(..) => { hir::ItemKind::TyAlias(..) => {
@ -689,6 +694,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
hir::TraitItemKind::Type(_, Some(_)) => { hir::TraitItemKind::Type(_, Some(_)) => {
tcx.ensure().item_bounds(def_id); tcx.ensure().item_bounds(def_id);
tcx.ensure().item_super_predicates(def_id);
tcx.ensure().type_of(def_id); tcx.ensure().type_of(def_id);
// Account for `type T = _;`. // Account for `type T = _;`.
let mut visitor = HirPlaceholderCollector::default(); let mut visitor = HirPlaceholderCollector::default();
@ -698,6 +704,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
hir::TraitItemKind::Type(_, None) => { hir::TraitItemKind::Type(_, None) => {
tcx.ensure().item_bounds(def_id); tcx.ensure().item_bounds(def_id);
tcx.ensure().item_super_predicates(def_id);
// #74612: Visit and try to find bad placeholders // #74612: Visit and try to find bad placeholders
// even if there is no concrete type. // even if there is no concrete type.
let mut visitor = HirPlaceholderCollector::default(); let mut visitor = HirPlaceholderCollector::default();

View file

@ -1,5 +1,6 @@
use super::ItemCtxt; use super::ItemCtxt;
use crate::astconv::{AstConv, PredicateFilter}; use crate::astconv::{AstConv, PredicateFilter};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::traits::util; use rustc_infer::traits::util;
use rustc_middle::ty::GenericArgs; use rustc_middle::ty::GenericArgs;
@ -19,6 +20,7 @@ fn associated_type_bounds<'tcx>(
assoc_item_def_id: LocalDefId, assoc_item_def_id: LocalDefId,
ast_bounds: &'tcx [hir::GenericBound<'tcx>], ast_bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span, span: Span,
filter: PredicateFilter,
) -> &'tcx [(ty::Clause<'tcx>, Span)] { ) -> &'tcx [(ty::Clause<'tcx>, Span)] {
let item_ty = Ty::new_projection( let item_ty = Ty::new_projection(
tcx, tcx,
@ -27,7 +29,7 @@ fn associated_type_bounds<'tcx>(
); );
let icx = ItemCtxt::new(tcx, assoc_item_def_id); let icx = ItemCtxt::new(tcx, assoc_item_def_id);
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, filter);
// Associated types are implicitly sized unless a `?Sized` bound is found // Associated types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
@ -63,10 +65,11 @@ fn opaque_type_bounds<'tcx>(
ast_bounds: &'tcx [hir::GenericBound<'tcx>], ast_bounds: &'tcx [hir::GenericBound<'tcx>],
item_ty: Ty<'tcx>, item_ty: Ty<'tcx>,
span: Span, span: Span,
filter: PredicateFilter,
) -> &'tcx [(ty::Clause<'tcx>, Span)] { ) -> &'tcx [(ty::Clause<'tcx>, Span)] {
ty::print::with_reduced_queries!({ ty::print::with_reduced_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id); let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, filter);
// Opaque types are implicitly sized unless a `?Sized` bound is found // Opaque types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds); debug!(?bounds);
@ -78,6 +81,21 @@ fn opaque_type_bounds<'tcx>(
pub(super) fn explicit_item_bounds( pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
def_id: LocalDefId, def_id: LocalDefId,
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::All)
}
pub(super) fn explicit_item_super_predicates(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::SelfOnly)
}
pub(super) fn explicit_item_bounds_with_filter(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
filter: PredicateFilter,
) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { ) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
match tcx.opt_rpitit_info(def_id.to_def_id()) { match tcx.opt_rpitit_info(def_id.to_def_id()) {
// RPITIT's bounds are the same as opaque type bounds, but with // RPITIT's bounds are the same as opaque type bounds, but with
@ -95,6 +113,7 @@ pub(super) fn explicit_item_bounds(
ty::GenericArgs::identity_for_item(tcx, def_id), ty::GenericArgs::identity_for_item(tcx, def_id),
), ),
item.span, item.span,
filter,
)); ));
} }
Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!( Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
@ -109,7 +128,7 @@ pub(super) fn explicit_item_bounds(
kind: hir::TraitItemKind::Type(bounds, _), kind: hir::TraitItemKind::Type(bounds, _),
span, span,
.. ..
}) => associated_type_bounds(tcx, def_id, bounds, *span), }) => associated_type_bounds(tcx, def_id, bounds, *span, filter),
hir::Node::Item(hir::Item { hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }), kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }),
span, span,
@ -117,7 +136,7 @@ pub(super) fn explicit_item_bounds(
}) => { }) => {
let args = GenericArgs::identity_for_item(tcx, def_id); let args = GenericArgs::identity_for_item(tcx, def_id);
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
} }
// Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking // Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
// for the item bounds of the *opaques* in a trait's default method signature, we // for the item bounds of the *opaques* in a trait's default method signature, we
@ -135,7 +154,7 @@ pub(super) fn explicit_item_bounds(
let args = GenericArgs::identity_for_item(tcx, def_id); let args = GenericArgs::identity_for_item(tcx, def_id);
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
tcx.arena.alloc_slice( tcx.arena.alloc_slice(
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
.to_vec() .to_vec()
.fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }), .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
) )
@ -155,6 +174,31 @@ pub(super) fn item_bounds(
}) })
} }
pub(super) fn item_super_predicates(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| {
tcx.mk_clauses_from_iter(
util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(),
)
})
}
pub(super) fn item_non_self_assumptions(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect();
let own_bounds: FxIndexSet<_> =
tcx.item_super_predicates(def_id).skip_binder().iter().collect();
if all_bounds.len() == own_bounds.len() {
ty::EarlyBinder::bind(ty::List::empty())
} else {
ty::EarlyBinder::bind(tcx.mk_clauses_from_iter(all_bounds.difference(&own_bounds).copied()))
}
}
struct AssocTyToOpaque<'tcx> { struct AssocTyToOpaque<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
fn_def_id: DefId, fn_def_id: DefId,

View file

@ -645,7 +645,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for ty in [first_ty, second_ty] { for ty in [first_ty, second_ty] {
for (clause, _) in self for (clause, _) in self
.tcx .tcx
.explicit_item_bounds(rpit_def_id) .explicit_item_super_predicates(rpit_def_id)
.iter_instantiated_copied(self.tcx, args) .iter_instantiated_copied(self.tcx, args)
{ {
let pred = clause.kind().rebind(match clause.kind().skip_binder() { let pred = clause.kind().rebind(match clause.kind().skip_binder() {

View file

@ -329,7 +329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty, expected_ty,
closure_kind, closure_kind,
self.tcx self.tcx
.explicit_item_bounds(def_id) .explicit_item_super_predicates(def_id)
.iter_instantiated_copied(self.tcx, args) .iter_instantiated_copied(self.tcx, args)
.map(|(c, s)| (c.as_predicate(), s)), .map(|(c, s)| (c.as_predicate(), s)),
), ),
@ -906,7 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
.tcx .tcx
.explicit_item_bounds(def_id) .explicit_item_super_predicates(def_id)
.iter_instantiated_copied(self.tcx, args) .iter_instantiated_copied(self.tcx, args)
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
ty::Error(_) => return Some(ret_ty), ty::Error(_) => return Some(ret_ty),

View file

@ -403,8 +403,10 @@ impl<'tcx> InferCtxt<'tcx> {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None); let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
self.tcx.explicit_item_bounds(def_id).iter_instantiated_copied(self.tcx, args).find_map( self.tcx
|(predicate, _)| { .explicit_item_super_predicates(def_id)
.iter_instantiated_copied(self.tcx, args)
.find_map(|(predicate, _)| {
predicate predicate
.kind() .kind()
.map_bound(|kind| match kind { .map_bound(|kind| match kind {
@ -417,8 +419,7 @@ impl<'tcx> InferCtxt<'tcx> {
}) })
.no_bound_vars() .no_bound_vars()
.flatten() .flatten()
}, })
)
} }
} }

View file

@ -299,8 +299,11 @@ impl<T> Trait<T> for X {
} }
(ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias)) (ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias))
if let Some(def_id) = t.principal_def_id() if let Some(def_id) = t.principal_def_id()
&& tcx.explicit_item_bounds(alias.def_id).skip_binder().iter().any( && tcx
|(pred, _span)| match pred.kind().skip_binder() { .explicit_item_super_predicates(alias.def_id)
.skip_binder()
.iter()
.any(|(pred, _span)| match pred.kind().skip_binder() {
ty::ClauseKind::Trait(trait_predicate) ty::ClauseKind::Trait(trait_predicate)
if trait_predicate.polarity if trait_predicate.polarity
== ty::ImplPolarity::Positive => == ty::ImplPolarity::Positive =>
@ -308,8 +311,7 @@ impl<T> Trait<T> for X {
trait_predicate.def_id() == def_id trait_predicate.def_id() == def_id
} }
_ => false, _ => false,
}, }) =>
) =>
{ {
diag.help(format!( diag.help(format!(
"you can box the `{}` to coerce it to `Box<{}>`, but you'll have to \ "you can box the `{}` to coerce it to `Box<{}>`, but you'll have to \
@ -412,7 +414,7 @@ impl<T> Trait<T> for X {
ty::Alias(..) => values.expected, ty::Alias(..) => values.expected,
_ => values.found, _ => values.found,
}; };
let preds = tcx.explicit_item_bounds(opaque_ty.def_id); let preds = tcx.explicit_item_super_predicates(opaque_ty.def_id);
for (pred, _span) in preds.skip_binder() { for (pred, _span) in preds.skip_binder() {
let ty::ClauseKind::Trait(trait_predicate) = pred.kind().skip_binder() let ty::ClauseKind::Trait(trait_predicate) = pred.kind().skip_binder()
else { else {

View file

@ -300,7 +300,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
alias_ty: ty::AliasTy<'tcx>, alias_ty: ty::AliasTy<'tcx>,
) -> impl Iterator<Item = ty::Region<'tcx>> { ) -> impl Iterator<Item = ty::Region<'tcx>> {
let tcx = self.tcx; let tcx = self.tcx;
let bounds = tcx.item_bounds(alias_ty.def_id); let bounds = tcx.item_super_predicates(alias_ty.def_id);
trace!("{:#?}", bounds.skip_binder()); trace!("{:#?}", bounds.skip_binder());
bounds bounds
.iter_instantiated(tcx, alias_ty.args) .iter_instantiated(tcx, alias_ty.args)

View file

@ -295,7 +295,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => {
elaborate( elaborate(
cx.tcx, cx.tcx,
cx.tcx.explicit_item_bounds(def).instantiate_identity_iter_copied(), cx.tcx
.explicit_item_super_predicates(def)
.instantiate_identity_iter_copied(),
) )
// We only care about self bounds for the impl-trait // We only care about self bounds for the impl-trait
.filter_only_self() .filter_only_self()

View file

@ -1063,6 +1063,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
ty::EarlyBinder::bind(&*output) ty::EarlyBinder::bind(&*output)
} }
fn get_explicit_item_super_predicates(
self,
index: DefIndex,
tcx: TyCtxt<'tcx>,
) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
let lazy = self.root.tables.explicit_item_super_predicates.get(self, index);
let output = if lazy.is_default() {
&mut []
} else {
tcx.arena.alloc_from_iter(lazy.decode((self, tcx)))
};
ty::EarlyBinder::bind(&*output)
}
fn get_variant( fn get_variant(
self, self,
kind: DefKind, kind: DefKind,

View file

@ -206,6 +206,7 @@ impl IntoArgs for (CrateNum, SimplifiedType) {
provide! { tcx, def_id, other, cdata, provide! { tcx, def_id, other, cdata,
explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) } explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) }
explicit_item_super_predicates => { cdata.get_explicit_item_super_predicates(def_id.index, tcx) }
explicit_predicates_of => { table } explicit_predicates_of => { table }
generics_of => { table } generics_of => { table }
inferred_outlives_of => { table_defaulted_array } inferred_outlives_of => { table_defaulted_array }

View file

@ -1491,6 +1491,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
if let DefKind::OpaqueTy = def_kind { if let DefKind::OpaqueTy = def_kind {
self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_bounds(def_id);
self.encode_explicit_item_super_predicates(def_id);
self.tables self.tables
.is_type_alias_impl_trait .is_type_alias_impl_trait
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id)); .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
@ -1599,6 +1600,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds); record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
} }
fn encode_explicit_item_super_predicates(&mut self, def_id: DefId) {
debug!("EncodeContext::encode_explicit_item_super_predicates({:?})", def_id);
let bounds = self.tcx.explicit_item_super_predicates(def_id).skip_binder();
record_defaulted_array!(self.tables.explicit_item_super_predicates[def_id] <- bounds);
}
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn encode_info_for_assoc_item(&mut self, def_id: DefId) { fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
let tcx = self.tcx; let tcx = self.tcx;
@ -1611,6 +1618,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
AssocItemContainer::TraitContainer => { AssocItemContainer::TraitContainer => {
if let ty::AssocKind::Type = item.kind { if let ty::AssocKind::Type = item.kind {
self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_bounds(def_id);
self.encode_explicit_item_super_predicates(def_id);
} }
} }
AssocItemContainer::ImplContainer => { AssocItemContainer::ImplContainer => {

View file

@ -387,6 +387,7 @@ define_tables! {
// corresponding DefPathHash. // corresponding DefPathHash.
def_path_hashes: Table<DefIndex, u64>, def_path_hashes: Table<DefIndex, u64>,
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
explicit_item_super_predicates: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>, associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,

View file

@ -343,11 +343,14 @@ rustc_queries! {
} }
} }
/// Returns the list of bounds that can be used for /// Returns the list of bounds that are required to be satsified
/// `SelectionCandidate::ProjectionCandidate(_)` and /// by a implementation or definition. For associated types, these
/// `ProjectionTyCandidate::TraitDef`. /// must be satisfied for an implementation to be well-formed,
/// Specifically this is the bounds written on the trait's type /// and for opaque types, these are required to be satisfied by
/// definition, or those after the `impl` keyword /// the hidden-type of the opaque.
///
/// Syntactially, these are the bounds written on the trait's type
/// definition, or those after the `impl` keyword for an opaque:
/// ///
/// ```ignore (incomplete) /// ```ignore (incomplete)
/// type X: Bound + 'lt /// type X: Bound + 'lt
@ -363,7 +366,16 @@ rustc_queries! {
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() } cache_on_disk_if { key.is_local() }
separate_provide_extern separate_provide_extern
feedable }
/// The set of item bounds (see [`TyCtxt::explicit_item_bounds`]) that
/// share the `Self` type of the item. These are a subset of the bounds
/// that may explicitly be used for things like closure signature
/// deduction.
query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
} }
/// Elaborated version of the predicates from `explicit_item_bounds`. /// Elaborated version of the predicates from `explicit_item_bounds`.
@ -390,6 +402,14 @@ rustc_queries! {
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
} }
query item_super_predicates(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) }
}
query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) }
}
/// Look up all native libraries this crate depends on. /// Look up all native libraries this crate depends on.
/// These are assembled from the following places: /// These are assembled from the following places:
/// - `extern` blocks (depending on their `link` attributes) /// - `extern` blocks (depending on their `link` attributes)

View file

@ -1828,7 +1828,7 @@ impl<'tcx> TyCtxt<'tcx> {
let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
let future_trait = self.require_lang_item(LangItem::Future, None); let future_trait = self.require_lang_item(LangItem::Future, None);
self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| { self.explicit_item_super_predicates(def_id).skip_binder().iter().any(|&(predicate, _)| {
let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
return false; return false;
}; };

View file

@ -1098,8 +1098,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
)) ))
} }
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
self.tcx.item_bounds(def_id).instantiate(self.tcx, args).iter().find_map( self.tcx
|pred| { .item_super_predicates(def_id)
.instantiate(self.tcx, args)
.iter()
.find_map(|pred| {
if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
&& Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
// args tuple will always be args[1] // args tuple will always be args[1]
@ -1113,8 +1116,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} else { } else {
None None
} }
}, })
)
} }
ty::Dynamic(data, _, ty::Dyn) => { ty::Dynamic(data, _, ty::Dyn) => {
data.iter().find_map(|pred| { data.iter().find_map(|pred| {

View file

@ -1617,21 +1617,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => return ControlFlow::Continue(()), _ => return ControlFlow::Continue(()),
}; };
for bound in
self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
{
// HACK: On subsequent recursions, we only care about bounds that don't // HACK: On subsequent recursions, we only care about bounds that don't
// share the same type as `self_ty`. This is because for truly rigid // share the same type as `self_ty`. This is because for truly rigid
// projections, we will never be able to equate, e.g. `<T as Tr>::A` // projections, we will never be able to equate, e.g. `<T as Tr>::A`
// with `<<T as Tr>::A as Tr>::A`. // with `<<T as Tr>::A as Tr>::A`.
if in_parent_alias_type { let relevant_bounds = if in_parent_alias_type {
match bound.kind().skip_binder() { self.tcx().item_non_self_assumptions(alias_ty.def_id)
ty::ClauseKind::Trait(tr) if tr.self_ty() == self_ty => continue, } else {
ty::ClauseKind::Projection(p) if p.self_ty() == self_ty => continue, self.tcx().item_super_predicates(alias_ty.def_id)
_ => {} };
}
}
for bound in relevant_bounds.instantiate(self.tcx(), alias_ty.args) {
for_each(self, bound, idx)?; for_each(self, bound, idx)?;
idx += 1; idx += 1;
} }

View file

@ -0,0 +1,21 @@
//@ check-pass
#![feature(type_alias_impl_trait)]
trait IsPtr {
type Assoc;
}
impl<T> IsPtr for T {
type Assoc = fn(i32);
}
type Tait = impl IsPtr<Assoc: Fn(i32)> + Fn(u32);
fn hello()
where
Tait:,
{
let _: Tait = |x| {};
}
fn main() {}

View file

@ -0,0 +1,21 @@
//@ check-pass
#![deny(unused_must_use)]
use std::future::Future;
use std::pin::Pin;
trait Factory {
type Output;
}
impl Factory for () {
type Output = Pin<Box<dyn Future<Output = ()> + 'static>>;
}
// Make sure we don't get an `unused_must_use` error on the *associated type bound*.
fn f() -> impl Factory<Output: Future> {}
fn main() {
f();
}