merge builtin unsize candidates again
This commit is contained in:
parent
0d71860368
commit
ea4e5b8458
@ -253,17 +253,6 @@ fn consider_structural_builtin_unsize_candidates(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>;
|
||||
|
||||
/// Consider the `Unsize` candidate corresponding to coercing a sized type
|
||||
/// into a `dyn Trait`.
|
||||
///
|
||||
/// This is computed separately from the rest of the `Unsize` candidates
|
||||
/// since it is only done once per self type, and not once per
|
||||
/// *normalization step* (in `assemble_candidates_via_self_ty`).
|
||||
fn consider_unsize_to_dyn_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
@ -306,8 +295,6 @@ pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
|
||||
|
||||
self.assemble_object_bound_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_unsize_to_dyn_candidate(goal, &mut candidates);
|
||||
|
||||
self.assemble_blanket_impl_candidates(goal, &mut candidates);
|
||||
|
||||
self.assemble_param_env_candidates(goal, &mut candidates);
|
||||
@ -422,24 +409,6 @@ fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn assemble_unsize_to_dyn_candidate<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, G>,
|
||||
candidates: &mut Vec<Candidate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
if tcx.lang_items().unsize_trait() == Some(goal.predicate.trait_def_id(tcx)) {
|
||||
match G::consider_unsize_to_dyn_candidate(self, goal) {
|
||||
Ok(result) => candidates.push(Candidate {
|
||||
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
||||
result,
|
||||
}),
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip_all)]
|
||||
fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
||||
&mut self,
|
||||
|
@ -603,13 +603,6 @@ fn consider_builtin_coroutine_candidate(
|
||||
)
|
||||
}
|
||||
|
||||
fn consider_unsize_to_dyn_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
bug!("`Unsize` does not have an associated type: {:?}", goal)
|
||||
}
|
||||
|
||||
fn consider_structural_builtin_unsize_candidates(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -490,53 +490,6 @@ fn consider_builtin_transmute_candidate(
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(certainty)
|
||||
}
|
||||
|
||||
fn consider_unsize_to_dyn_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| {
|
||||
let a_ty = goal.predicate.self_ty();
|
||||
// We need to normalize the b_ty since it's destructured as a `dyn Trait`.
|
||||
let Some(b_ty) =
|
||||
ecx.try_normalize_ty(goal.param_env, goal.predicate.trait_ref.args.type_at(1))
|
||||
else {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
|
||||
};
|
||||
|
||||
let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
let tcx = ecx.tcx();
|
||||
|
||||
// Can only unsize to an object-safe trait.
|
||||
if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// Check that the type implements all of the predicates of the trait object.
|
||||
// (i.e. the principal, all of the associated types match, and any auto traits)
|
||||
ecx.add_goals(
|
||||
GoalSource::ImplWhereBound,
|
||||
b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
|
||||
);
|
||||
|
||||
// The type must be `Sized` to be unsized.
|
||||
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
|
||||
ecx.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])),
|
||||
);
|
||||
} else {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// The type must outlive the lifetime of the `dyn` we're unsizing into.
|
||||
ecx.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
/// ```ignore (builtin impl example)
|
||||
/// trait Trait {
|
||||
/// fn foo(&self);
|
||||
@ -588,8 +541,11 @@ fn consider_structural_builtin_unsize_candidates(
|
||||
goal, a_data, a_region, b_data, b_region,
|
||||
),
|
||||
|
||||
// `T` -> `dyn Trait` unsizing is handled separately in `consider_unsize_to_dyn_candidate`
|
||||
(_, &ty::Dynamic(..)) => vec![],
|
||||
// `T` -> `dyn Trait` unsizing.
|
||||
(_, &ty::Dynamic(b_region, b_data, ty::Dyn)) => result_to_single(
|
||||
ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data),
|
||||
BuiltinImplSource::Misc,
|
||||
),
|
||||
|
||||
// `[T; N]` -> `[T]` unsizing
|
||||
(&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => result_to_single(
|
||||
@ -691,6 +647,42 @@ fn consider_builtin_dyn_upcast_candidates(
|
||||
responses
|
||||
}
|
||||
|
||||
fn consider_builtin_unsize_to_dyn_candidate(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
b_region: ty::Region<'tcx>,
|
||||
) -> QueryResult<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let Goal { predicate: (a_ty, _), .. } = goal;
|
||||
|
||||
// Can only unsize to an object-safe trait.
|
||||
if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// Check that the type implements all of the predicates of the trait object.
|
||||
// (i.e. the principal, all of the associated types match, and any auto traits)
|
||||
self.add_goals(
|
||||
GoalSource::ImplWhereBound,
|
||||
b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
|
||||
);
|
||||
|
||||
// The type must be `Sized` to be unsized.
|
||||
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
|
||||
self.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])),
|
||||
);
|
||||
} else {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// The type must outlive the lifetime of the `dyn` we're unsizing into.
|
||||
self.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
||||
fn consider_builtin_upcast_to_principal(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
|
Loading…
Reference in New Issue
Block a user