@@ -9,17 +9,18 @@ use rustc_hir as hir;
9
9
use rustc_hir:: lang_items:: LangItem ;
10
10
use rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ;
11
11
use rustc_infer:: infer:: { BoundRegionConversionTime , DefineOpaqueTypes , InferOk , InferResult } ;
12
- use rustc_infer:: traits:: { ObligationCauseCode , PredicateObligations } ;
12
+ use rustc_infer:: traits:: { ObligationCause , ObligationCauseCode , PredicateObligations } ;
13
13
use rustc_macros:: { TypeFoldable , TypeVisitable } ;
14
14
use rustc_middle:: span_bug;
15
+ use rustc_middle:: ty:: error:: TypeError ;
15
16
use rustc_middle:: ty:: {
16
- self , ClosureKind , GenericArgs , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable ,
17
- TypeVisitableExt , TypeVisitor ,
17
+ self , ClosureKind , GenericArgs , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable ,
18
+ TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
18
19
} ;
19
20
use rustc_span:: def_id:: LocalDefId ;
20
21
use rustc_span:: { DUMMY_SP , Span } ;
21
22
use rustc_trait_selection:: error_reporting:: traits:: ArgKind ;
22
- use rustc_trait_selection:: traits;
23
+ use rustc_trait_selection:: traits:: { self , ObligationCtxt } ;
23
24
use tracing:: { debug, instrument, trace} ;
24
25
25
26
use super :: { CoroutineTypes , Expectation , FnCtxt , check_fn} ;
@@ -384,56 +385,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
384
385
// Make sure that we didn't infer a signature that mentions itself.
385
386
// This can happen when we elaborate certain supertrait bounds that
386
387
// mention projections containing the `Self` type. See #105401.
387
- struct MentionsTy < ' tcx > {
388
- expected_ty : Ty < ' tcx > ,
389
- }
390
- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for MentionsTy < ' tcx > {
391
- type Result = ControlFlow < ( ) > ;
392
-
393
- fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> Self :: Result {
394
- if t == self . expected_ty {
395
- ControlFlow :: Break ( ( ) )
396
- } else {
397
- t. super_visit_with ( self )
398
- }
399
- }
400
- }
401
-
402
- // Don't infer a closure signature from a goal that names the closure type as this will
403
- // (almost always) lead to occurs check errors later in type checking.
388
+ //
389
+ // Doing so will (almost always) lead to occurs check errors later in
390
+ // type checking.
404
391
if self . next_trait_solver ( )
405
392
&& let Some ( inferred_sig) = inferred_sig
406
393
{
407
- // In the new solver it is difficult to explicitly normalize the inferred signature as we
408
- // would have to manually handle universes and rewriting bound vars and placeholders back
409
- // and forth.
410
- //
411
- // Instead we take advantage of the fact that we relating an inference variable with an alias
412
- // will only instantiate the variable if the alias is rigid(*not quite). Concretely we:
413
- // - Create some new variable `?sig`
414
- // - Equate `?sig` with the unnormalized signature, e.g. `fn(<Foo<?x> as Trait>::Assoc)`
415
- // - Depending on whether `<Foo<?x> as Trait>::Assoc` is rigid, ambiguous or normalizeable,
416
- // we will either wind up with `?sig=<Foo<?x> as Trait>::Assoc/?y/ConcreteTy` respectively.
417
- //
418
- // *: In cases where there are ambiguous aliases in the signature that make use of bound vars
419
- // they will wind up present in `?sig` even though they are non-rigid.
394
+ // If we've got `F: FnOnce(<u32 as Id<F>>::This)` we want to
395
+ // use this to infer the signature `FnOnce(u32)` for the closure.
420
396
//
421
- // This is a bit weird and means we may wind up discarding the goal due to it naming `expected_ty`
422
- // even though the normalized form may not name `expected_ty`. However, this matches the existing
423
- // behaviour of the old solver and would be technically a breaking change to fix.
397
+ // We handle self-referential aliases here by relying on generalization
398
+ // which replaces such aliases with inference variables. This is currently
399
+ // a bit too weak, see trait-system-refactor-initiative#191.
400
+ struct ReplaceTy < ' tcx > {
401
+ tcx : TyCtxt < ' tcx > ,
402
+ expected_ty : Ty < ' tcx > ,
403
+ with_ty : Ty < ' tcx > ,
404
+ }
405
+ impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for ReplaceTy < ' tcx > {
406
+ fn cx ( & self ) -> TyCtxt < ' tcx > {
407
+ self . tcx
408
+ }
409
+
410
+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
411
+ if t == self . expected_ty {
412
+ self . with_ty
413
+ } else {
414
+ t. super_fold_with ( self )
415
+ }
416
+ }
417
+ }
424
418
let generalized_fnptr_sig = self . next_ty_var ( span) ;
425
419
let inferred_fnptr_sig = Ty :: new_fn_ptr ( self . tcx , inferred_sig. sig ) ;
426
- self . demand_eqtype ( span, inferred_fnptr_sig, generalized_fnptr_sig) ;
427
-
428
- let resolved_sig = self . resolve_vars_if_possible ( generalized_fnptr_sig) ;
429
-
430
- if resolved_sig. visit_with ( & mut MentionsTy { expected_ty } ) . is_continue ( ) {
431
- expected_sig = Some ( ExpectedSig {
432
- cause_span : inferred_sig. cause_span ,
433
- sig : resolved_sig. fn_sig ( self . tcx ) ,
434
- } ) ;
420
+ let inferred_fnptr_sig = inferred_fnptr_sig. fold_with ( & mut ReplaceTy {
421
+ tcx : self . tcx ,
422
+ expected_ty,
423
+ with_ty : generalized_fnptr_sig,
424
+ } ) ;
425
+ let resolved_sig = self . fudge_inference_if_ok ( |snapshot| {
426
+ let outer_universe = self . universe ( ) ;
427
+ let ocx = ObligationCtxt :: new ( self ) ;
428
+ ocx. eq (
429
+ & ObligationCause :: dummy ( ) ,
430
+ self . param_env ,
431
+ generalized_fnptr_sig,
432
+ inferred_fnptr_sig,
433
+ ) ?;
434
+ if ocx. select_where_possible ( ) . is_empty ( ) {
435
+ self . leak_check ( outer_universe, Some ( snapshot) ) ?;
436
+ Ok ( self . resolve_vars_if_possible ( generalized_fnptr_sig) )
437
+ } else {
438
+ Err ( TypeError :: Mismatch )
439
+ }
440
+ } ) ;
441
+ match resolved_sig {
442
+ Ok ( resolved_sig) => {
443
+ expected_sig = Some ( ExpectedSig {
444
+ cause_span : inferred_sig. cause_span ,
445
+ sig : resolved_sig. fn_sig ( self . tcx ) ,
446
+ } )
447
+ }
448
+ Err ( _) => { }
435
449
}
436
450
} else {
451
+ struct MentionsTy < ' tcx > {
452
+ expected_ty : Ty < ' tcx > ,
453
+ }
454
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for MentionsTy < ' tcx > {
455
+ type Result = ControlFlow < ( ) > ;
456
+
457
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> Self :: Result {
458
+ if t == self . expected_ty {
459
+ ControlFlow :: Break ( ( ) )
460
+ } else {
461
+ t. super_visit_with ( self )
462
+ }
463
+ }
464
+ }
437
465
if inferred_sig. visit_with ( & mut MentionsTy { expected_ty } ) . is_continue ( ) {
438
466
expected_sig = inferred_sig;
439
467
}
0 commit comments