Skip to content

Commit d2cc847

Browse files
committed
Add helper trait that restricts lifetimes and extra predicates to ensure soundness
1 parent 4b4c05b commit d2cc847

39 files changed

Lines changed: 623 additions & 69 deletions

compiler/rustc_hir/src/lang_items.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ language_item_table! {
189189
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
190190
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
191191

192+
TryAsDyn, sym::try_as_dyn, try_as_dyn, Target::Trait, GenericRequirement::Exact(1);
193+
192194
// lang items relating to transmutability
193195
TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
194196
TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(2);

compiler/rustc_middle/src/traits/select.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ pub enum SelectionCandidate<'tcx> {
183183
BuiltinUnsizeCandidate,
184184

185185
BikeshedGuaranteedNoDropCandidate,
186+
187+
TryAsDynCandidate,
186188
}
187189

188190
/// The result of trait evaluation. The order is important

compiler/rustc_middle/src/ty/context/impl_interner.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ bidirectional_lang_item_map! {
806806
Sized,
807807
TransmuteTrait,
808808
TrivialClone,
809+
TryAsDyn,
809810
Tuple,
810811
Unpin,
811812
Unsize,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,9 @@ pub struct ImplTraitHeader<'tcx> {
281281
}
282282

283283
impl<'tcx> ImplTraitHeader<'tcx> {
284-
/// For trait impls, checks whether the type and trait only have generic parameters in their
285-
/// arguments and only uses each generic param once, too.
286-
/// Pessimistic analysis, so it will reject alias types
284+
/// For trait impls, checks whether the type and trait only have generic lifetime parameters in their
285+
/// arguments and only use any generic param once.
286+
/// This is a pessimistic analysis, so it will reject alias types
287287
/// and other types that may be actually ok. We can allow more in the future.
288288
pub fn is_fully_generic_for_reflection(self) -> bool {
289289
#[derive(Default)]
@@ -302,14 +302,12 @@ impl<'tcx> ImplTraitHeader<'tcx> {
302302
ControlFlow::Break(())
303303
}
304304
}
305-
RegionKind::ReBound(..) | RegionKind::ReLateParam(_) => {
306-
ControlFlow::Continue(())
307-
}
308-
RegionKind::ReStatic
309-
| RegionKind::ReVar(_)
305+
RegionKind::ReBound(..) => ControlFlow::Continue(()),
306+
RegionKind::ReStatic | RegionKind::ReError(_) => ControlFlow::Break(()),
307+
RegionKind::ReVar(_)
310308
| RegionKind::RePlaceholder(_)
311309
| RegionKind::ReErased
312-
| RegionKind::ReError(_) => ControlFlow::Break(()),
310+
| RegionKind::ReLateParam(_) => bug!("unexpected lifetime in impl: {r:?}"),
313311
}
314312
}
315313

compiler/rustc_middle/src/ty/predicate.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,12 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesPredicate<'tcx>> for Predicate<'
557557
}
558558
}
559559

560+
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTypeOutlivesPredicate<'tcx>> for Predicate<'tcx> {
561+
fn upcast_from(from: PolyTypeOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
562+
from.map_bound(|p| PredicateKind::Clause(ClauseKind::TypeOutlives(p))).upcast(tcx)
563+
}
564+
}
565+
560566
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Predicate<'tcx> {
561567
fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
562568
ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx)

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,11 @@ where
337337
goal: Goal<I, Self>,
338338
) -> Result<Candidate<I>, NoSolution>;
339339

340+
fn consider_builtin_try_as_dyn_candidate(
341+
ecx: &mut EvalCtxt<'_, D>,
342+
goal: Goal<I, Self>,
343+
) -> Result<Candidate<I>, NoSolution>;
344+
340345
/// Consider (possibly several) candidates to upcast or unsize a type to another
341346
/// type, excluding the coercion of a sized type into a `dyn Trait`.
342347
///
@@ -530,6 +535,10 @@ where
530535
let cx = self.cx();
531536
let trait_def_id = goal.predicate.trait_def_id(cx);
532537

538+
if let TypingMode::Reflection = self.typing_mode() {
539+
return;
540+
}
541+
533542
// N.B. When assembling built-in candidates for lang items that are also
534543
// `auto` traits, then the auto trait candidate that is assembled in
535544
// `consider_auto_trait_candidate` MUST be disqualified to remain sound.
@@ -622,6 +631,9 @@ where
622631
Some(SolverTraitLangItem::BikeshedGuaranteedNoDrop) => {
623632
G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal)
624633
}
634+
Some(SolverTraitLangItem::TryAsDyn) => {
635+
G::consider_builtin_try_as_dyn_candidate(self, goal)
636+
}
625637
Some(SolverTraitLangItem::Field) => G::consider_builtin_field_candidate(self, goal),
626638
_ => Err(NoSolution),
627639
}
@@ -804,6 +816,10 @@ where
804816
return;
805817
}
806818

819+
if let TypingMode::Reflection = self.typing_mode() {
820+
return;
821+
}
822+
807823
let self_ty = goal.predicate.self_ty();
808824
let bounds = match self_ty.kind() {
809825
ty::Bool

compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,13 @@ where
425425
unreachable!("BikeshedGuaranteedNoDrop is not const");
426426
}
427427

428+
fn consider_builtin_try_as_dyn_candidate(
429+
_ecx: &mut EvalCtxt<'_, D>,
430+
goal: Goal<I, Self>,
431+
) -> Result<Candidate<I>, NoSolution> {
432+
unreachable!("`TryAsDynCompat` is not const: {:?}", goal)
433+
}
434+
428435
fn consider_structural_builtin_unsize_candidates(
429436
_ecx: &mut EvalCtxt<'_, D>,
430437
_goal: Goal<I, Self>,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,13 @@ where
953953
unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
954954
}
955955

956+
fn consider_builtin_try_as_dyn_candidate(
957+
_ecx: &mut EvalCtxt<'_, D>,
958+
goal: Goal<I, Self>,
959+
) -> Result<Candidate<I>, NoSolution> {
960+
unreachable!("`TryAsDynCompat` does not have an associated type: {:?}", goal)
961+
}
962+
956963
fn consider_builtin_field_candidate(
957964
ecx: &mut EvalCtxt<'_, D>,
958965
goal: Goal<I, Self>,

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,39 @@ where
854854
})
855855
}
856856

857+
fn consider_builtin_try_as_dyn_candidate(
858+
ecx: &mut EvalCtxt<'_, D>,
859+
goal: Goal<I, Self>,
860+
) -> Result<Candidate<I>, NoSolution> {
861+
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
862+
return Err(NoSolution);
863+
}
864+
let cx = ecx.cx();
865+
866+
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
867+
let self_ty = goal.predicate.self_ty();
868+
let ty = goal.predicate.trait_ref.args.type_at(1);
869+
match self_ty.kind() {
870+
ty::Dynamic(_bounds, lifetime) => {
871+
ecx.add_goal(
872+
GoalSource::Misc,
873+
goal.with(cx, ty::OutlivesPredicate(ty, lifetime)),
874+
);
875+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
876+
}
877+
878+
ty::Bound(..)
879+
| ty::Infer(
880+
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
881+
) => {
882+
panic!("unexpected type `{ty:?}`")
883+
}
884+
885+
_ => Err(NoSolution),
886+
}
887+
})
888+
}
889+
857890
fn consider_builtin_field_candidate(
858891
ecx: &mut EvalCtxt<'_, D>,
859892
goal: Goal<I, Self>,

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,7 @@ symbols! {
20482048
truncf32,
20492049
truncf64,
20502050
truncf128,
2051+
try_as_dyn,
20512052
try_blocks,
20522053
try_blocks_heterogeneous,
20532054
try_capture,

0 commit comments

Comments
 (0)