]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/infer.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / infer.rs
CommitLineData
136023e0 1use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
487cf647 2use crate::traits::{self, ObligationCtxt};
ba9703b0 3
136023e0 4use rustc_hir::def_id::DefId;
3dfed10e 5use rustc_hir::lang_items::LangItem;
ba9703b0 6use rustc_middle::arena::ArenaAllocatable;
9c376795 7use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
49aad941 8use rustc_middle::traits::query::NoSolution;
9ffffee4 9use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
487cf647 10use rustc_middle::ty::{GenericArg, ToPredicate};
353b0b11 11use rustc_span::DUMMY_SP;
ba9703b0
XL
12
13use std::fmt::Debug;
14
15pub use rustc_infer::infer::*;
16
17pub trait InferCtxtExt<'tcx> {
353b0b11 18 fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool;
ba9703b0 19
353b0b11 20 fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool;
f2b60f7d 21
136023e0
XL
22 /// Check whether a `ty` implements given trait(trait_def_id).
23 /// The inputs are:
24 ///
25 /// - the def-id of the trait
487cf647 26 /// - the type parameters of the trait, including the self-type
136023e0 27 /// - the parameter environment
94222f64
XL
28 ///
29 /// Invokes `evaluate_obligation`, so in the event that evaluating
30 /// `Ty: Trait` causes overflow, EvaluatedToRecur (or EvaluatedToUnknown)
31 /// will be returned.
136023e0
XL
32 fn type_implements_trait(
33 &self,
34 trait_def_id: DefId,
9ffffee4 35 params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
136023e0
XL
36 param_env: ty::ParamEnv<'tcx>,
37 ) -> traits::EvaluationResult;
38}
353b0b11 39
2b03887a 40impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
353b0b11 41 fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
fc512014 42 let ty = self.resolve_vars_if_possible(ty);
ba9703b0 43
49aad941 44 if !(param_env, ty).has_infer() {
2b03887a 45 return ty.is_copy_modulo_regions(self.tcx, param_env);
ba9703b0
XL
46 }
47
3dfed10e 48 let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None);
ba9703b0
XL
49
50 // This can get called from typeck (by euv), and `moves_by_default`
51 // rightly refuses to work with inference variables, but
52 // moves_by_default has a cache, which we want to use in other
53 // cases.
353b0b11 54 traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
ba9703b0
XL
55 }
56
353b0b11 57 fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
f2b60f7d 58 let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
353b0b11 59 traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
f2b60f7d
FG
60 }
61
487cf647 62 #[instrument(level = "debug", skip(self, params), ret)]
136023e0
XL
63 fn type_implements_trait(
64 &self,
65 trait_def_id: DefId,
9ffffee4 66 params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
136023e0
XL
67 param_env: ty::ParamEnv<'tcx>,
68 ) -> traits::EvaluationResult {
49aad941 69 let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, params);
136023e0
XL
70
71 let obligation = traits::Obligation {
72 cause: traits::ObligationCause::dummy(),
73 param_env,
74 recursion_depth: 0,
c295e0f8 75 predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx),
136023e0 76 };
94222f64 77 self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr)
136023e0 78 }
ba9703b0
XL
79}
80
81pub trait InferCtxtBuilderExt<'tcx> {
82 fn enter_canonical_trait_query<K, R>(
83 &mut self,
84 canonical_key: &Canonical<'tcx, K>,
49aad941
FG
85 operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
86 ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
ba9703b0 87 where
9ffffee4
FG
88 K: TypeFoldable<TyCtxt<'tcx>>,
89 R: Debug + TypeFoldable<TyCtxt<'tcx>>,
f035d41b 90 Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
ba9703b0
XL
91}
92
93impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
94 /// The "main method" for a canonicalized trait query. Given the
95 /// canonical key `canonical_key`, this method will create a new
96 /// inference context, instantiate the key, and run your operation
97 /// `op`. The operation should yield up a result (of type `R`) as
98 /// well as a set of trait obligations that must be fully
99 /// satisfied. These obligations will be processed and the
100 /// canonical result created.
101 ///
102 /// Returns `NoSolution` in the event of any error.
103 ///
104 /// (It might be mildly nicer to implement this on `TyCtxt`, and
105 /// not `InferCtxtBuilder`, but that is a bit tricky right now.
106 /// In part because we would need a `for<'tcx>` sort of
107 /// bound for the closure and in part because it is convenient to
108 /// have `'tcx` be free on this function so that we can talk about
9ffffee4 109 /// `K: TypeFoldable<TyCtxt<'tcx>>`.)
ba9703b0
XL
110 fn enter_canonical_trait_query<K, R>(
111 &mut self,
112 canonical_key: &Canonical<'tcx, K>,
49aad941
FG
113 operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
114 ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
ba9703b0 115 where
9ffffee4
FG
116 K: TypeFoldable<TyCtxt<'tcx>>,
117 R: Debug + TypeFoldable<TyCtxt<'tcx>>,
f035d41b 118 Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
ba9703b0 119 {
487cf647 120 let (infcx, key, canonical_inference_vars) =
2b03887a 121 self.build_with_canonical(DUMMY_SP, canonical_key);
487cf647
FG
122 let ocx = ObligationCtxt::new(&infcx);
123 let value = operation(&ocx, key)?;
124 ocx.make_canonicalized_query_response(canonical_inference_vars, value)
ba9703b0
XL
125 }
126}