@@ -335,37 +335,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
335335 tcx. mk_adt ( def, substs)
336336 }
337337 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)
339339 }
340340 // Opaque types desugared from `impl Trait`.
341341 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)
369343 }
370344 ItemKind :: Trait ( ..)
371345 | ItemKind :: TraitAlias ( ..)
@@ -519,7 +493,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
519493/// fn b<T>() -> Foo<T, u32> { .. }
520494/// ```
521495///
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 < ' _ > {
523497 use rustc_hir:: { Expr , ImplItem , Item , TraitItem } ;
524498
525499 struct ConstraintLocator < ' tcx > {
@@ -660,6 +634,122 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
660634 }
661635}
662636
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+
663753fn infer_placeholder_type < ' a > (
664754 tcx : TyCtxt < ' a > ,
665755 def_id : LocalDefId ,
0 commit comments