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