@@ -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,52 @@ 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 : & str =
126+ "alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items" ;
127+
127128impl < ' tcx > InherentCollect < ' tcx > {
128- fn check_def_id ( & mut self , item : & hir:: Item < ' _ > , def_id : DefId ) {
129+ fn check_def_id ( & mut self , item : & hir:: Item < ' _ > , self_ty : Ty < ' tcx > , def_id : DefId ) {
130+ let impl_def_id = item. def_id ;
129131 if let Some ( def_id) = def_id. as_local ( ) {
130132 // Add the implementation to the mapping from implementation to base
131133 // type def ID, if there is a base type for this implementation and
132134 // the implementation does not have any associated traits.
133135 let vec = self . impls_map . inherent_impls . entry ( def_id) . or_default ( ) ;
134- vec. push ( item. def_id . to_def_id ( ) ) ;
136+ vec. push ( impl_def_id. to_def_id ( ) ) ;
137+ return ;
138+ }
139+
140+ if self . tcx . features ( ) . rustc_attrs
141+ && self . tcx . has_attr ( def_id, sym:: rustc_has_incoherent_inherent_impls)
142+ {
143+ let hir:: ItemKind :: Impl ( hir:: Impl { items, .. } ) = item. kind else {
144+ bug ! ( "expected `impl` item: {:?}" , item) ;
145+ } ;
146+
147+ for item in items {
148+ if !self . tcx . has_attr ( item. id . def_id . to_def_id ( ) , sym:: rustc_allow_incoherent_impl)
149+ {
150+ struct_span_err ! (
151+ self . tcx. sess,
152+ item. span,
153+ E0390 ,
154+ "cannot define inherent `impl` for a type outside of crate where the type is defined" ,
155+ )
156+ . help ( INTO_DEFINING_CRATE )
157+ . span_help ( item. span , ADD_ATTR )
158+ . emit ( ) ;
159+ return ;
160+ }
161+ }
162+
163+ if let Some ( simp) = simplify_type ( self . tcx , self_ty, TreatParams :: AsPlaceholders ) {
164+ self . impls_map . incoherent_impls . entry ( simp) . or_default ( ) . push ( impl_def_id) ;
165+ } else {
166+ bug ! ( "unexpected self type: {:?}" , self_ty) ;
167+ }
135168 } else {
136169 struct_span_err ! (
137170 self . tcx. sess,
@@ -153,9 +186,6 @@ impl<'tcx> InherentCollect<'tcx> {
153186 items : & [ hir:: ImplItemRef ] ,
154187 span : Span ,
155188 ) {
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" ;
159189 if !self . tcx . hir ( ) . rustc_coherence_is_core ( ) {
160190 if self . tcx . features ( ) . rustc_attrs {
161191 for item in items {
0 commit comments