]>
Commit | Line | Data |
---|---|---|
136023e0 | 1 | use crate::traits::query::evaluate_obligation::InferCtxtExt as _; |
487cf647 | 2 | use crate::traits::{self, ObligationCtxt}; |
ba9703b0 | 3 | |
136023e0 | 4 | use rustc_hir::def_id::DefId; |
3dfed10e | 5 | use rustc_hir::lang_items::LangItem; |
ba9703b0 | 6 | use rustc_middle::arena::ArenaAllocatable; |
9c376795 | 7 | use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse}; |
49aad941 | 8 | use rustc_middle::traits::query::NoSolution; |
9ffffee4 | 9 | use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; |
487cf647 | 10 | use rustc_middle::ty::{GenericArg, ToPredicate}; |
353b0b11 | 11 | use rustc_span::DUMMY_SP; |
ba9703b0 XL |
12 | |
13 | use std::fmt::Debug; | |
14 | ||
15 | pub use rustc_infer::infer::*; | |
16 | ||
17 | pub 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 | 40 | impl<'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 | ||
81 | pub 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 | ||
93 | impl<'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 | } |