@@ -55,18 +55,13 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
5555 let self_ty = self . tcx . type_of ( item. def_id ) ;
5656 match * self_ty. kind ( ) {
5757 ty:: Adt ( def, _) => {
58- let def_id = def. did ( ) ;
59- if !def_id. is_local ( ) && Some ( def_id) == self . tcx . lang_items ( ) . c_str ( ) {
60- self . check_primitive_impl ( item. def_id , self_ty, items, ty. span )
61- } else {
62- self . check_def_id ( item, def_id) ;
63- }
58+ self . check_def_id ( item, self_ty, def. did ( ) ) ;
6459 }
6560 ty:: Foreign ( did) => {
66- self . check_def_id ( item, did) ;
61+ self . check_def_id ( item, self_ty , did) ;
6762 }
6863 ty:: Dynamic ( data, ..) if data. principal_def_id ( ) . is_some ( ) => {
69- self . check_def_id ( item, data. principal_def_id ( ) . unwrap ( ) ) ;
64+ self . check_def_id ( item, self_ty , data. principal_def_id ( ) . unwrap ( ) ) ;
7065 }
7166 ty:: Dynamic ( ..) => {
7267 struct_span_err ! (
@@ -124,14 +119,67 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
124119 fn visit_foreign_item ( & mut self , _foreign_item : & hir:: ForeignItem < ' _ > ) { }
125120}
126121
122+ const INTO_CORE : & str = "consider moving this inherent impl into `core` if possible" ;
123+ const INTO_DEFINING_CRATE : & str =
124+ "consider moving this inherent impl into the crate defining the type if possible" ;
125+ const ADD_ATTR_TO_TY : & str = "alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type \
126+ and `#[rustc_allow_incoherent_impl]` to the relevant impl items";
127+ const ADD_ATTR : & str =
128+ "alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items" ;
129+
127130impl < ' tcx > InherentCollect < ' tcx > {
128- fn check_def_id ( & mut self , item : & hir:: Item < ' _ > , def_id : DefId ) {
131+ fn check_def_id ( & mut self , item : & hir:: Item < ' _ > , self_ty : Ty < ' tcx > , def_id : DefId ) {
132+ let impl_def_id = item. def_id ;
129133 if let Some ( def_id) = def_id. as_local ( ) {
130134 // Add the implementation to the mapping from implementation to base
131135 // type def ID, if there is a base type for this implementation and
132136 // the implementation does not have any associated traits.
133137 let vec = self . impls_map . inherent_impls . entry ( def_id) . or_default ( ) ;
134- vec. push ( item. def_id . to_def_id ( ) ) ;
138+ vec. push ( impl_def_id. to_def_id ( ) ) ;
139+ return ;
140+ }
141+
142+ if self . tcx . features ( ) . rustc_attrs {
143+ let hir:: ItemKind :: Impl ( & hir:: Impl { items, .. } ) = item. kind else {
144+ bug ! ( "expected `impl` item: {:?}" , item) ;
145+ } ;
146+
147+ if !self . tcx . has_attr ( def_id, sym:: rustc_has_incoherent_inherent_impls) {
148+ struct_span_err ! (
149+ self . tcx. sess,
150+ item. span,
151+ E0390 ,
152+ "cannot define inherent `impl` for a type outside of the crate where the type is defined" ,
153+ )
154+ . help ( INTO_DEFINING_CRATE )
155+ . span_help ( item. span , ADD_ATTR_TO_TY )
156+ . emit ( ) ;
157+ return ;
158+ }
159+
160+ for impl_item in items {
161+ if !self
162+ . tcx
163+ . has_attr ( impl_item. id . def_id . to_def_id ( ) , sym:: rustc_allow_incoherent_impl)
164+ {
165+ struct_span_err ! (
166+ self . tcx. sess,
167+ item. span,
168+ E0390 ,
169+ "cannot define inherent `impl` for a type outside of the crate where the type is defined" ,
170+ )
171+ . help ( INTO_DEFINING_CRATE )
172+ . span_help ( impl_item. span , ADD_ATTR )
173+ . emit ( ) ;
174+ return ;
175+ }
176+ }
177+
178+ if let Some ( simp) = simplify_type ( self . tcx , self_ty, TreatParams :: AsPlaceholders ) {
179+ self . impls_map . incoherent_impls . entry ( simp) . or_default ( ) . push ( impl_def_id) ;
180+ } else {
181+ bug ! ( "unexpected self type: {:?}" , self_ty) ;
182+ }
135183 } else {
136184 struct_span_err ! (
137185 self . tcx. sess,
@@ -153,9 +201,6 @@ impl<'tcx> InherentCollect<'tcx> {
153201 items : & [ hir:: ImplItemRef ] ,
154202 span : Span ,
155203 ) {
156- const INTO_CORE : & str = "consider moving this inherent impl into `core` if possible" ;
157- const ADD_ATTR : & str =
158- "alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items" ;
159204 if !self . tcx . hir ( ) . rustc_coherence_is_core ( ) {
160205 if self . tcx . features ( ) . rustc_attrs {
161206 for item in items {
0 commit comments