@@ -167,15 +167,20 @@ pub(crate) fn setup_constraining_predicates<'tcx>(
167167 // which is `O(nt)` where `t` is the depth of type-parameter constraints,
168168 // remembering that `t` should be less than 7 in practice.
169169 //
170+ // FIXME(hkBst): the big-O bound above would be accurate for the number
171+ // of calls to `parameters_for`, which itself is some O(complexity of type).
172+ // That would make this potentially cubic instead of merely quadratic...
173+ // ...unless we cache those `parameters_for` calls.
174+ //
170175 // Basically, I iterate over all projections and swap every
171176 // "ready" projection to the start of the list, such that
172177 // all of the projections before `i` are topologically sorted
173178 // and constrain all the parameters in `input_parameters`.
174179 //
175- // In the example, `input_parameters` starts by containing `U` - which
176- // is constrained by the trait-ref - and so on the first pass we
180+ // In the first example, `input_parameters` starts by containing `U`,
181+ // which is constrained by the self type `U`. Then, on the first pass we
177182 // observe that `<U as Iterator>::Item = T` is a "ready" projection that
178- // constrains `T` and swap it to front. As it is the sole projection,
183+ // constrains `T` and swap it to the front. As it is the sole projection,
179184 // no more swaps can take place afterwards, with the result being
180185 // * <U as Iterator>::Item = T
181186 // * T: Debug
@@ -193,33 +198,25 @@ pub(crate) fn setup_constraining_predicates<'tcx>(
193198 for j in i..predicates. len ( ) {
194199 // Note that we don't have to care about binders here,
195200 // as the impl trait ref never contains any late-bound regions.
196- if let ty:: ClauseKind :: Projection ( projection) = predicates[ j] . 0 . kind ( ) . skip_binder ( ) {
197- // Special case: watch out for some kind of sneaky attempt
198- // to project out an associated type defined by this very
199- // trait.
200- let unbound_trait_ref = projection. projection_term . trait_ref ( tcx) ;
201- if Some ( unbound_trait_ref) == impl_trait_ref {
202- continue ;
203- }
204-
205- // A projection depends on its input types and determines its output
206- // type. For example, if we have
207- // `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
208- // Then the projection only applies if `T` is known, but it still
209- // does not determine `U`.
210- let inputs = parameters_for ( tcx, projection. projection_term , true ) ;
211- let relies_only_on_inputs = inputs. iter ( ) . all ( |p| input_parameters. contains ( p) ) ;
212- if !relies_only_on_inputs {
213- continue ;
214- }
201+ if let ty:: ClauseKind :: Projection ( projection) = predicates[ j] . 0 . kind ( ) . skip_binder ( ) &&
202+
203+ // Special case: watch out for some kind of sneaky attempt to
204+ // project out an associated type defined by this very trait.
205+ !impl_trait_ref. is_some_and ( |t| t == projection. projection_term . trait_ref ( tcx) ) &&
206+
207+ // A projection depends on its input types and determines its output
208+ // type. For example, if we have
209+ // `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
210+ // then the projection only applies if `T` is known, but it still
211+ // does not determine `U`.
212+ parameters_for ( tcx, projection. projection_term , true ) . iter ( ) . all ( |p| input_parameters. contains ( p) )
213+ {
215214 input_parameters. extend ( parameters_for ( tcx, projection. term , false ) ) ;
216- } else {
217- continue ;
215+
216+ predicates. swap ( i, j) ;
217+ i += 1 ;
218+ changed = true ;
218219 }
219- // fancy control flow to bypass borrow checker
220- predicates. swap ( i, j) ;
221- i += 1 ;
222- changed = true ;
223220 }
224221 debug ! (
225222 "setup_constraining_predicates: predicates={:?} \
0 commit comments