Skip to content

Commit ea4e5b8

Browse files
committed
merge builtin unsize candidates again
1 parent 0d71860 commit ea4e5b8

File tree

3 files changed

+41
-87
lines changed

3 files changed

+41
-87
lines changed

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

-31
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,6 @@ pub(super) trait GoalKind<'tcx>:
253253
ecx: &mut EvalCtxt<'_, 'tcx>,
254254
goal: Goal<'tcx, Self>,
255255
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>;
256-
257-
/// Consider the `Unsize` candidate corresponding to coercing a sized type
258-
/// into a `dyn Trait`.
259-
///
260-
/// This is computed separately from the rest of the `Unsize` candidates
261-
/// since it is only done once per self type, and not once per
262-
/// *normalization step* (in `assemble_candidates_via_self_ty`).
263-
fn consider_unsize_to_dyn_candidate(
264-
ecx: &mut EvalCtxt<'_, 'tcx>,
265-
goal: Goal<'tcx, Self>,
266-
) -> QueryResult<'tcx>;
267256
}
268257

269258
impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -306,8 +295,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
306295

307296
self.assemble_object_bound_candidates(goal, &mut candidates);
308297

309-
self.assemble_unsize_to_dyn_candidate(goal, &mut candidates);
310-
311298
self.assemble_blanket_impl_candidates(goal, &mut candidates);
312299

313300
self.assemble_param_env_candidates(goal, &mut candidates);
@@ -422,24 +409,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
422409
}
423410
}
424411

425-
#[instrument(level = "debug", skip_all)]
426-
fn assemble_unsize_to_dyn_candidate<G: GoalKind<'tcx>>(
427-
&mut self,
428-
goal: Goal<'tcx, G>,
429-
candidates: &mut Vec<Candidate<'tcx>>,
430-
) {
431-
let tcx = self.tcx();
432-
if tcx.lang_items().unsize_trait() == Some(goal.predicate.trait_def_id(tcx)) {
433-
match G::consider_unsize_to_dyn_candidate(self, goal) {
434-
Ok(result) => candidates.push(Candidate {
435-
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
436-
result,
437-
}),
438-
Err(NoSolution) => (),
439-
}
440-
}
441-
}
442-
443412
#[instrument(level = "debug", skip_all)]
444413
fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
445414
&mut self,

compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs

-7
Original file line numberDiff line numberDiff line change
@@ -603,13 +603,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
603603
)
604604
}
605605

606-
fn consider_unsize_to_dyn_candidate(
607-
_ecx: &mut EvalCtxt<'_, 'tcx>,
608-
goal: Goal<'tcx, Self>,
609-
) -> QueryResult<'tcx> {
610-
bug!("`Unsize` does not have an associated type: {:?}", goal)
611-
}
612-
613606
fn consider_structural_builtin_unsize_candidates(
614607
_ecx: &mut EvalCtxt<'_, 'tcx>,
615608
goal: Goal<'tcx, Self>,

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+41-49
Original file line numberDiff line numberDiff line change
@@ -490,53 +490,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
490490
ecx.evaluate_added_goals_and_make_canonical_response(certainty)
491491
}
492492

493-
fn consider_unsize_to_dyn_candidate(
494-
ecx: &mut EvalCtxt<'_, 'tcx>,
495-
goal: Goal<'tcx, Self>,
496-
) -> QueryResult<'tcx> {
497-
ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| {
498-
let a_ty = goal.predicate.self_ty();
499-
// We need to normalize the b_ty since it's destructured as a `dyn Trait`.
500-
let Some(b_ty) =
501-
ecx.try_normalize_ty(goal.param_env, goal.predicate.trait_ref.args.type_at(1))
502-
else {
503-
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW);
504-
};
505-
506-
let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
507-
return Err(NoSolution);
508-
};
509-
510-
let tcx = ecx.tcx();
511-
512-
// Can only unsize to an object-safe trait.
513-
if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
514-
return Err(NoSolution);
515-
}
516-
517-
// Check that the type implements all of the predicates of the trait object.
518-
// (i.e. the principal, all of the associated types match, and any auto traits)
519-
ecx.add_goals(
520-
GoalSource::ImplWhereBound,
521-
b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
522-
);
523-
524-
// The type must be `Sized` to be unsized.
525-
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
526-
ecx.add_goal(
527-
GoalSource::ImplWhereBound,
528-
goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])),
529-
);
530-
} else {
531-
return Err(NoSolution);
532-
}
533-
534-
// The type must outlive the lifetime of the `dyn` we're unsizing into.
535-
ecx.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
536-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
537-
})
538-
}
539-
540493
/// ```ignore (builtin impl example)
541494
/// trait Trait {
542495
/// fn foo(&self);
@@ -588,8 +541,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
588541
goal, a_data, a_region, b_data, b_region,
589542
),
590543

591-
// `T` -> `dyn Trait` unsizing is handled separately in `consider_unsize_to_dyn_candidate`
592-
(_, &ty::Dynamic(..)) => vec![],
544+
// `T` -> `dyn Trait` unsizing.
545+
(_, &ty::Dynamic(b_region, b_data, ty::Dyn)) => result_to_single(
546+
ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data),
547+
BuiltinImplSource::Misc,
548+
),
593549

594550
// `[T; N]` -> `[T]` unsizing
595551
(&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => result_to_single(
@@ -691,6 +647,42 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
691647
responses
692648
}
693649

650+
fn consider_builtin_unsize_to_dyn_candidate(
651+
&mut self,
652+
goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
653+
b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
654+
b_region: ty::Region<'tcx>,
655+
) -> QueryResult<'tcx> {
656+
let tcx = self.tcx();
657+
let Goal { predicate: (a_ty, _), .. } = goal;
658+
659+
// Can only unsize to an object-safe trait.
660+
if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
661+
return Err(NoSolution);
662+
}
663+
664+
// Check that the type implements all of the predicates of the trait object.
665+
// (i.e. the principal, all of the associated types match, and any auto traits)
666+
self.add_goals(
667+
GoalSource::ImplWhereBound,
668+
b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))),
669+
);
670+
671+
// The type must be `Sized` to be unsized.
672+
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
673+
self.add_goal(
674+
GoalSource::ImplWhereBound,
675+
goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])),
676+
);
677+
} else {
678+
return Err(NoSolution);
679+
}
680+
681+
// The type must outlive the lifetime of the `dyn` we're unsizing into.
682+
self.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
683+
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
684+
}
685+
694686
fn consider_builtin_upcast_to_principal(
695687
&mut self,
696688
goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,

0 commit comments

Comments
 (0)