|
1 | 1 | use rustc_data_structures::fx::FxHashSet;
|
2 |
| -use rustc_data_structures::stack::ensure_sufficient_stack; |
3 | 2 | use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
4 | 3 | use rustc_middle::ty::{self, Ty, TyCtxt};
|
5 | 4 | use rustc_span::Span;
|
| 5 | +use rustc_type_ir::fold::TypeFoldable; |
6 | 6 | use std::ops::ControlFlow;
|
7 | 7 |
|
8 | 8 | #[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
@@ -33,62 +33,47 @@ pub fn parameters_for_impl<'tcx>(
|
33 | 33 | impl_trait_ref: Option<ty::TraitRef<'tcx>>,
|
34 | 34 | ) -> FxHashSet<Parameter> {
|
35 | 35 | let vec = match impl_trait_ref {
|
36 |
| - Some(tr) => parameters_for(tcx, &tr, false), |
37 |
| - None => parameters_for(tcx, &impl_self_ty, false), |
| 36 | + Some(tr) => parameters_for(tcx, tr, false), |
| 37 | + None => parameters_for(tcx, impl_self_ty, false), |
38 | 38 | };
|
39 | 39 | vec.into_iter().collect()
|
40 | 40 | }
|
41 | 41 |
|
42 | 42 | /// If `include_nonconstraining` is false, returns the list of parameters that are
|
43 |
| -/// constrained by `t` - i.e., the value of each parameter in the list is |
44 |
| -/// uniquely determined by `t` (see RFC 447). If it is true, return the list |
45 |
| -/// of parameters whose values are needed in order to constrain `ty` - these |
| 43 | +/// constrained by `value` - i.e., the value of each parameter in the list is |
| 44 | +/// uniquely determined by `value` (see RFC 447). If it is true, return the list |
| 45 | +/// of parameters whose values are needed in order to constrain `value` - these |
46 | 46 | /// differ, with the latter being a superset, in the presence of projections.
|
47 | 47 | pub fn parameters_for<'tcx>(
|
48 | 48 | tcx: TyCtxt<'tcx>,
|
49 |
| - t: &impl TypeVisitable<TyCtxt<'tcx>>, |
| 49 | + value: impl TypeFoldable<TyCtxt<'tcx>>, |
50 | 50 | include_nonconstraining: bool,
|
51 | 51 | ) -> Vec<Parameter> {
|
52 |
| - let mut collector = |
53 |
| - ParameterCollector { tcx, parameters: vec![], include_nonconstraining, depth: 0 }; |
54 |
| - t.visit_with(&mut collector); |
| 52 | + let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining }; |
| 53 | + let value = if !include_nonconstraining { tcx.expand_weak_alias_tys(value) } else { value }; |
| 54 | + value.visit_with(&mut collector); |
55 | 55 | collector.parameters
|
56 | 56 | }
|
57 | 57 |
|
58 |
| -struct ParameterCollector<'tcx> { |
59 |
| - tcx: TyCtxt<'tcx>, |
| 58 | +struct ParameterCollector { |
60 | 59 | parameters: Vec<Parameter>,
|
61 | 60 | include_nonconstraining: bool,
|
62 |
| - depth: usize, |
63 | 61 | }
|
64 | 62 |
|
65 |
| -impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector<'tcx> { |
| 63 | +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector { |
66 | 64 | fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
67 | 65 | match *t.kind() {
|
| 66 | + // Projections are not injective in general. |
68 | 67 | ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _)
|
69 | 68 | if !self.include_nonconstraining =>
|
70 | 69 | {
|
71 |
| - // Projections are not injective in general. |
72 | 70 | return ControlFlow::Continue(());
|
73 | 71 | }
|
74 |
| - ty::Alias(ty::Weak, alias) if !self.include_nonconstraining => { |
75 |
| - if !self.tcx.recursion_limit().value_within_limit(self.depth) { |
76 |
| - // Other constituent types may still constrain some generic params, consider |
77 |
| - // `<T> (Overflow, T)` for example. Therefore we want to continue instead of |
78 |
| - // breaking. Only affects diagnostics. |
79 |
| - return ControlFlow::Continue(()); |
80 |
| - } |
81 |
| - self.depth += 1; |
82 |
| - return ensure_sufficient_stack(|| { |
83 |
| - self.tcx |
84 |
| - .type_of(alias.def_id) |
85 |
| - .instantiate(self.tcx, alias.args) |
86 |
| - .visit_with(self) |
87 |
| - }); |
88 |
| - } |
89 |
| - ty::Param(data) => { |
90 |
| - self.parameters.push(Parameter::from(data)); |
| 72 | + // All weak alias types should've been expanded beforehand. |
| 73 | + ty::Alias(ty::Weak, _) if !self.include_nonconstraining => { |
| 74 | + bug!("unexpected weak alias type") |
91 | 75 | }
|
| 76 | + ty::Param(param) => self.parameters.push(Parameter::from(param)), |
92 | 77 | _ => {}
|
93 | 78 | }
|
94 | 79 |
|
@@ -224,12 +209,12 @@ pub fn setup_constraining_predicates<'tcx>(
|
224 | 209 | // `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
|
225 | 210 | // Then the projection only applies if `T` is known, but it still
|
226 | 211 | // does not determine `U`.
|
227 |
| - let inputs = parameters_for(tcx, &projection.projection_ty, true); |
| 212 | + let inputs = parameters_for(tcx, projection.projection_ty, true); |
228 | 213 | let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p));
|
229 | 214 | if !relies_only_on_inputs {
|
230 | 215 | continue;
|
231 | 216 | }
|
232 |
| - input_parameters.extend(parameters_for(tcx, &projection.term, false)); |
| 217 | + input_parameters.extend(parameters_for(tcx, projection.term, false)); |
233 | 218 | } else {
|
234 | 219 | continue;
|
235 | 220 | }
|
|
0 commit comments