|
1 |
| -use rustc_infer::infer::TyCtxtInferExt; |
2 |
| -use rustc_infer::traits::ObligationCause; |
3 | 1 | use rustc_middle::mir::interpret::{InterpResult, Pointer};
|
4 | 2 | use rustc_middle::ty::layout::LayoutOf;
|
5 |
| -use rustc_middle::ty::{self, Ty}; |
| 3 | +use rustc_middle::ty::{self, Ty, TyCtxt, VtblEntry}; |
6 | 4 | use rustc_target::abi::{Align, Size};
|
7 |
| -use rustc_trait_selection::traits::ObligationCtxt; |
8 | 5 | use tracing::trace;
|
9 | 6 |
|
10 | 7 | use super::util::ensure_monomorphic_enough;
|
@@ -47,35 +44,36 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
47 | 44 | Ok((layout.size, layout.align.abi))
|
48 | 45 | }
|
49 | 46 |
|
| 47 | + pub(super) fn vtable_entries( |
| 48 | + &self, |
| 49 | + trait_: Option<ty::PolyExistentialTraitRef<'tcx>>, |
| 50 | + dyn_ty: Ty<'tcx>, |
| 51 | + ) -> &'tcx [VtblEntry<'tcx>] { |
| 52 | + if let Some(trait_) = trait_ { |
| 53 | + let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty); |
| 54 | + let trait_ref = self.tcx.erase_regions(trait_ref); |
| 55 | + self.tcx.vtable_entries(trait_ref) |
| 56 | + } else { |
| 57 | + TyCtxt::COMMON_VTABLE_ENTRIES |
| 58 | + } |
| 59 | + } |
| 60 | + |
50 | 61 | /// Check that the given vtable trait is valid for a pointer/reference/place with the given
|
51 | 62 | /// expected trait type.
|
52 | 63 | pub(super) fn check_vtable_for_type(
|
53 | 64 | &self,
|
54 | 65 | vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
55 | 66 | expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
56 | 67 | ) -> InterpResult<'tcx> {
|
57 |
| - // Fast path: if they are equal, it's all fine. |
58 |
| - if expected_trait.principal() == vtable_trait { |
59 |
| - return Ok(()); |
60 |
| - } |
61 |
| - if let (Some(expected_trait), Some(vtable_trait)) = |
62 |
| - (expected_trait.principal(), vtable_trait) |
63 |
| - { |
64 |
| - // Slow path: spin up an inference context to check if these traits are sufficiently equal. |
65 |
| - let infcx = self.tcx.infer_ctxt().build(); |
66 |
| - let ocx = ObligationCtxt::new(&infcx); |
67 |
| - let cause = ObligationCause::dummy_with_span(self.cur_span()); |
68 |
| - // equate the two trait refs after normalization |
69 |
| - let expected_trait = ocx.normalize(&cause, self.param_env, expected_trait); |
70 |
| - let vtable_trait = ocx.normalize(&cause, self.param_env, vtable_trait); |
71 |
| - if ocx.eq(&cause, self.param_env, expected_trait, vtable_trait).is_ok() { |
72 |
| - if ocx.select_all_or_error().is_empty() { |
73 |
| - // All good. |
74 |
| - return Ok(()); |
75 |
| - } |
76 |
| - } |
| 68 | + let eq = match (expected_trait.principal(), vtable_trait) { |
| 69 | + (Some(a), Some(b)) => self.eq_in_param_env(a, b), |
| 70 | + (None, None) => true, |
| 71 | + _ => false, |
| 72 | + }; |
| 73 | + if !eq { |
| 74 | + throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait }); |
77 | 75 | }
|
78 |
| - throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait }); |
| 76 | + Ok(()) |
79 | 77 | }
|
80 | 78 |
|
81 | 79 | /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
|
|
0 commit comments