@@ -335,37 +335,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
335
335
tcx. mk_adt ( def, substs)
336
336
}
337
337
ItemKind :: OpaqueTy ( OpaqueTy { origin : hir:: OpaqueTyOrigin :: TyAlias , .. } ) => {
338
- find_opaque_ty_constraints ( tcx, def_id)
338
+ find_opaque_ty_constraints_for_tait ( tcx, def_id)
339
339
}
340
340
// Opaque types desugared from `impl Trait`.
341
341
ItemKind :: OpaqueTy ( OpaqueTy { origin : hir:: OpaqueTyOrigin :: FnReturn ( owner) | hir:: OpaqueTyOrigin :: AsyncFn ( owner) , .. } ) => {
342
- let concrete_ty = tcx
343
- . mir_borrowck ( owner)
344
- . concrete_opaque_types
345
- . get ( & def_id)
346
- . copied ( )
347
- . map ( |concrete| concrete. ty )
348
- . unwrap_or_else ( || {
349
- let table = tcx. typeck ( owner) ;
350
- if let Some ( _) = table. tainted_by_errors {
351
- // Some error in the
352
- // owner fn prevented us from populating
353
- // the `concrete_opaque_types` table.
354
- tcx. ty_error ( )
355
- } else {
356
- table. concrete_opaque_types . get ( & def_id) . copied ( ) . unwrap_or_else ( || {
357
- // We failed to resolve the opaque type or it
358
- // resolves to itself. We interpret this as the
359
- // no values of the hidden type ever being constructed,
360
- // so we can just make the hidden type be `!`.
361
- // For backwards compatibility reasons, we fall back to
362
- // `()` until we the diverging default is changed.
363
- Some ( tcx. mk_diverging_default ( ) )
364
- } ) . expect ( "RPIT always have a hidden type from typeck" )
365
- }
366
- } ) ;
367
- debug ! ( "concrete_ty = {:?}" , concrete_ty) ;
368
- concrete_ty
342
+ find_opaque_ty_constraints_for_rpit ( tcx, def_id, owner)
369
343
}
370
344
ItemKind :: Trait ( ..)
371
345
| ItemKind :: TraitAlias ( ..)
@@ -519,7 +493,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
519
493
/// fn b<T>() -> Foo<T, u32> { .. }
520
494
/// ```
521
495
///
522
- fn find_opaque_ty_constraints ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Ty < ' _ > {
496
+ fn find_opaque_ty_constraints_for_tait ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Ty < ' _ > {
523
497
use rustc_hir:: { Expr , ImplItem , Item , TraitItem } ;
524
498
525
499
struct ConstraintLocator < ' tcx > {
@@ -660,6 +634,122 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
660
634
}
661
635
}
662
636
637
+ fn find_opaque_ty_constraints_for_rpit (
638
+ tcx : TyCtxt < ' _ > ,
639
+ def_id : LocalDefId ,
640
+ owner_def_id : LocalDefId ,
641
+ ) -> Ty < ' _ > {
642
+ use rustc_hir:: { Expr , ImplItem , Item , TraitItem } ;
643
+
644
+ struct ConstraintChecker < ' tcx > {
645
+ tcx : TyCtxt < ' tcx > ,
646
+
647
+ /// def_id of the opaque type whose defining uses are being checked
648
+ def_id : LocalDefId ,
649
+
650
+ found : ty:: OpaqueHiddenType < ' tcx > ,
651
+ }
652
+
653
+ impl ConstraintChecker < ' _ > {
654
+ #[ instrument( skip( self ) , level = "debug" ) ]
655
+ fn check ( & self , def_id : LocalDefId ) {
656
+ // Use borrowck to get the type with unerased regions.
657
+ let concrete_opaque_types = & self . tcx . mir_borrowck ( def_id) . concrete_opaque_types ;
658
+ debug ! ( ?concrete_opaque_types) ;
659
+ for & ( def_id, concrete_type) in concrete_opaque_types {
660
+ if def_id != self . def_id {
661
+ // Ignore constraints for other opaque types.
662
+ continue ;
663
+ }
664
+
665
+ debug ! ( ?concrete_type, "found constraint" ) ;
666
+
667
+ if concrete_type. ty != self . found . ty
668
+ && !( concrete_type, self . found ) . references_error ( )
669
+ {
670
+ self . found . report_mismatch ( & concrete_type, self . tcx ) ;
671
+ }
672
+ }
673
+ }
674
+ }
675
+
676
+ impl < ' tcx > intravisit:: Visitor < ' tcx > for ConstraintChecker < ' tcx > {
677
+ type NestedFilter = nested_filter:: OnlyBodies ;
678
+
679
+ fn nested_visit_map ( & mut self ) -> Self :: Map {
680
+ self . tcx . hir ( )
681
+ }
682
+ fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
683
+ if let hir:: ExprKind :: Closure { .. } = ex. kind {
684
+ let def_id = self . tcx . hir ( ) . local_def_id ( ex. hir_id ) ;
685
+ self . check ( def_id) ;
686
+ }
687
+ intravisit:: walk_expr ( self , ex) ;
688
+ }
689
+ fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
690
+ trace ! ( ?it. def_id) ;
691
+ // The opaque type itself or its children are not within its reveal scope.
692
+ if it. def_id != self . def_id {
693
+ self . check ( it. def_id ) ;
694
+ intravisit:: walk_item ( self , it) ;
695
+ }
696
+ }
697
+ fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
698
+ trace ! ( ?it. def_id) ;
699
+ // The opaque type itself or its children are not within its reveal scope.
700
+ if it. def_id != self . def_id {
701
+ self . check ( it. def_id ) ;
702
+ intravisit:: walk_impl_item ( self , it) ;
703
+ }
704
+ }
705
+ fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
706
+ trace ! ( ?it. def_id) ;
707
+ self . check ( it. def_id ) ;
708
+ intravisit:: walk_trait_item ( self , it) ;
709
+ }
710
+ }
711
+
712
+ let concrete = tcx. mir_borrowck ( owner_def_id) . concrete_opaque_types . get ( & def_id) . copied ( ) ;
713
+
714
+ if let Some ( concrete) = concrete {
715
+ let scope = tcx. hir ( ) . local_def_id_to_hir_id ( owner_def_id) ;
716
+ debug ! ( ?scope) ;
717
+ let mut locator = ConstraintChecker { def_id : def_id, tcx, found : concrete } ;
718
+
719
+ match tcx. hir ( ) . get ( scope) {
720
+ Node :: Item ( it) => intravisit:: walk_item ( & mut locator, it) ,
721
+ Node :: ImplItem ( it) => intravisit:: walk_impl_item ( & mut locator, it) ,
722
+ Node :: TraitItem ( it) => intravisit:: walk_trait_item ( & mut locator, it) ,
723
+ other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
724
+ }
725
+ }
726
+
727
+ concrete. map ( |concrete| concrete. ty ) . unwrap_or_else ( || {
728
+ let table = tcx. typeck ( owner_def_id) ;
729
+ if let Some ( _) = table. tainted_by_errors {
730
+ // Some error in the
731
+ // owner fn prevented us from populating
732
+ // the `concrete_opaque_types` table.
733
+ tcx. ty_error ( )
734
+ } else {
735
+ table
736
+ . concrete_opaque_types
737
+ . get ( & def_id)
738
+ . copied ( )
739
+ . unwrap_or_else ( || {
740
+ // We failed to resolve the opaque type or it
741
+ // resolves to itself. We interpret this as the
742
+ // no values of the hidden type ever being constructed,
743
+ // so we can just make the hidden type be `!`.
744
+ // For backwards compatibility reasons, we fall back to
745
+ // `()` until we the diverging default is changed.
746
+ Some ( tcx. mk_diverging_default ( ) )
747
+ } )
748
+ . expect ( "RPIT always have a hidden type from typeck" )
749
+ }
750
+ } )
751
+ }
752
+
663
753
fn infer_placeholder_type < ' a > (
664
754
tcx : TyCtxt < ' a > ,
665
755
def_id : LocalDefId ,
0 commit comments