@@ -8,8 +8,9 @@ use std::iter;
88
99use rustc_data_structures:: fx:: FxIndexSet ;
1010use rustc_errors:: { Applicability , E0806 , struct_span_code_err} ;
11+ use rustc_hir:: attrs:: { AttributeKind , EiiImplResolution } ;
1112use rustc_hir:: def_id:: { DefId , LocalDefId } ;
12- use rustc_hir:: { self as hir, FnSig , HirId , ItemKind } ;
13+ use rustc_hir:: { self as hir, FnSig , HirId , ItemKind , find_attr } ;
1314use rustc_infer:: infer:: { self , InferCtxt , TyCtxtInferExt } ;
1415use rustc_infer:: traits:: { ObligationCause , ObligationCauseCode } ;
1516use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
@@ -24,7 +25,7 @@ use super::potentially_plural_count;
2425use crate :: check:: compare_impl_item:: {
2526 CheckNumberOfEarlyBoundRegionsError , check_number_of_early_bound_regions,
2627} ;
27- use crate :: errors:: LifetimesOrBoundsMismatchOnEii ;
28+ use crate :: errors:: { EiiWithGenerics , LifetimesOrBoundsMismatchOnEii } ;
2829
2930/// Checks whether the signature of some `external_impl`, matches
3031/// the signature of `declaration`, which it is supposed to be compatible
@@ -154,11 +155,44 @@ fn check_is_structurally_compatible<'tcx>(
154155 eii_name : Symbol ,
155156 eii_attr_span : Span ,
156157) -> Result < ( ) , ErrorGuaranteed > {
158+ check_no_generics ( tcx, external_impl, declaration, eii_name, eii_attr_span) ?;
157159 check_number_of_arguments ( tcx, external_impl, declaration, eii_name, eii_attr_span) ?;
158160 check_early_region_bounds ( tcx, external_impl, declaration, eii_attr_span) ?;
159161 Ok ( ( ) )
160162}
161163
164+ /// externally implementable items can't have generics
165+ fn check_no_generics < ' tcx > (
166+ tcx : TyCtxt < ' tcx > ,
167+ external_impl : LocalDefId ,
168+ _declaration : DefId ,
169+ eii_name : Symbol ,
170+ eii_attr_span : Span ,
171+ ) -> Result < ( ) , ErrorGuaranteed > {
172+ let generics = tcx. generics_of ( external_impl) ;
173+ if generics. own_requires_monomorphization ( )
174+ // When an EII implementation is automatically generated by the `#[eii]` macro,
175+ // it will directly refer to the foreign item, not through a macro.
176+ // We don't want to emit this error if it's an implementation that's generated by the `#[eii]` macro,
177+ // since in that case it looks like a duplicate error: the declaration of the EII already can't contain generics.
178+ // So, we check here if at least one of the eii impls has ImplResolution::Macro, which indicates it's
179+ // not generated as part of the declaration.
180+ && find_attr ! (
181+ tcx. get_all_attrs( external_impl) ,
182+ AttributeKind :: EiiImpls ( impls) if impls. iter( ) . any( |i| matches!( i. resolution, EiiImplResolution :: Macro ( _) ) )
183+ )
184+ {
185+ tcx. dcx ( ) . emit_err ( EiiWithGenerics {
186+ span : tcx. def_span ( external_impl) ,
187+ attr : eii_attr_span,
188+ eii_name,
189+ impl_name : tcx. item_name ( external_impl) ,
190+ } ) ;
191+ }
192+
193+ Ok ( ( ) )
194+ }
195+
162196fn check_early_region_bounds < ' tcx > (
163197 tcx : TyCtxt < ' tcx > ,
164198 external_impl : LocalDefId ,
0 commit comments