Replace RPITIT current impl with new strategy that lowers as a GAT
This commit is contained in:
parent
d1389b9b48
commit
20429af7a3
146 changed files with 1106 additions and 586 deletions
|
@ -131,8 +131,6 @@ enum ProjectionCandidate<'tcx> {
|
|||
|
||||
/// From an "impl" (or a "pseudo-impl" returned by select)
|
||||
Select(Selection<'tcx>),
|
||||
|
||||
ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
|
||||
}
|
||||
|
||||
enum ProjectionCandidateSet<'tcx> {
|
||||
|
@ -1472,8 +1470,6 @@ fn project<'cx, 'tcx>(
|
|||
|
||||
let mut candidates = ProjectionCandidateSet::None;
|
||||
|
||||
assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates);
|
||||
|
||||
// Make sure that the following procedures are kept in order. ParamEnv
|
||||
// needs to be first because it has highest priority, and Select checks
|
||||
// the return value of push_candidate which assumes it's ran at last.
|
||||
|
@ -1499,7 +1495,7 @@ fn project<'cx, 'tcx>(
|
|||
ProjectionCandidateSet::None => {
|
||||
let tcx = selcx.tcx();
|
||||
let term = match tcx.def_kind(obligation.predicate.def_id) {
|
||||
DefKind::AssocTy | DefKind::ImplTraitPlaceholder => Ty::new_projection(
|
||||
DefKind::AssocTy => Ty::new_projection(
|
||||
tcx,
|
||||
obligation.predicate.def_id,
|
||||
obligation.predicate.substs,
|
||||
|
@ -1530,47 +1526,6 @@ fn project<'cx, 'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the
|
||||
/// corresponding trait ref. If this yields an `impl`, then we're able to project
|
||||
/// to a concrete type, since we have an `impl`'s method to provide the RPITIT.
|
||||
fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
|
||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
candidate_set: &mut ProjectionCandidateSet<'tcx>,
|
||||
) {
|
||||
let tcx = selcx.tcx();
|
||||
if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
|
||||
let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
|
||||
|
||||
let trait_def_id = tcx.parent(trait_fn_def_id);
|
||||
let trait_substs =
|
||||
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
|
||||
let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs);
|
||||
|
||||
let _ = selcx.infcx.commit_if_ok(|_| {
|
||||
match selcx.select(&obligation.with(tcx, trait_predicate)) {
|
||||
Ok(Some(super::ImplSource::UserDefined(data))) => {
|
||||
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
|
||||
Ok(())
|
||||
}
|
||||
Ok(None) => {
|
||||
candidate_set.mark_ambiguous();
|
||||
Err(())
|
||||
}
|
||||
Ok(Some(_)) => {
|
||||
// Don't know enough about the impl to provide a useful signature
|
||||
Err(())
|
||||
}
|
||||
Err(e) => {
|
||||
debug!(error = ?e, "selection error");
|
||||
candidate_set.mark_error(e);
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// The first thing we have to do is scan through the parameter
|
||||
/// environment to see whether there are any projection predicates
|
||||
/// there that can answer this question.
|
||||
|
@ -1739,11 +1694,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
candidate_set: &mut ProjectionCandidateSet<'tcx>,
|
||||
) {
|
||||
// Can't assemble candidate from impl for RPITIT
|
||||
if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
||||
// start out by selecting the predicate `T as TraitRef<...>`:
|
||||
let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
|
||||
|
@ -2012,9 +1962,6 @@ fn confirm_candidate<'cx, 'tcx>(
|
|||
ProjectionCandidate::Select(impl_source) => {
|
||||
confirm_select_candidate(selcx, obligation, impl_source)
|
||||
}
|
||||
ProjectionCandidate::ImplTraitInTrait(data) => {
|
||||
confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
|
||||
}
|
||||
};
|
||||
|
||||
// When checking for cycle during evaluation, we compare predicates with
|
||||
|
@ -2240,8 +2187,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
|
|||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
nested: Vec<PredicateObligation<'tcx>>,
|
||||
) -> Progress<'tcx> {
|
||||
let ty::Closure(_, substs) =
|
||||
selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
|
||||
let ty::Closure(_, substs) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
@ -2419,103 +2365,6 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn confirm_impl_trait_in_trait_candidate<'tcx>(
|
||||
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
|
||||
) -> Progress<'tcx> {
|
||||
let tcx = selcx.tcx();
|
||||
let mut obligations = data.nested;
|
||||
|
||||
let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
|
||||
let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
|
||||
Ok(assoc_ty) => assoc_ty,
|
||||
Err(guar) => return Progress::error(tcx, guar),
|
||||
};
|
||||
// We don't support specialization for RPITITs anyways... yet.
|
||||
// Also don't try to project to an RPITIT that has no value
|
||||
if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() {
|
||||
return Progress { term: Ty::new_misc_error(tcx).into(), obligations };
|
||||
}
|
||||
|
||||
// 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: Ty::new_opaque(tcx, obligation.predicate.def_id, obligation.predicate.substs)
|
||||
.into(),
|
||||
obligations,
|
||||
};
|
||||
}
|
||||
|
||||
// Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
|
||||
// since `data.substs` are the impl substs.
|
||||
let impl_fn_substs =
|
||||
obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
|
||||
let impl_fn_substs = translate_substs(
|
||||
selcx.infcx,
|
||||
obligation.param_env,
|
||||
data.impl_def_id,
|
||||
impl_fn_substs,
|
||||
leaf_def.defining_node,
|
||||
);
|
||||
|
||||
if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
|
||||
let err = Ty::new_error_with_message(
|
||||
tcx,
|
||||
obligation.cause.span,
|
||||
"impl method and trait method have different parameters",
|
||||
);
|
||||
return Progress { term: err.into(), obligations };
|
||||
}
|
||||
|
||||
let impl_fn_def_id = leaf_def.item.def_id;
|
||||
|
||||
let cause = ObligationCause::new(
|
||||
obligation.cause.span,
|
||||
obligation.cause.body_id,
|
||||
super::ItemObligation(impl_fn_def_id),
|
||||
);
|
||||
let predicates = normalize_with_depth_to(
|
||||
selcx,
|
||||
obligation.param_env,
|
||||
cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
|
||||
&mut obligations,
|
||||
);
|
||||
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.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else(
|
||||
|guar| Ty::new_error(tcx, guar),
|
||||
|tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs),
|
||||
),
|
||||
&mut obligations,
|
||||
);
|
||||
|
||||
Progress { term: ty.into(), obligations }
|
||||
}
|
||||
|
||||
// Get obligations corresponding to the predicates from the where-clause of the
|
||||
// associated type itself.
|
||||
fn assoc_ty_own_obligations<'cx, 'tcx>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue