@@ -22,7 +22,9 @@ use rustc_span::{sym, Span, DUMMY_SP};
2222
2323use super :: ItemCtxt ;
2424use super :: { bad_placeholder, is_suggestable_infer_ty} ;
25- use crate :: errors:: { OpaqueTypeConstrainedButNotInSig , UnconstrainedOpaqueType } ;
25+ use crate :: errors:: {
26+ OpaqueTypeConstrainedButNotInSig , OpaqueTypeConstrainedInNonSibling , UnconstrainedOpaqueType ,
27+ } ;
2628
2729/// Computes the relevant generic parameter for a potential generic const argument.
2830///
@@ -640,13 +642,20 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
640642 let concrete_opaque_types = & self . tcx . mir_borrowck ( item_def_id) . concrete_opaque_types ;
641643 debug ! ( ?concrete_opaque_types) ;
642644 if let Some ( & concrete_type) = concrete_opaque_types. get ( & self . def_id ) {
643- if let Err ( item_def_id) =
645+ if let Err ( ( item_def_id, sibling ) ) =
644646 may_define_opaque_type ( self . tcx , item_def_id, self . def_id , concrete_type. span )
645647 {
646- self . tcx . sess . emit_err ( OpaqueTypeConstrainedButNotInSig {
647- span : concrete_type. span ,
648- item_span : self . tcx . def_span ( item_def_id) ,
649- } ) ;
648+ if sibling {
649+ self . tcx . sess . emit_err ( OpaqueTypeConstrainedButNotInSig {
650+ span : concrete_type. span ,
651+ item_span : self . tcx . def_span ( item_def_id) ,
652+ } ) ;
653+ } else {
654+ self . tcx . sess . emit_err ( OpaqueTypeConstrainedInNonSibling {
655+ span : concrete_type. span ,
656+ item_span : self . tcx . def_span ( item_def_id) ,
657+ } ) ;
658+ }
650659 }
651660 debug ! ( ?concrete_type, "found constraint" ) ;
652661 if let Some ( prev) = & mut self . found {
@@ -766,8 +775,27 @@ fn may_define_opaque_type<'tcx>(
766775 def_id : LocalDefId ,
767776 opaque_def_id : LocalDefId ,
768777 span : Span ,
769- ) -> Result < ( ) , LocalDefId > {
770- if tcx. is_descendant_of ( opaque_def_id. to_def_id ( ) , def_id. to_def_id ( ) ) {
778+ ) -> Result < ( ) , ( LocalDefId , bool ) > {
779+ let mut parent = tcx. local_parent ( opaque_def_id) ;
780+ loop {
781+ trace ! ( ?parent) ;
782+ match tcx. def_kind ( parent) {
783+ DefKind :: AssocTy | DefKind :: TyAlias => {
784+ parent = tcx. local_parent ( parent) ;
785+ break ;
786+ }
787+ // Skip nested opaque types
788+ DefKind :: OpaqueTy => {
789+ parent = tcx. local_parent ( parent) ;
790+ }
791+ def_kind => {
792+ trace ! ( ?def_kind) ;
793+ return Err ( ( def_id, false ) ) ;
794+ }
795+ }
796+ }
797+ trace ! ( ?parent) ;
798+ if parent == def_id {
771799 // If the opaque type is defined in the body of a function, that function
772800 // may constrain the opaque type since it can't mention it in bounds.
773801 return Ok ( ( ) ) ;
@@ -777,9 +805,31 @@ fn may_define_opaque_type<'tcx>(
777805 return may_define_opaque_type ( tcx, tcx. local_parent ( def_id) , opaque_def_id, span) ;
778806 }
779807
808+ let mut item_parent = tcx. local_parent ( def_id) ;
809+ while item_parent != parent {
810+ trace ! ( ?item_parent) ;
811+ match tcx. def_kind ( item_parent) {
812+ // Skip impls, to allow methods to constrain opaque types from the surrounding module.
813+ DefKind :: Impl { .. } | DefKind :: Trait => {
814+ item_parent = tcx. local_parent ( item_parent) ;
815+ }
816+ // Skip modules, to allow constraining opaque types in child modules
817+ DefKind :: Mod => {
818+ item_parent = tcx. local_parent ( item_parent) ;
819+ }
820+ def_kind => {
821+ trace ! ( ?def_kind) ;
822+ break ;
823+ }
824+ }
825+ }
826+
827+ if item_parent != parent {
828+ return Err ( ( def_id, false ) ) ;
829+ }
830+
780831 let param_env = tcx. param_env ( def_id) ;
781832
782- trace ! ( parent = ?tcx. parent( opaque_def_id. to_def_id( ) ) ) ;
783833 fn has_tait < ' tcx > (
784834 val : impl TypeVisitable < TyCtxt < ' tcx > > ,
785835 opaque_def_id : LocalDefId ,
@@ -874,7 +924,7 @@ fn may_define_opaque_type<'tcx>(
874924 let tait_in_where_bounds =
875925 has_tait ( tcx. predicates_of ( def_id. to_def_id ( ) ) . predicates , opaque_def_id, tcx, param_env) ;
876926 if tcx. features ( ) . type_alias_impl_trait_in_where_bounds {
877- if tait_in_where_bounds { Ok ( ( ) ) } else { Err ( def_id) }
927+ if tait_in_where_bounds { Ok ( ( ) ) } else { Err ( ( def_id, true ) ) }
878928 } else {
879929 if tait_in_where_bounds {
880930 feature_err (
@@ -885,7 +935,7 @@ fn may_define_opaque_type<'tcx>(
885935 )
886936 . emit ( ) ;
887937 }
888- Err ( def_id)
938+ Err ( ( def_id, true ) )
889939 }
890940}
891941
0 commit comments