]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_const_eval/src/interpret/traits.rs
Rollup merge of #99578 - steffahn:remove_redundant_bound, r=thomcc
[rust.git] / compiler / rustc_const_eval / src / interpret / traits.rs
1 use rustc_middle::mir::interpret::{InterpResult, Pointer};
2 use rustc_middle::ty::layout::LayoutOf;
3 use rustc_middle::ty::{self, Ty, TyCtxt};
4 use rustc_target::abi::{Align, Size};
5
6 use super::util::ensure_monomorphic_enough;
7 use super::{InterpCx, Machine};
8
9 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10     /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
11     /// objects.
12     ///
13     /// The `trait_ref` encodes the erased self type. Hence, if we are making an object `Foo<Trait>`
14     /// from a value of type `Foo<T>`, then `trait_ref` would map `T: Trait`. `None` here means that
15     /// this is an auto trait without any methods, so we only need the basic vtable (drop, size,
16     /// align).
17     pub fn get_vtable_ptr(
18         &self,
19         ty: Ty<'tcx>,
20         poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
21     ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
22         trace!("get_vtable(trait_ref={:?})", poly_trait_ref);
23
24         let (ty, poly_trait_ref) = self.tcx.erase_regions((ty, poly_trait_ref));
25
26         // All vtables must be monomorphic, bail out otherwise.
27         ensure_monomorphic_enough(*self.tcx, ty)?;
28         ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?;
29
30         let vtable_symbolic_allocation = self.tcx.create_vtable_alloc(ty, poly_trait_ref);
31         let vtable_ptr = self.global_base_pointer(Pointer::from(vtable_symbolic_allocation))?;
32         Ok(vtable_ptr.into())
33     }
34
35     /// Returns a high-level representation of the entries of the given vtable.
36     pub fn get_vtable_entries(
37         &self,
38         vtable: Pointer<Option<M::Provenance>>,
39     ) -> InterpResult<'tcx, &'tcx [ty::VtblEntry<'tcx>]> {
40         let (ty, poly_trait_ref) = self.get_ptr_vtable(vtable)?;
41         Ok(if let Some(poly_trait_ref) = poly_trait_ref {
42             let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
43             let trait_ref = self.tcx.erase_regions(trait_ref);
44             self.tcx.vtable_entries(trait_ref)
45         } else {
46             TyCtxt::COMMON_VTABLE_ENTRIES
47         })
48     }
49
50     pub fn get_vtable_size_and_align(
51         &self,
52         vtable: Pointer<Option<M::Provenance>>,
53     ) -> InterpResult<'tcx, (Size, Align)> {
54         let (ty, _trait_ref) = self.get_ptr_vtable(vtable)?;
55         let layout = self.layout_of(ty)?;
56         assert!(!layout.is_unsized(), "there are no vtables for unsized types");
57         Ok((layout.size, layout.align.abi))
58     }
59 }