@@ -13,14 +13,15 @@ use rustc_infer::infer::{InferOk, InferResult};
1313use rustc_macros:: { TypeFoldable , TypeVisitable } ;
1414use rustc_middle:: ty:: subst:: InternalSubsts ;
1515use rustc_middle:: ty:: visit:: TypeVisitable ;
16- use rustc_middle:: ty:: { self , Ty } ;
16+ use rustc_middle:: ty:: { self , Ty , TypeSuperVisitable , TypeVisitor } ;
1717use rustc_span:: source_map:: Span ;
1818use rustc_target:: spec:: abi:: Abi ;
1919use rustc_trait_selection:: traits;
2020use rustc_trait_selection:: traits:: error_reporting:: ArgKind ;
2121use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt as _;
2222use std:: cmp;
2323use std:: iter;
24+ use std:: ops:: ControlFlow ;
2425
2526/// What signature do we *expect* the closure to have from context?
2627#[ derive( Debug , Clone , TypeFoldable , TypeVisitable ) ]
@@ -54,7 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5455 // closure sooner rather than later, so first examine the expected
5556 // type, and see if can glean a closure kind from there.
5657 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) ,
5859 None => ( None , None ) ,
5960 } ;
6061 let body = self . tcx . hir ( ) . body ( closure. body ) ;
@@ -162,13 +163,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
162163 /// Given the expected type, figures out what it can about this closure we
163164 /// are about to type check:
164165 #[ instrument( skip( self ) , level = "debug" ) ]
165- fn deduce_expectations_from_expected_type (
166+ fn deduce_closure_signature (
166167 & self ,
167168 expected_ty : Ty < ' tcx > ,
168169 ) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
169170 match * expected_ty. kind ( ) {
170171 ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => self
171- . deduce_signature_from_predicates (
172+ . deduce_closure_signature_from_predicates (
173+ expected_ty,
172174 self . tcx . bound_explicit_item_bounds ( def_id) . subst_iter_copied ( self . tcx , substs) ,
173175 ) ,
174176 ty:: Dynamic ( ref object_type, ..) => {
@@ -181,7 +183,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
181183 . and_then ( |did| self . tcx . fn_trait_kind_from_def_id ( did) ) ;
182184 ( sig, kind)
183185 }
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) ) ,
185188 self . obligations_for_self_ty ( vid) . map ( |obl| ( obl. predicate , obl. cause . span ) ) ,
186189 ) ,
187190 ty:: FnPtr ( sig) => {
@@ -192,8 +195,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
192195 }
193196 }
194197
195- fn deduce_signature_from_predicates (
198+ fn deduce_closure_signature_from_predicates (
196199 & self ,
200+ expected_ty : Ty < ' tcx > ,
197201 predicates : impl DoubleEndedIterator < Item = ( ty:: Predicate < ' tcx > , Span ) > ,
198202 ) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
199203 let mut expected_sig = None ;
@@ -214,13 +218,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
214218 if expected_sig. is_none ( )
215219 && let ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( proj_predicate) ) = bound_predicate. skip_binder ( )
216220 {
217- expected_sig = self . normalize (
221+ let inferred_sig = self . normalize (
218222 obligation. cause . span ,
219223 self . deduce_sig_from_projection (
220224 Some ( obligation. cause . span ) ,
221225 bound_predicate. rebind ( proj_predicate) ,
222226 ) ,
223227 ) ;
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+ }
224248 }
225249
226250 // Even if we can't infer the full signature, we may be able to
0 commit comments