|
1 | 1 | //! Computes a normalizes-to (projection) goal for opaque types. This goal
|
2 | 2 | //! behaves differently depending on the current `TypingMode`.
|
3 | 3 |
|
4 |
| -use rustc_index::bit_set::GrowableBitSet; |
5 | 4 | use rustc_type_ir::inherent::*;
|
6 | 5 | use rustc_type_ir::solve::GoalSource;
|
7 |
| -use rustc_type_ir::{self as ty, Interner, TypingMode, fold_regions}; |
| 6 | +use rustc_type_ir::{self as ty, GenericArgKind, Interner, TypingMode, fold_regions}; |
8 | 7 |
|
9 | 8 | use crate::delegate::SolverDelegate;
|
10 |
| -use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect}; |
| 9 | +use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult}; |
11 | 10 |
|
12 | 11 | impl<D, I> EvalCtxt<'_, D>
|
13 | 12 | where
|
@@ -49,54 +48,27 @@ where
|
49 | 48 | return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
50 | 49 | };
|
51 | 50 |
|
52 |
| - // FIXME: This may have issues when the args contain aliases... |
53 |
| - match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) { |
54 |
| - Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => { |
55 |
| - return self.evaluate_added_goals_and_make_canonical_response( |
56 |
| - Certainty::AMBIGUOUS, |
57 |
| - ); |
58 |
| - } |
59 |
| - Err(_) => { |
60 |
| - return Err(NoSolution); |
61 |
| - } |
62 |
| - Ok(()) => {} |
63 |
| - } |
64 |
| - // Prefer opaques registered already. |
65 |
| - let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args }; |
66 |
| - // FIXME: This also unifies the previous hidden type with the expected. |
67 |
| - // |
68 |
| - // If that fails, we insert `expected` as a new hidden type instead of |
69 |
| - // eagerly emitting an error. |
70 |
| - let existing = self.probe_existing_opaque_ty(opaque_type_key); |
71 |
| - if let Some((candidate_key, candidate_ty)) = existing { |
72 |
| - return self |
73 |
| - .probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { |
74 |
| - result: *result, |
75 |
| - }) |
76 |
| - .enter(|ecx| { |
77 |
| - for (a, b) in std::iter::zip( |
78 |
| - candidate_key.args.iter(), |
79 |
| - opaque_type_key.args.iter(), |
80 |
| - ) { |
81 |
| - ecx.eq(goal.param_env, a, b)?; |
82 |
| - } |
83 |
| - ecx.eq(goal.param_env, candidate_ty, expected)?; |
84 |
| - ecx.add_item_bounds_for_hidden_type( |
85 |
| - def_id.into(), |
86 |
| - candidate_key.args, |
87 |
| - goal.param_env, |
88 |
| - candidate_ty, |
89 |
| - ); |
90 |
| - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) |
91 |
| - }); |
| 51 | + // We structurally normalize the args to |
| 52 | + let normalized_args = |
| 53 | + cx.mk_args_from_iter(opaque_ty.args.iter().map(|arg| match arg.kind() { |
| 54 | + GenericArgKind::Lifetime(lt) => Ok(lt.into()), |
| 55 | + GenericArgKind::Type(ty) => { |
| 56 | + self.structurally_normalize_ty(goal.param_env, ty).map(Into::into) |
| 57 | + } |
| 58 | + GenericArgKind::Const(ct) => { |
| 59 | + self.structurally_normalize_const(goal.param_env, ct).map(Into::into) |
| 60 | + } |
| 61 | + }))?; |
| 62 | + |
| 63 | + let opaque_type_key = ty::OpaqueTypeKey { def_id, args: normalized_args }; |
| 64 | + if let Some(prev) = self.register_hidden_type_in_storage(opaque_type_key, expected) |
| 65 | + { |
| 66 | + self.eq(goal.param_env, expected, prev)?; |
92 | 67 | }
|
93 | 68 |
|
94 |
| - // Otherwise, define a new opaque type |
95 |
| - let prev = self.register_hidden_type_in_storage(opaque_type_key, expected); |
96 |
| - assert_eq!(prev, None); |
97 | 69 | self.add_item_bounds_for_hidden_type(
|
98 | 70 | def_id.into(),
|
99 |
| - opaque_ty.args, |
| 71 | + normalized_args, |
100 | 72 | goal.param_env,
|
101 | 73 | expected,
|
102 | 74 | );
|
@@ -168,44 +140,3 @@ where
|
168 | 140 | }
|
169 | 141 | }
|
170 | 142 | }
|
171 |
| - |
172 |
| -/// Checks whether each generic argument is simply a unique generic placeholder. |
173 |
| -/// |
174 |
| -/// FIXME: Interner argument is needed to constrain the `I` parameter. |
175 |
| -fn uses_unique_placeholders_ignoring_regions<I: Interner>( |
176 |
| - _cx: I, |
177 |
| - args: I::GenericArgs, |
178 |
| -) -> Result<(), NotUniqueParam<I>> { |
179 |
| - let mut seen = GrowableBitSet::default(); |
180 |
| - for arg in args.iter() { |
181 |
| - match arg.kind() { |
182 |
| - // Ignore regions, since we can't resolve those in a canonicalized |
183 |
| - // query in the trait solver. |
184 |
| - ty::GenericArgKind::Lifetime(_) => {} |
185 |
| - ty::GenericArgKind::Type(t) => match t.kind() { |
186 |
| - ty::Placeholder(p) => { |
187 |
| - if !seen.insert(p.var()) { |
188 |
| - return Err(NotUniqueParam::DuplicateParam(t.into())); |
189 |
| - } |
190 |
| - } |
191 |
| - _ => return Err(NotUniqueParam::NotParam(t.into())), |
192 |
| - }, |
193 |
| - ty::GenericArgKind::Const(c) => match c.kind() { |
194 |
| - ty::ConstKind::Placeholder(p) => { |
195 |
| - if !seen.insert(p.var()) { |
196 |
| - return Err(NotUniqueParam::DuplicateParam(c.into())); |
197 |
| - } |
198 |
| - } |
199 |
| - _ => return Err(NotUniqueParam::NotParam(c.into())), |
200 |
| - }, |
201 |
| - } |
202 |
| - } |
203 |
| - |
204 |
| - Ok(()) |
205 |
| -} |
206 |
| - |
207 |
| -// FIXME: This should check for dupes and non-params first, then infer vars. |
208 |
| -enum NotUniqueParam<I: Interner> { |
209 |
| - DuplicateParam(I::GenericArg), |
210 |
| - NotParam(I::GenericArg), |
211 |
| -} |
0 commit comments