@@ -10,12 +10,13 @@ use rustc_hir as hir;
10
10
use rustc_middle:: traits:: ObligationCause ;
11
11
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
12
12
use rustc_middle:: ty:: fold:: BottomUpFolder ;
13
- use rustc_middle:: ty:: GenericArgKind ;
14
13
use rustc_middle:: ty:: {
15
14
self , OpaqueHiddenType , OpaqueTypeKey , Ty , TyCtxt , TypeFoldable , TypeSuperVisitable ,
16
15
TypeVisitable , TypeVisitor ,
17
16
} ;
17
+ use rustc_middle:: ty:: { DefIdTree , GenericArgKind } ;
18
18
use rustc_span:: Span ;
19
+ use smallvec:: SmallVec ;
19
20
20
21
use std:: ops:: ControlFlow ;
21
22
@@ -59,7 +60,7 @@ impl<'tcx> InferCtxt<'tcx> {
59
60
let replace_opaque_type = |def_id : DefId | {
60
61
def_id
61
62
. 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 ( ) )
63
64
} ;
64
65
let value = value. fold_with ( & mut BottomUpFolder {
65
66
tcx : self . tcx ,
@@ -144,7 +145,7 @@ impl<'tcx> InferCtxt<'tcx> {
144
145
// let x = || foo(); // returns the Opaque assoc with `foo`
145
146
// }
146
147
// ```
147
- self . opaque_type_origin ( def_id, cause. span ) ?
148
+ self . opaque_type_origin ( def_id, cause. span , param_env ) ?
148
149
}
149
150
DefiningAnchor :: Bubble => self . opaque_ty_origin_unchecked ( def_id, cause. span ) ,
150
151
DefiningAnchor :: Error => return None ,
@@ -155,9 +156,10 @@ impl<'tcx> InferCtxt<'tcx> {
155
156
// no one encounters it in practice.
156
157
// It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
157
158
// 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
+ } )
161
163
{
162
164
self . tcx . sess . emit_err ( OpaqueHiddenTypeDiag {
163
165
span : cause. span ,
@@ -372,7 +374,12 @@ impl<'tcx> InferCtxt<'tcx> {
372
374
}
373
375
374
376
#[ 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 > {
376
383
let opaque_hir_id = self . tcx . hir ( ) . local_def_id_to_hir_id ( def_id) ;
377
384
let parent_def_id = match self . defining_use_anchor {
378
385
DefiningAnchor :: Bubble | DefiningAnchor :: Error => return None ,
@@ -395,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> {
395
402
hir:: OpaqueTyOrigin :: FnReturn ( parent) => parent == parent_def_id,
396
403
// Named `type Foo = impl Bar;`
397
404
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 )
399
406
}
400
407
} ;
401
408
trace ! ( ?origin) ;
@@ -639,11 +646,123 @@ impl<'tcx> InferCtxt<'tcx> {
639
646
/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
640
647
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
641
648
/// 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 {
643
657
let mut hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
644
658
645
659
// Named opaque types can be defined by any siblings or children of siblings.
646
660
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
+
647
766
// We walk up the node tree until we hit the root or the scope of the opaque type.
648
767
while hir_id != scope && hir_id != hir:: CRATE_HIR_ID {
649
768
hir_id = tcx. hir ( ) . get_parent_item ( hir_id) . into ( ) ;
0 commit comments