1+ use std:: ops:: ControlFlow ;
2+
3+ use hir:: def:: DefKind ;
4+ use rustc_data_structures:: fx:: FxHashSet ;
15use rustc_errors:: { Applicability , StashKey } ;
26use rustc_hir as hir;
37use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -9,15 +13,15 @@ use rustc_middle::ty::print::with_forced_trimmed_paths;
913use rustc_middle:: ty:: subst:: InternalSubsts ;
1014use rustc_middle:: ty:: util:: IntTypeExt ;
1115use rustc_middle:: ty:: {
12- self , ImplTraitInTraitData , IsSuggestable , Ty , TyCtxt , TypeFolder , TypeSuperFoldable ,
13- TypeVisitableExt ,
16+ self , ImplTraitInTraitData , IsSuggestable , Ty , TyCtxt , TypeFoldable , TypeFolder ,
17+ TypeSuperFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
1418} ;
1519use rustc_span:: symbol:: Ident ;
1620use rustc_span:: { Span , DUMMY_SP } ;
1721
1822use super :: ItemCtxt ;
1923use super :: { bad_placeholder, is_suggestable_infer_ty} ;
20- use crate :: errors:: UnconstrainedOpaqueType ;
24+ use crate :: errors:: { OpaqueTypeConstrainedButNotInSig , UnconstrainedOpaqueType } ;
2125
2226/// Computes the relevant generic parameter for a potential generic const argument.
2327///
@@ -635,6 +639,12 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
635639 let concrete_opaque_types = & self . tcx . mir_borrowck ( item_def_id) . concrete_opaque_types ;
636640 debug ! ( ?concrete_opaque_types) ;
637641 if let Some ( & concrete_type) = concrete_opaque_types. get ( & self . def_id ) {
642+ if !may_define_opaque_type ( self . tcx , item_def_id, self . def_id ) {
643+ self . tcx . sess . emit_err ( OpaqueTypeConstrainedButNotInSig {
644+ span : concrete_type. span ,
645+ item_span : self . tcx . def_span ( item_def_id) ,
646+ } ) ;
647+ }
638648 debug ! ( ?concrete_type, "found constraint" ) ;
639649 if let Some ( prev) = & mut self . found {
640650 if concrete_type. ty != prev. ty && !( concrete_type, prev. ty ) . references_error ( ) {
@@ -743,6 +753,117 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
743753 hidden. ty
744754}
745755
756+ #[ instrument( skip( tcx) , level = "trace" , ret) ]
757+ fn may_define_opaque_type < ' tcx > (
758+ tcx : TyCtxt < ' tcx > ,
759+ def_id : LocalDefId ,
760+ opaque_def_id : LocalDefId ,
761+ ) -> bool {
762+ if tcx. is_descendant_of ( opaque_def_id. to_def_id ( ) , def_id. to_def_id ( ) ) {
763+ // If the opaque type is defined in the body of a function, that function
764+ // may constrain the opaque type since it can't mention it in bounds.
765+ return true ;
766+ }
767+
768+ if tcx. is_closure ( def_id. to_def_id ( ) ) {
769+ return may_define_opaque_type ( tcx, tcx. local_parent ( def_id) , opaque_def_id) ;
770+ }
771+
772+ let param_env = tcx. param_env ( def_id) ;
773+
774+ trace ! ( parent = ?tcx. parent( opaque_def_id. to_def_id( ) ) ) ;
775+ fn has_tait < ' tcx > (
776+ val : impl TypeVisitable < TyCtxt < ' tcx > > ,
777+ opaque_def_id : LocalDefId ,
778+ tcx : TyCtxt < ' tcx > ,
779+ param_env : ty:: ParamEnv < ' tcx > ,
780+ ) -> bool {
781+ struct Visitor < ' tcx > {
782+ opaque_def_id : DefId ,
783+ tcx : TyCtxt < ' tcx > ,
784+ seen : FxHashSet < Ty < ' tcx > > ,
785+ param_env : ty:: ParamEnv < ' tcx > ,
786+ }
787+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for Visitor < ' tcx > {
788+ type BreakTy = ( ) ;
789+
790+ #[ instrument( skip( self ) , level = "trace" , ret) ]
791+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
792+ // Erase all lifetimes, they can't affect anything, but recursion
793+ // may cause late bound regions to differ, because the type visitor
794+ // can't erase them in `visit_binder`.
795+ let t = t. fold_with ( & mut ty:: fold:: BottomUpFolder {
796+ tcx : self . tcx ,
797+ ct_op : |c| c,
798+ ty_op : |t| t,
799+ lt_op : |_| self . tcx . lifetimes . re_erased ,
800+ } ) ;
801+ if !self . seen . insert ( t) {
802+ return ControlFlow :: Continue ( ( ) ) ;
803+ }
804+ match t. kind ( ) {
805+ ty:: Alias ( ty:: Opaque , alias) => {
806+ if alias. def_id == self . opaque_def_id {
807+ return ControlFlow :: Break ( ( ) ) ;
808+ }
809+ for ( pred, _span) in self
810+ . tcx
811+ . bound_explicit_item_bounds ( alias. def_id )
812+ . subst_iter_copied ( self . tcx , alias. substs )
813+ {
814+ pred. visit_with ( self ) ?;
815+ }
816+ }
817+ ty:: Alias ( ty:: Projection , _) => {
818+ if let Ok ( proj) = self . tcx . try_normalize_erasing_regions ( self . param_env , t)
819+ {
820+ proj. visit_with ( self ) ?;
821+ }
822+ }
823+ // Types that have opaque type fields must get walked manually, they
824+ // would not be seen by the type visitor otherwise.
825+ ty:: Adt ( adt_def, substs) => {
826+ for variant in adt_def. variants ( ) {
827+ for field in & variant. fields {
828+ field. ty ( self . tcx , substs) . visit_with ( self ) ?;
829+ }
830+ }
831+ }
832+ _ => ( ) ,
833+ }
834+ t. super_visit_with ( self )
835+ }
836+ }
837+ val. visit_with ( & mut Visitor {
838+ opaque_def_id : opaque_def_id. to_def_id ( ) ,
839+ tcx,
840+ seen : Default :: default ( ) ,
841+ param_env,
842+ } )
843+ . is_break ( )
844+ }
845+ let tait_in_fn_sig = match tcx. def_kind ( def_id) {
846+ DefKind :: AssocFn | DefKind :: Fn => {
847+ has_tait ( tcx. fn_sig ( def_id. to_def_id ( ) ) . skip_binder ( ) , opaque_def_id, tcx, param_env)
848+ }
849+ // Opaque types in types of contsts
850+ DefKind :: Static ( _) | DefKind :: Const | DefKind :: AssocConst => {
851+ has_tait ( tcx. type_of ( def_id. to_def_id ( ) ) . skip_binder ( ) , opaque_def_id, tcx, param_env)
852+ }
853+ // Nested opaque types
854+ DefKind :: OpaqueTy => has_tait (
855+ tcx. bound_explicit_item_bounds ( def_id. to_def_id ( ) ) . skip_binder ( ) ,
856+ opaque_def_id,
857+ tcx,
858+ param_env,
859+ ) ,
860+ _ => false ,
861+ } ;
862+ trace ! ( ?tait_in_fn_sig) ;
863+ tait_in_fn_sig
864+ || has_tait ( tcx. predicates_of ( def_id. to_def_id ( ) ) . predicates , opaque_def_id, tcx, param_env)
865+ }
866+
746867fn find_opaque_ty_constraints_for_rpit (
747868 tcx : TyCtxt < ' _ > ,
748869 def_id : LocalDefId ,
0 commit comments