@@ -10,12 +10,13 @@ use rustc_hir as hir;
1010use rustc_middle:: traits:: ObligationCause ;
1111use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
1212use rustc_middle:: ty:: fold:: BottomUpFolder ;
13- use rustc_middle:: ty:: GenericArgKind ;
1413use rustc_middle:: ty:: {
1514 self , OpaqueHiddenType , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable , TypeSuperVisitable ,
1615 TypeVisitable , TypeVisitor ,
1716} ;
17+ use rustc_middle:: ty:: { DefIdTree , GenericArgKind } ;
1818use rustc_span:: Span ;
19+ use smallvec:: SmallVec ;
1920
2021use std:: ops:: ControlFlow ;
2122
@@ -59,7 +60,7 @@ impl<'tcx> InferCtxt<'tcx> {
5960 let replace_opaque_type = |def_id : DefId | {
6061 def_id
6162 . as_local ( )
62- . map_or ( false , |def_id| self . opaque_type_origin ( def_id, span) . is_some ( ) )
63+ . map_or ( false , |def_id| self . opaque_type_origin ( def_id, span, param_env ) . is_some ( ) )
6364 } ;
6465 let value = value. fold_with ( & mut BottomUpFolder {
6566 tcx : self . tcx ,
@@ -144,7 +145,7 @@ impl<'tcx> InferCtxt<'tcx> {
144145 // let x = || foo(); // returns the Opaque assoc with `foo`
145146 // }
146147 // ```
147- self . opaque_type_origin ( def_id, cause. span ) ?
148+ self . opaque_type_origin ( def_id, cause. span , param_env ) ?
148149 }
149150 DefiningAnchor :: Bubble => self . opaque_ty_origin_unchecked ( def_id, cause. span ) ,
150151 DefiningAnchor :: Error => return None ,
@@ -155,9 +156,10 @@ impl<'tcx> InferCtxt<'tcx> {
155156 // no one encounters it in practice.
156157 // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
157158 // where it is of no concern, so we only check for TAITs.
158- if let Some ( OpaqueTyOrigin :: TyAlias ) = b_def_id
159- . as_local ( )
160- . and_then ( |b_def_id| self . opaque_type_origin ( b_def_id, cause. span ) )
159+ if let Some ( OpaqueTyOrigin :: TyAlias ) =
160+ b_def_id. as_local ( ) . and_then ( |b_def_id| {
161+ self . opaque_type_origin ( b_def_id, cause. span , param_env)
162+ } )
161163 {
162164 self . tcx . sess . emit_err ( OpaqueHiddenTypeDiag {
163165 span : cause. span ,
@@ -372,7 +374,12 @@ impl<'tcx> InferCtxt<'tcx> {
372374 }
373375
374376 #[ instrument( skip( self ) , level = "trace" , ret) ]
375- pub fn opaque_type_origin ( & self , def_id : LocalDefId , span : Span ) -> Option < OpaqueTyOrigin > {
377+ pub fn opaque_type_origin (
378+ & self ,
379+ def_id : LocalDefId ,
380+ span : Span ,
381+ param_env : ty:: ParamEnv < ' tcx > ,
382+ ) -> Option < OpaqueTyOrigin > {
376383 let opaque_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( def_id) ;
377384 let parent_def_id = match self . defining_use_anchor {
378385 DefiningAnchor :: Bubble | DefiningAnchor :: Error => return None ,
@@ -395,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> {
395402 hir:: OpaqueTyOrigin :: FnReturn ( parent) => parent == parent_def_id,
396403 // Named `type Foo = impl Bar;`
397404 hir:: OpaqueTyOrigin :: TyAlias => {
398- may_define_opaque_type ( self . tcx , parent_def_id, opaque_hir_id)
405+ may_define_opaque_type ( self . tcx , parent_def_id, opaque_hir_id, def_id , param_env )
399406 }
400407 } ;
401408 trace ! ( ?origin) ;
@@ -639,11 +646,123 @@ impl<'tcx> InferCtxt<'tcx> {
639646/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
640647/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
641648/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
642- fn may_define_opaque_type ( tcx : TyCtxt < ' _ > , def_id : LocalDefId , opaque_hir_id : hir:: HirId ) -> bool {
649+ #[ instrument( skip( tcx) , level = "trace" , ret) ]
650+ fn may_define_opaque_type < ' tcx > (
651+ tcx : TyCtxt < ' tcx > ,
652+ def_id : LocalDefId ,
653+ opaque_hir_id : hir:: HirId ,
654+ opaque_def_id : LocalDefId ,
655+ param_env : ty:: ParamEnv < ' tcx > ,
656+ ) -> bool {
643657 let mut hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
644658
645659 // Named opaque types can be defined by any siblings or children of siblings.
646660 let scope = tcx. hir ( ) . get_defining_scope ( opaque_hir_id) ;
661+
662+ // When doing checks within the opaque type itself
663+ if def_id != opaque_def_id
664+ // When the opaque type is defined in the body of a function, the function may access it.
665+ && hir_id != scope
666+ {
667+ trace ! ( parent = ?tcx. parent( opaque_def_id. to_def_id( ) ) ) ;
668+ fn has_tait < ' tcx > (
669+ val : impl TypeVisitable < ' tcx > ,
670+ opaque_def_id : LocalDefId ,
671+ tcx : TyCtxt < ' tcx > ,
672+ param_env : ty:: ParamEnv < ' tcx > ,
673+ ) -> bool {
674+ struct Visitor < ' tcx > {
675+ opaque_def_id : DefId ,
676+ tcx : TyCtxt < ' tcx > ,
677+ ignore_nested : SmallVec < [ DefId ; 1 ] > ,
678+ param_env : ty:: ParamEnv < ' tcx > ,
679+ }
680+ impl < ' tcx > TypeVisitor < ' tcx > for Visitor < ' tcx > {
681+ type BreakTy = ( ) ;
682+ #[ instrument( skip( self ) , level = "trace" , ret) ]
683+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
684+ match t. kind ( ) {
685+ ty:: Alias ( ty:: Opaque , alias) => {
686+ if alias. def_id == self . opaque_def_id {
687+ return ControlFlow :: Break ( ( ) ) ;
688+ }
689+ if !self . ignore_nested . contains ( & alias. def_id ) {
690+ // avoid infinite recursion since the opaque type shows
691+ // up in its own bounds.
692+ self . ignore_nested . push ( alias. def_id ) ;
693+ for ( pred, _span) in self
694+ . tcx
695+ . bound_explicit_item_bounds ( alias. def_id )
696+ . subst_iter_copied ( self . tcx , alias. substs )
697+ {
698+ pred. visit_with ( self ) ?;
699+ }
700+ }
701+ }
702+ ty:: Alias ( ty:: Projection , _) => {
703+ if let Ok ( proj) =
704+ self . tcx . try_normalize_erasing_regions ( self . param_env , t)
705+ {
706+ proj. visit_with ( self ) ?;
707+ }
708+ }
709+ // Types that have opaque type fields must get walked manually, they
710+ // would not be seen by the type visitor otherwise.
711+ ty:: Adt ( adt_def, substs) => {
712+ if !self . ignore_nested . contains ( & adt_def. did ( ) ) {
713+ // avoid infinite recursion since adts can recursively refer
714+ // to themselves
715+ self . ignore_nested . push ( adt_def. did ( ) ) ;
716+ for variant in adt_def. variants ( ) {
717+ for field in & variant. fields {
718+ field. ty ( self . tcx , substs) . visit_with ( self ) ?;
719+ }
720+ }
721+ }
722+ }
723+ _ => ( ) ,
724+ }
725+ t. super_visit_with ( self )
726+ }
727+ }
728+ val. visit_with ( & mut Visitor {
729+ opaque_def_id : opaque_def_id. to_def_id ( ) ,
730+ tcx,
731+ ignore_nested : SmallVec :: new ( ) ,
732+ param_env,
733+ } )
734+ . is_break ( )
735+ }
736+ let tait_in_fn_sig = match tcx. def_kind ( def_id) {
737+ DefKind :: AssocFn | DefKind :: Fn => {
738+ has_tait ( tcx. fn_sig ( def_id. to_def_id ( ) ) , opaque_def_id, tcx, param_env)
739+ }
740+ // Opaque types in types of contsts
741+ DefKind :: Static ( _) | DefKind :: Const | DefKind :: AssocConst => {
742+ has_tait ( tcx. type_of ( def_id. to_def_id ( ) ) , opaque_def_id, tcx, param_env)
743+ }
744+ // Nested opaque types
745+ DefKind :: OpaqueTy => has_tait (
746+ tcx. bound_explicit_item_bounds ( def_id. to_def_id ( ) ) . skip_binder ( ) ,
747+ opaque_def_id,
748+ tcx,
749+ param_env,
750+ ) ,
751+ _ => false ,
752+ } ;
753+ trace ! ( ?tait_in_fn_sig) ;
754+ if !tait_in_fn_sig
755+ && !has_tait (
756+ tcx. predicates_of ( def_id. to_def_id ( ) ) . predicates ,
757+ opaque_def_id,
758+ tcx,
759+ param_env,
760+ )
761+ {
762+ return false ;
763+ }
764+ }
765+
647766 // We walk up the node tree until we hit the root or the scope of the opaque type.
648767 while hir_id != scope && hir_id != hir:: CRATE_HIR_ID {
649768 hir_id = tcx. hir ( ) . get_parent_item ( hir_id) . into ( ) ;
0 commit comments