@@ -13,14 +13,15 @@ use rustc_infer::infer::{InferOk, InferResult};
13
13
use rustc_macros:: { TypeFoldable , TypeVisitable } ;
14
14
use rustc_middle:: ty:: subst:: InternalSubsts ;
15
15
use rustc_middle:: ty:: visit:: TypeVisitable ;
16
- use rustc_middle:: ty:: { self , Ty } ;
16
+ use rustc_middle:: ty:: { self , Ty , TypeSuperVisitable , TypeVisitor } ;
17
17
use rustc_span:: source_map:: Span ;
18
18
use rustc_target:: spec:: abi:: Abi ;
19
19
use rustc_trait_selection:: traits;
20
20
use rustc_trait_selection:: traits:: error_reporting:: ArgKind ;
21
21
use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt as _;
22
22
use std:: cmp;
23
23
use std:: iter;
24
+ use std:: ops:: ControlFlow ;
24
25
25
26
/// What signature do we *expect* the closure to have from context?
26
27
#[ derive( Debug , Clone , TypeFoldable , TypeVisitable ) ]
@@ -54,7 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
54
55
// closure sooner rather than later, so first examine the expected
55
56
// type, and see if can glean a closure kind from there.
56
57
let ( expected_sig, expected_kind) = match expected. to_option ( self ) {
57
- Some ( ty) => self . deduce_expectations_from_expected_type ( ty) ,
58
+ Some ( ty) => self . deduce_closure_signature ( ty) ,
58
59
None => ( None , None ) ,
59
60
} ;
60
61
let body = self . tcx . hir ( ) . body ( closure. body ) ;
@@ -162,13 +163,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
162
163
/// Given the expected type, figures out what it can about this closure we
163
164
/// are about to type check:
164
165
#[ instrument( skip( self ) , level = "debug" ) ]
165
- fn deduce_expectations_from_expected_type (
166
+ fn deduce_closure_signature (
166
167
& self ,
167
168
expected_ty : Ty < ' tcx > ,
168
169
) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
169
170
match * expected_ty. kind ( ) {
170
171
ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => self
171
- . deduce_signature_from_predicates (
172
+ . deduce_closure_signature_from_predicates (
173
+ expected_ty,
172
174
self . tcx . bound_explicit_item_bounds ( def_id) . subst_iter_copied ( self . tcx , substs) ,
173
175
) ,
174
176
ty:: Dynamic ( ref object_type, ..) => {
@@ -181,7 +183,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
181
183
. and_then ( |did| self . tcx . fn_trait_kind_from_def_id ( did) ) ;
182
184
( sig, kind)
183
185
}
184
- ty:: Infer ( ty:: TyVar ( vid) ) => self . deduce_signature_from_predicates (
186
+ ty:: Infer ( ty:: TyVar ( vid) ) => self . deduce_closure_signature_from_predicates (
187
+ self . tcx . mk_ty_var ( self . root_var ( vid) ) ,
185
188
self . obligations_for_self_ty ( vid) . map ( |obl| ( obl. predicate , obl. cause . span ) ) ,
186
189
) ,
187
190
ty:: FnPtr ( sig) => {
@@ -192,8 +195,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
192
195
}
193
196
}
194
197
195
- fn deduce_signature_from_predicates (
198
+ fn deduce_closure_signature_from_predicates (
196
199
& self ,
200
+ expected_ty : Ty < ' tcx > ,
197
201
predicates : impl DoubleEndedIterator < Item = ( ty:: Predicate < ' tcx > , Span ) > ,
198
202
) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
199
203
let mut expected_sig = None ;
@@ -214,13 +218,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
214
218
if expected_sig. is_none ( )
215
219
&& let ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( proj_predicate) ) = bound_predicate. skip_binder ( )
216
220
{
217
- expected_sig = self . normalize (
221
+ let inferred_sig = self . normalize (
218
222
obligation. cause . span ,
219
223
self . deduce_sig_from_projection (
220
224
Some ( obligation. cause . span ) ,
221
225
bound_predicate. rebind ( proj_predicate) ,
222
226
) ,
223
227
) ;
228
+ // Make sure that we didn't infer a signature that mentions itself.
229
+ // This can happen when we elaborate certain supertrait bounds that
230
+ // mention projections containing the `Self` type. See
231
+ struct MentionsTy < ' tcx > {
232
+ expected_ty : Ty < ' tcx > ,
233
+ }
234
+ impl < ' tcx > TypeVisitor < ' tcx > for MentionsTy < ' tcx > {
235
+ type BreakTy = ( ) ;
236
+
237
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
238
+ if t == self . expected_ty {
239
+ ControlFlow :: BREAK
240
+ } else {
241
+ t. super_visit_with ( self )
242
+ }
243
+ }
244
+ }
245
+ if inferred_sig. visit_with ( & mut MentionsTy { expected_ty } ) . is_continue ( ) {
246
+ expected_sig = inferred_sig;
247
+ }
224
248
}
225
249
226
250
// Even if we can't infer the full signature, we may be able to
0 commit comments