@@ -19,11 +19,13 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
19
19
use rustc_middle:: hir:: nested_filter;
20
20
use rustc_middle:: middle:: stability:: EvalResult ;
21
21
use rustc_middle:: traits:: DefiningAnchor ;
22
+ use rustc_middle:: ty:: fold:: BottomUpFolder ;
22
23
use rustc_middle:: ty:: layout:: { LayoutError , MAX_SIMD_LANES } ;
23
24
use rustc_middle:: ty:: util:: { Discr , IntTypeExt } ;
24
25
use rustc_middle:: ty:: GenericArgKind ;
25
26
use rustc_middle:: ty:: {
26
- self , AdtDef , ParamEnv , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt ,
27
+ self , AdtDef , ParamEnv , RegionKind , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable ,
28
+ TypeVisitableExt ,
27
29
} ;
28
30
use rustc_session:: lint:: builtin:: { UNINHABITED_STATIC , UNSUPPORTED_CALLING_CONVENTIONS } ;
29
31
use rustc_span:: symbol:: sym;
@@ -34,6 +36,7 @@ use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplem
34
36
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt as _;
35
37
use rustc_trait_selection:: traits:: outlives_bounds:: InferCtxtExt as _;
36
38
use rustc_trait_selection:: traits:: { self , ObligationCtxt , TraitEngine , TraitEngineExt as _} ;
39
+ use rustc_type_ir:: fold:: TypeFoldable ;
37
40
38
41
use std:: ops:: ControlFlow ;
39
42
@@ -437,7 +440,7 @@ fn check_opaque_meets_bounds<'tcx>(
437
440
// hidden type is well formed even without those bounds.
438
441
let predicate =
439
442
ty:: Binder :: dummy ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( hidden_ty. into ( ) ) ) ) ;
440
- ocx. register_obligation ( Obligation :: new ( tcx, misc_cause, param_env, predicate) ) ;
443
+ ocx. register_obligation ( Obligation :: new ( tcx, misc_cause. clone ( ) , param_env, predicate) ) ;
441
444
442
445
// Check that all obligations are satisfied by the implementation's
443
446
// version.
@@ -464,11 +467,143 @@ fn check_opaque_meets_bounds<'tcx>(
464
467
ocx. resolve_regions_and_report_errors ( defining_use_anchor, & outlives_env) ?;
465
468
}
466
469
}
467
- // Clean up after ourselves
468
- let _ = infcx. take_opaque_types ( ) ;
470
+ // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
471
+ for ( key, mut ty) in infcx. take_opaque_types ( ) {
472
+ ty. hidden_type . ty = infcx. resolve_vars_if_possible ( ty. hidden_type . ty ) ;
473
+ sanity_check_found_hidden_type ( tcx, key, ty. hidden_type , defining_use_anchor, origin) ?;
474
+ }
469
475
Ok ( ( ) )
470
476
}
471
477
478
+ fn sanity_check_found_hidden_type < ' tcx > (
479
+ tcx : TyCtxt < ' tcx > ,
480
+ key : ty:: OpaqueTypeKey < ' tcx > ,
481
+ mut ty : ty:: OpaqueHiddenType < ' tcx > ,
482
+ defining_use_anchor : LocalDefId ,
483
+ origin : & hir:: OpaqueTyOrigin ,
484
+ ) -> Result < ( ) , ErrorGuaranteed > {
485
+ if ty. ty . is_ty_var ( ) {
486
+ // Nothing was actually constrained.
487
+ return Ok ( ( ) ) ;
488
+ }
489
+ if let ty:: Alias ( ty:: Opaque , alias) = ty. ty . kind ( ) {
490
+ if alias. def_id == key. def_id . to_def_id ( ) && alias. args == key. args {
491
+ // Nothing was actually constrained, this is an opaque usage that was
492
+ // only discovered to be opaque after inference vars resolved.
493
+ return Ok ( ( ) ) ;
494
+ }
495
+ }
496
+ // Closures frequently end up containing erased lifetimes in their final representation.
497
+ // These correspond to lifetime variables that never got resolved, so we patch this up here.
498
+ ty. ty = ty. ty . fold_with ( & mut BottomUpFolder {
499
+ tcx,
500
+ ty_op : |t| t,
501
+ ct_op : |c| c,
502
+ lt_op : |l| match l. kind ( ) {
503
+ RegionKind :: ReVar ( _) => tcx. lifetimes . re_erased ,
504
+ _ => l,
505
+ } ,
506
+ } ) ;
507
+ // Get the hidden type, and in case it is in a nested opaque type, find that opaque type's
508
+ // usage in the function signature and use the generic arguments from the usage site.
509
+ let mut hidden_ty = tcx. type_of ( key. def_id ) . instantiate ( tcx, key. args ) ;
510
+ if let hir:: OpaqueTyOrigin :: FnReturn ( ..) | hir:: OpaqueTyOrigin :: AsyncFn ( ..) = origin {
511
+ if hidden_ty != ty. ty {
512
+ hidden_ty = find_and_apply_rpit_substs (
513
+ tcx,
514
+ hidden_ty,
515
+ defining_use_anchor. to_def_id ( ) ,
516
+ key. def_id . to_def_id ( ) ,
517
+ ) ?;
518
+ }
519
+ }
520
+ // If the hidden types differ, emit a type mismatch diagnostic.
521
+ if hidden_ty == ty. ty {
522
+ Ok ( ( ) )
523
+ } else {
524
+ let span = tcx. def_span ( key. def_id ) ;
525
+ let other = ty:: OpaqueHiddenType { ty : hidden_ty, span } ;
526
+ Err ( ty. report_mismatch ( & other, key. def_id , tcx) . emit ( ) )
527
+ }
528
+ }
529
+
530
+ fn find_and_apply_rpit_substs < ' tcx > (
531
+ tcx : TyCtxt < ' tcx > ,
532
+ mut hidden_ty : Ty < ' tcx > ,
533
+ function : DefId ,
534
+ opaque : DefId ,
535
+ ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
536
+ // Find use of the RPIT in the function signature and thus find the right substs to
537
+ // convert it into the parameter space of the function signature. This is needed,
538
+ // because that's what `type_of` returns, against which we compare later.
539
+ let ret = tcx. fn_sig ( function) . instantiate_identity ( ) . output ( ) ;
540
+ struct Visitor < ' tcx > {
541
+ tcx : TyCtxt < ' tcx > ,
542
+ opaque : DefId ,
543
+ function : DefId ,
544
+ seen : FxHashSet < DefId > ,
545
+ }
546
+ impl < ' tcx > ty:: TypeVisitor < TyCtxt < ' tcx > > for Visitor < ' tcx > {
547
+ type BreakTy = GenericArgsRef < ' tcx > ;
548
+
549
+ #[ instrument( level = "trace" , skip( self ) , ret) ]
550
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
551
+ trace ! ( "{:#?}" , t. kind( ) ) ;
552
+ match t. kind ( ) {
553
+ ty:: Alias ( ty:: Opaque , alias) => {
554
+ trace ! ( ?alias. def_id) ;
555
+ if alias. def_id == self . opaque {
556
+ return ControlFlow :: Break ( alias. args ) ;
557
+ } else if self . seen . insert ( alias. def_id ) {
558
+ for clause in self
559
+ . tcx
560
+ . explicit_item_bounds ( alias. def_id )
561
+ . iter_instantiated_copied ( self . tcx , alias. args )
562
+ {
563
+ trace ! ( ?clause) ;
564
+ clause. visit_with ( self ) ?;
565
+ }
566
+ }
567
+ }
568
+ ty:: Alias ( ty:: Projection , alias) => {
569
+ if self . tcx . is_impl_trait_in_trait ( alias. def_id )
570
+ && self . tcx . impl_trait_in_trait_parent_fn ( alias. def_id ) == self . function
571
+ {
572
+ // If we're lowering to associated item, install the opaque type which is just
573
+ // the `type_of` of the trait's associated item. If we're using the old lowering
574
+ // strategy, then just reinterpret the associated type like an opaque :^)
575
+ self . tcx
576
+ . type_of ( alias. def_id )
577
+ . instantiate ( self . tcx , alias. args )
578
+ . visit_with ( self ) ?;
579
+ }
580
+ }
581
+ ty:: Alias ( ty:: Weak , alias) => {
582
+ self . tcx
583
+ . type_of ( alias. def_id )
584
+ . instantiate ( self . tcx , alias. args )
585
+ . visit_with ( self ) ?;
586
+ }
587
+ _ => ( ) ,
588
+ }
589
+
590
+ t. super_visit_with ( self )
591
+ }
592
+ }
593
+ if let ControlFlow :: Break ( args) =
594
+ ret. visit_with ( & mut Visitor { tcx, function, opaque, seen : Default :: default ( ) } )
595
+ {
596
+ trace ! ( ?args) ;
597
+ trace ! ( "expected: {hidden_ty:#?}" ) ;
598
+ hidden_ty = ty:: EarlyBinder :: bind ( hidden_ty) . instantiate ( tcx, args) ;
599
+ trace ! ( "expected: {hidden_ty:#?}" ) ;
600
+ } else {
601
+ tcx. sess
602
+ . delay_span_bug ( tcx. def_span ( function) , format ! ( "{ret:?} does not contain {opaque:?}" ) ) ;
603
+ }
604
+ Ok ( hidden_ty)
605
+ }
606
+
472
607
fn is_enum_of_nonnullable_ptr < ' tcx > (
473
608
tcx : TyCtxt < ' tcx > ,
474
609
adt_def : AdtDef < ' tcx > ,
0 commit comments