|
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