Skip to content

Commit 1c25d1b

Browse files
committed
Merge remote-tracking branch 'origin/try_as_dyn' into try_as_dyn
# Conflicts: # compiler/rustc_const_eval/src/interpret/intrinsics.rs
2 parents 6033439 + 53a486f commit 1c25d1b

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,48 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
190190
let b_ty = self.read_type_id(&args[1])?;
191191
self.write_scalar(Scalar::from_bool(a_ty == b_ty), dest)?;
192192
}
193+
sym::vtable_for => {
194+
let tp_ty = instance.args.type_at(0);
195+
let result_ty = instance.args.type_at(1);
196+
197+
ensure_monomorphic_enough(tcx, tp_ty)?;
198+
ensure_monomorphic_enough(tcx, result_ty)?;
199+
let ty::Dynamic(preds, _, ty::Dyn) = result_ty.kind() else {
200+
span_bug!(
201+
self.find_closest_untracked_caller_location(),
202+
"Invalid type provided to vtable_for::<T, U>. U must be dyn Trait, got {result_ty}."
203+
);
204+
};
205+
206+
let (infcx, param_env) =
207+
self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
208+
209+
let ocx = ObligationCtxt::new(&infcx);
210+
ocx.register_obligations(preds.iter().map(|pred| {
211+
let pred = pred.with_self_ty(tcx, tp_ty);
212+
// Lifetimes can only be 'static because of the bound on T
213+
let pred = pred.fold_with(&mut ty::BottomUpFolder {
214+
tcx,
215+
ty_op: |ty| ty,
216+
lt_op: |lt| {
217+
if lt == tcx.lifetimes.re_erased { tcx.lifetimes.re_static } else { lt }
218+
},
219+
ct_op: |ct| ct,
220+
});
221+
Obligation::new(tcx, ObligationCause::dummy(), param_env, pred)
222+
}));
223+
let type_impls_trait = ocx.select_all_or_error().is_empty();
224+
// Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default"
225+
let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty();
226+
227+
if regions_are_valid && type_impls_trait {
228+
let vtable_ptr = self.get_vtable_ptr(tp_ty, preds)?;
229+
// Writing a non-null pointer into an `Option<NonNull>` will automatically make it `Some`.
230+
self.write_pointer(vtable_ptr, dest)?;
231+
} else {
232+
// Write `None`
233+
self.write_discriminant(FIRST_VARIANT, dest)?;
234+
}
193235
sym::size_of => {
194236
let tp_ty = instance.args.type_at(0);
195237
let layout = self.layout_of(tp_ty)?;

0 commit comments

Comments
 (0)