|
4 | 4 |
|
5 | 5 | use std::assert_matches::assert_matches; |
6 | 6 |
|
7 | | -use rustc_abi::{FieldIdx, HasDataLayout, Size}; |
| 7 | +use rustc_abi::{FIRST_VARIANT, FieldIdx, HasDataLayout, Size}; |
8 | 8 | use rustc_apfloat::ieee::{Double, Half, Quad, Single}; |
| 9 | +use rustc_infer::infer::TyCtxtInferExt; |
9 | 10 | use rustc_middle::mir::interpret::{read_target_uint, write_target_uint}; |
10 | 11 | use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; |
11 | 12 | use rustc_middle::ty::layout::TyAndLayout; |
12 | | -use rustc_middle::ty::{Ty, TyCtxt}; |
| 13 | +use rustc_middle::ty::{Ty, TyCtxt, Upcast}; |
13 | 14 | use rustc_middle::{bug, ty}; |
14 | 15 | use rustc_span::{Symbol, sym}; |
| 16 | +use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; |
15 | 17 | use tracing::trace; |
16 | 18 |
|
17 | 19 | use super::memory::MemoryKind; |
18 | 20 | use super::util::ensure_monomorphic_enough; |
19 | 21 | use super::{ |
20 | 22 | Allocation, CheckInAllocMsg, ConstAllocation, ImmTy, InterpCx, InterpResult, Machine, OpTy, |
21 | 23 | PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_ub_custom, err_unsup_format, |
22 | | - interp_ok, throw_inval, throw_ub_custom, throw_ub_format, |
| 24 | + interp_ok, throw_inval, throw_ub_custom, throw_ub_format, throw_unsup_format, |
23 | 25 | }; |
24 | 26 | use crate::fluent_generated as fluent; |
25 | 27 |
|
@@ -151,18 +153,41 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { |
151 | 153 | sym::vtable_for => { |
152 | 154 | let tp_ty = instance.args.type_at(0); |
153 | 155 | let result_ty = instance.args.type_at(1); |
154 | | - //let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, span); |
155 | 156 |
|
156 | 157 | ensure_monomorphic_enough(tcx, tp_ty)?; |
157 | 158 | ensure_monomorphic_enough(tcx, result_ty)?; |
158 | 159 |
|
159 | | - // Get vtable |
160 | | - //let vtable_ptr = self.get_vtable_ptr(tp_ty, result_ty.into())?; |
| 160 | + let ty::Dynamic(preds, _, ty::Dyn) = result_ty.kind() else { |
| 161 | + throw_unsup_format!( |
| 162 | + "Invalid type provided to vtable_for::<T, U>. U must be dyn Trait, got {result_ty}." |
| 163 | + ); |
| 164 | + }; |
161 | 165 |
|
162 | | - //let dyn_metadata = metadata(vtable_ptr); |
163 | | - //let val = ConstValue::from_u128(tcx.type_id_hash(tp_ty).as_u128()); |
164 | | - //let val = self.const_val_to_op(val, dest.layout.ty, Some(dest.layout))?; |
165 | | - //self.copy_op(&val, dest)?; |
| 166 | + let (infcx, param_env) = self |
| 167 | + .tcx |
| 168 | + .infer_ctxt() |
| 169 | + .build_with_typing_env(ty::TypingEnv::fully_monomorphized()); |
| 170 | + |
| 171 | + let type_impls_trait = preds.iter().all(|pred| { |
| 172 | + let trait_ref = ty::TraitRef::new(tcx, pred.def_id(), [tp_ty]); |
| 173 | + let pred: ty::Predicate<'tcx> = trait_ref.upcast(tcx); |
| 174 | + |
| 175 | + let ocx = ObligationCtxt::new(&infcx); |
| 176 | + ocx.register_obligation(Obligation::new( |
| 177 | + tcx, |
| 178 | + ObligationCause::dummy(), |
| 179 | + param_env, |
| 180 | + pred, |
| 181 | + )); |
| 182 | + ocx.select_all_or_error().is_empty() |
| 183 | + }); |
| 184 | + |
| 185 | + if type_impls_trait { |
| 186 | + let vtable_ptr = self.get_vtable_ptr(tp_ty, preds)?; |
| 187 | + self.write_pointer(vtable_ptr, dest)?; |
| 188 | + } else { |
| 189 | + self.write_discriminant(FIRST_VARIANT, dest)?; |
| 190 | + } |
166 | 191 | } |
167 | 192 | sym::variant_count => { |
168 | 193 | let tp_ty = instance.args.type_at(0); |
|
0 commit comments