|
1 | | -use rustc_hir::def_id::LocalDefId; |
2 | | -use rustc_middle::mir; |
| 1 | +use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; |
| 2 | +use rustc_infer::infer::TyCtxtInferExt; |
| 3 | +use rustc_infer::traits::{Obligation, ObligationCause}; |
3 | 4 | use rustc_middle::mir::interpret::{AllocInit, Allocation, GlobalAlloc, InterpResult, Pointer}; |
4 | 5 | use rustc_middle::ty::layout::TyAndLayout; |
5 | | -use rustc_middle::ty::{TyCtxt, TypeVisitable, TypeVisitableExt}; |
| 6 | +use rustc_middle::ty::{PolyExistentialPredicate, Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; |
| 7 | +use rustc_middle::{mir, span_bug, ty}; |
| 8 | +use rustc_trait_selection::traits::ObligationCtxt; |
6 | 9 | use tracing::debug; |
7 | 10 |
|
8 | 11 | use super::{InterpCx, MPlaceTy, MemoryKind, interp_ok, throw_inval}; |
9 | 12 | use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult}; |
| 13 | +use crate::interpret::Machine; |
| 14 | + |
| 15 | +/// Checks if a type implements predicates. |
| 16 | +/// Calls `ensure_monomorphic_enough` on `ty` and `trait_ty` for you. |
| 17 | +pub(crate) fn type_implements_dyn_trait<'tcx, M: Machine<'tcx>>( |
| 18 | + ecx: &mut InterpCx<'tcx, M>, |
| 19 | + ty: Ty<'tcx>, |
| 20 | + trait_ty: Ty<'tcx>, |
| 21 | +) -> InterpResult<'tcx, (bool, &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>)> { |
| 22 | + ensure_monomorphic_enough(ecx.tcx.tcx, ty)?; |
| 23 | + ensure_monomorphic_enough(ecx.tcx.tcx, trait_ty)?; |
| 24 | + |
| 25 | + let ty::Dynamic(preds, _) = trait_ty.kind() else { |
| 26 | + span_bug!( |
| 27 | + ecx.find_closest_untracked_caller_location(), |
| 28 | + "Invalid type provided to type_implements_predicates. U must be dyn Trait, got {trait_ty}." |
| 29 | + ); |
| 30 | + }; |
| 31 | + |
| 32 | + let (infcx, param_env) = ecx.tcx.infer_ctxt().build_with_typing_env(ecx.typing_env); |
| 33 | + |
| 34 | + let ocx = ObligationCtxt::new(&infcx); |
| 35 | + ocx.register_obligations(preds.iter().map(|pred: PolyExistentialPredicate<'_>| { |
| 36 | + let pred = pred.with_self_ty(ecx.tcx.tcx, ty); |
| 37 | + // Lifetimes can only be 'static because of the bound on T |
| 38 | + let pred = rustc_middle::ty::fold_regions(ecx.tcx.tcx, pred, |r, _| { |
| 39 | + if r == ecx.tcx.tcx.lifetimes.re_erased { ecx.tcx.tcx.lifetimes.re_static } else { r } |
| 40 | + }); |
| 41 | + Obligation::new(ecx.tcx.tcx, ObligationCause::dummy(), param_env, pred) |
| 42 | + })); |
| 43 | + let type_impls_trait = ocx.evaluate_obligations_error_on_ambiguity().is_empty(); |
| 44 | + // Since `assumed_wf_tys=[]` the choice of LocalDefId is irrelevant, so using the "default" |
| 45 | + let regions_are_valid = ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty(); |
| 46 | + |
| 47 | + interp_ok((regions_are_valid && type_impls_trait, preds)) |
| 48 | +} |
10 | 49 |
|
11 | 50 | /// Checks whether a type contains generic parameters which must be instantiated. |
12 | 51 | /// |
|
0 commit comments