@@ -55,18 +55,13 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
55
55
let self_ty = self . tcx . type_of ( item. def_id ) ;
56
56
match * self_ty. kind ( ) {
57
57
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 ( ) ) ;
64
59
}
65
60
ty:: Foreign ( did) => {
66
- self . check_def_id ( item, did) ;
61
+ self . check_def_id ( item, self_ty , did) ;
67
62
}
68
63
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 ( ) ) ;
70
65
}
71
66
ty:: Dynamic ( ..) => {
72
67
struct_span_err ! (
@@ -124,14 +119,67 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
124
119
fn visit_foreign_item ( & mut self , _foreign_item : & hir:: ForeignItem < ' _ > ) { }
125
120
}
126
121
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
+
127
130
impl < ' 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 ;
129
133
if let Some ( def_id) = def_id. as_local ( ) {
130
134
// Add the implementation to the mapping from implementation to base
131
135
// type def ID, if there is a base type for this implementation and
132
136
// the implementation does not have any associated traits.
133
137
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
+ }
135
183
} else {
136
184
struct_span_err ! (
137
185
self . tcx. sess,
@@ -153,9 +201,6 @@ impl<'tcx> InherentCollect<'tcx> {
153
201
items : & [ hir:: ImplItemRef ] ,
154
202
span : Span ,
155
203
) {
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" ;
159
204
if !self . tcx . hir ( ) . rustc_coherence_is_core ( ) {
160
205
if self . tcx . features ( ) . rustc_attrs {
161
206
for item in items {
0 commit comments