summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/project.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/project.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs196
1 files changed, 63 insertions, 133 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 5789754e4..fbc7ecced 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -25,7 +25,6 @@ use rustc_data_structures::sso::SsoHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::at::At;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
@@ -45,7 +44,7 @@ pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPre
pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
pub(super) struct InProgress;
@@ -149,7 +148,7 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
}
// Prefer where-clauses. As in select, if there are multiple
- // candidates, we prefer where-clause candidates over impls. This
+ // candidates, we prefer where-clause candidates over impls. This
// may seem a bit surprising, since impls are the source of
// "truth" in some sense, but in fact some of the impls that SEEM
// applicable are not, because of nested obligations. Where
@@ -283,7 +282,7 @@ fn project_and_unify_type<'cx, 'tcx>(
};
debug!(?normalized, ?obligations, "project_and_unify_type result");
let actual = obligation.predicate.term;
- // For an example where this is necessary see src/test/ui/impl-trait/nested-return-type2.rs
+ // For an example where this is necessary see tests/ui/impl-trait/nested-return-type2.rs
// This allows users to omit re-mentioning all bounds on an associated type and just use an
// `impl Trait` for the assoc type to add more bounds.
let InferOk { value: actual, obligations: new } =
@@ -496,7 +495,9 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
// This is really important. While we *can* handle this, this has
// severe performance implications for large opaque types with
// late-bound regions. See `issue-88862` benchmark.
- ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+ if !substs.has_escaping_bound_vars() =>
+ {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty.super_fold_with(self),
@@ -523,7 +524,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
}
}
- ty::Projection(data) if !data.has_escaping_bound_vars() => {
+ ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
// This branch is *mostly* just an optimization: when we don't
// have escaping bound vars, we don't need to replace them with
// placeholders (see branch below). *Also*, we know that we can
@@ -562,7 +563,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
normalized_ty.ty().unwrap()
}
- ty::Projection(data) => {
+ ty::Alias(ty::Projection, data) => {
// If there are escaping bound vars, we temporarily replace the
// bound vars with placeholders. Note though, that in the case
// that we still can't project for whatever reason (e.g. self
@@ -957,7 +958,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
pub fn normalize_projection_type<'a, 'b, 'tcx>(
selcx: &'a mut SelectionContext<'b, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -995,7 +996,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
fn opt_normalize_projection_type<'a, 'b, 'tcx>(
selcx: &'a mut SelectionContext<'b, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
@@ -1033,7 +1034,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
}
Err(ProjectionCacheEntry::InProgress) => {
// Under lazy normalization, this can arise when
- // bootstrapping. That is, imagine an environment with a
+ // bootstrapping. That is, imagine an environment with a
// where-clause like `A::B == u32`. Now, if we are asked
// to normalize `A::B`, we will want to check the
// where-clauses in scope. So we will try to unify `A::B`
@@ -1177,7 +1178,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
fn normalize_to_error<'a, 'tcx>(
selcx: &mut SelectionContext<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
) -> NormalizedTy<'tcx> {
@@ -1189,10 +1190,9 @@ fn normalize_to_error<'a, 'tcx>(
predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
};
let tcx = selcx.infcx.tcx;
- let def_id = projection_ty.item_def_id;
let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::NormalizeProjectionType,
- span: tcx.def_span(def_id),
+ span: tcx.def_span(projection_ty.def_id),
});
Normalized { value: new_value, obligations: vec![trait_obligation] }
}
@@ -1270,7 +1270,7 @@ fn project<'cx, 'tcx>(
// need to investigate whether or not this is fine.
selcx
.tcx()
- .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs)
+ .mk_projection(obligation.predicate.def_id, obligation.predicate.substs)
.into(),
)),
// Error occurred while trying to processing impls.
@@ -1290,13 +1290,12 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
candidate_set: &mut ProjectionCandidateSet<'tcx>,
) {
let tcx = selcx.tcx();
- if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
- let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+ if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
+ let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
// If we are trying to project an RPITIT with trait's default `Self` parameter,
// then we must be within a default trait body.
if obligation.predicate.self_ty()
- == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
- .type_at(0)
+ == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
&& tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
{
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
@@ -1309,8 +1308,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
let trait_substs =
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
// FIXME(named-returns): Binders
- let trait_predicate =
- ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs });
+ let trait_predicate = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, trait_substs));
let _ = selcx.infcx.commit_if_ok(|_| {
match selcx.select(&obligation.with(tcx, trait_predicate)) {
@@ -1377,8 +1375,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
// Check whether the self-type is itself a projection.
// If so, extract what we know from the trait and try to come up with a good answer.
let bounds = match *obligation.predicate.self_ty().kind() {
- ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs),
- ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs),
+ ty::Alias(_, ref data) => tcx.item_bounds(data.def_id).subst(tcx, data.substs),
ty::Infer(ty::TyVar(_)) => {
// If the self-type is an inference variable, then it MAY wind up
// being a projected type, so induce an ambiguity.
@@ -1430,7 +1427,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
};
let env_predicates = data
.projection_bounds()
- .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+ .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
.map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
assemble_candidates_from_predicates(
@@ -1462,7 +1459,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
predicate.kind().skip_binder()
{
let data = bound_predicate.rebind(data);
- if data.projection_def_id() != obligation.predicate.item_def_id {
+ if data.projection_def_id() != obligation.predicate.def_id {
continue;
}
@@ -1503,7 +1500,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
candidate_set: &mut ProjectionCandidateSet<'tcx>,
) {
// Can't assemble candidate from impl for RPITIT
- if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+ if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
return;
}
@@ -1555,7 +1552,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// NOTE: This should be kept in sync with the similar code in
// `rustc_ty_utils::instance::resolve_associated_item()`.
let node_item =
- assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
+ specialization_graph::assoc_def(selcx.tcx(), impl_data.impl_def_id, obligation.predicate.def_id)
.map_err(|ErrorGuaranteed { .. }| ())?;
if node_item.is_final() {
@@ -1616,8 +1613,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// type parameters, opaques, and unnormalized projections have pointer
// metadata if they're known (e.g. by the param_env) to be sized
ty::Param(_)
- | ty::Projection(..)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(..)
@@ -1671,7 +1667,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// type parameters, opaques, and unnormalized projections have pointer
// metadata if they're known (e.g. by the param_env) to be sized
- ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
+ ty::Param(_) | ty::Alias(..)
if selcx.infcx.predicate_must_hold_modulo_regions(
&obligation.with(
selcx.tcx(),
@@ -1687,8 +1683,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
ty::Param(_)
- | ty::Projection(..)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(..)
@@ -1788,7 +1783,7 @@ fn confirm_candidate<'cx, 'tcx>(
ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
term: selcx
.tcx()
- .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+ .mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
.into(),
obligations: vec![],
},
@@ -1860,7 +1855,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
gen_sig,
)
.map_bound(|(trait_ref, yield_ty, return_ty)| {
- let name = tcx.associated_item(obligation.predicate.item_def_id).name;
+ let name = tcx.associated_item(obligation.predicate.def_id).name;
let ty = if name == sym::Return {
return_ty
} else if name == sym::Yield {
@@ -1870,10 +1865,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
};
ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- substs: trait_ref.substs,
- item_def_id: obligation.predicate.item_def_id,
- },
+ projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
term: ty.into(),
}
});
@@ -1909,13 +1901,10 @@ fn confirm_future_candidate<'cx, 'tcx>(
gen_sig,
)
.map_bound(|(trait_ref, return_ty)| {
- debug_assert_eq!(tcx.associated_item(obligation.predicate.item_def_id).name, sym::Output);
+ debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- substs: trait_ref.substs,
- item_def_id: obligation.predicate.item_def_id,
- },
+ projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
term: return_ty.into(),
}
});
@@ -1934,7 +1923,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
let self_ty = obligation.predicate.self_ty();
let substs = tcx.mk_substs([self_ty.into()].iter());
let lang_items = tcx.lang_items();
- let item_def_id = obligation.predicate.item_def_id;
+ let item_def_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
@@ -1969,7 +1958,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
};
let predicate =
- ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id }, term };
+ ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
.with_addl_obligations(obligations)
@@ -2038,10 +2027,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
flag,
)
.map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- substs: trait_ref.substs,
- item_def_id: fn_once_output_def_id,
- },
+ projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
term: ret_type.into(),
});
@@ -2122,11 +2108,11 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let tcx = selcx.tcx();
let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
- let assoc_item_id = obligation.predicate.item_def_id;
+ let assoc_item_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let param_env = obligation.param_env;
- let Ok(assoc_ty) = assoc_def(selcx, impl_def_id, assoc_item_id) else {
+ let Ok(assoc_ty) = specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) else {
return Progress { term: tcx.ty_error().into(), obligations: nested };
};
@@ -2222,8 +2208,8 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
let tcx = selcx.tcx();
let mut obligations = data.nested;
- let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
- let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
+ let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
+ let Ok(leaf_def) = specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) else {
return Progress { term: tcx.ty_error().into(), obligations };
};
if !leaf_def.item.defaultness(tcx).has_value() {
@@ -2233,9 +2219,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
// Use the default `impl Trait` for the trait, e.g., for a default trait body
if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
return Progress {
- term: tcx
- .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
- .into(),
+ term: tcx.mk_opaque(obligation.predicate.def_id, obligation.predicate.substs).into(),
obligations,
};
}
@@ -2275,34 +2259,32 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
&mut obligations,
);
- obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map(
- |(pred, span)| {
- Obligation::with_depth(
- tcx,
- ObligationCause::new(
- obligation.cause.span,
- obligation.cause.body_id,
- if span.is_dummy() {
- super::ItemObligation(impl_fn_def_id)
- } else {
- super::BindingObligation(impl_fn_def_id, span)
- },
- ),
- obligation.recursion_depth + 1,
- obligation.param_env,
- pred,
- )
- },
- ));
+ obligations.extend(predicates.into_iter().map(|(pred, span)| {
+ Obligation::with_depth(
+ tcx,
+ ObligationCause::new(
+ obligation.cause.span,
+ obligation.cause.body_id,
+ if span.is_dummy() {
+ super::ItemObligation(impl_fn_def_id)
+ } else {
+ super::BindingObligation(impl_fn_def_id, span)
+ },
+ ),
+ obligation.recursion_depth + 1,
+ obligation.param_env,
+ pred,
+ )
+ }));
let ty = normalize_with_depth_to(
selcx,
obligation.param_env,
cause.clone(),
obligation.recursion_depth + 1,
- tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
+ tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
.map_bound(|tys| {
- tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id])
+ tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
})
.subst(tcx, impl_fn_substs),
&mut obligations,
@@ -2319,10 +2301,10 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
nested: &mut Vec<PredicateObligation<'tcx>>,
) {
let tcx = selcx.tcx();
- let own = tcx
- .predicates_of(obligation.predicate.item_def_id)
+ let predicates = tcx
+ .predicates_of(obligation.predicate.def_id)
.instantiate_own(tcx, obligation.predicate.substs);
- for (predicate, span) in std::iter::zip(own.predicates, own.spans) {
+ for (predicate, span) in predicates {
let normalized = normalize_with_depth_to(
selcx,
obligation.param_env,
@@ -2343,13 +2325,13 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- super::ItemObligation(obligation.predicate.item_def_id),
+ super::ItemObligation(obligation.predicate.def_id),
)
} else {
ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- super::BindingObligation(obligation.predicate.item_def_id, span),
+ super::BindingObligation(obligation.predicate.def_id, span),
)
};
nested.push(Obligation::with_depth(
@@ -2362,58 +2344,6 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
}
}
-/// Locate the definition of an associated type in the specialization hierarchy,
-/// starting from the given impl.
-///
-/// Based on the "projection mode", this lookup may in fact only examine the
-/// topmost impl. See the comments for `Reveal` for more details.
-fn assoc_def(
- selcx: &SelectionContext<'_, '_>,
- impl_def_id: DefId,
- assoc_def_id: DefId,
-) -> Result<specialization_graph::LeafDef, ErrorGuaranteed> {
- let tcx = selcx.tcx();
- let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
- let trait_def = tcx.trait_def(trait_def_id);
-
- // This function may be called while we are still building the
- // specialization graph that is queried below (via TraitDef::ancestors()),
- // so, in order to avoid unnecessary infinite recursion, we manually look
- // for the associated item at the given impl.
- // If there is no such item in that impl, this function will fail with a
- // cycle error if the specialization graph is currently being built.
- if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_def_id) {
- let item = tcx.associated_item(impl_item_id);
- let impl_node = specialization_graph::Node::Impl(impl_def_id);
- return Ok(specialization_graph::LeafDef {
- item: *item,
- defining_node: impl_node,
- finalizing_node: if item.defaultness(tcx).is_default() {
- None
- } else {
- Some(impl_node)
- },
- });
- }
-
- let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
- if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_def_id) {
- Ok(assoc_item)
- } else {
- // This is saying that neither the trait nor
- // the impl contain a definition for this
- // associated type. Normally this situation
- // could only arise through a compiler bug --
- // if the user wrote a bad item name, it
- // should have failed in astconv.
- bug!(
- "No associated type `{}` for {}",
- tcx.item_name(assoc_def_id),
- tcx.def_path_str(impl_def_id)
- )
- }
-}
-
pub(crate) trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized {
fn from_poly_projection_predicate(
selcx: &mut SelectionContext<'cx, 'tcx>,