Rollup merge of #150915 - eii-regression-test-149983, r=kivooeo

Regression test for type params on eii

Somewhere along the line I fixed this one with my other PRs. This just adds the regression tests

Closes rust-lang/rust#149983
This commit is contained in:
Guillaume Gomez 2026-01-13 23:39:10 +01:00 committed by GitHub
commit 0d3692a437
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 73 additions and 4 deletions

View file

@ -166,8 +166,9 @@ hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twic
.label = parameter captured again here
hir_analysis_eii_with_generics =
#[{$eii_name}] cannot have generic parameters other than lifetimes
`{$impl_name}` cannot have generic parameters other than lifetimes
.label = required by this attribute
.help = `#[{$eii_name}]` marks the implementation of an "externally implementable item"
hir_analysis_empty_specialization = specialization impl does not specialize any associated items
.note = impl is a specialization of this impl

View file

@ -974,12 +974,19 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
(0, _) => ("const", "consts", None),
_ => ("type or const", "types or consts", None),
};
let name =
if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::EiiForeignItem) {
"externally implementable items"
} else {
"foreign items"
};
let span = tcx.def_span(def_id);
struct_span_code_err!(
tcx.dcx(),
span,
E0044,
"foreign items may not have {kinds} parameters",
"{name} may not have {kinds} parameters",
)
.with_span_label(span, format!("can't have {kinds} parameters"))
.with_help(

View file

@ -8,8 +8,9 @@ use std::iter;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Applicability, E0806, struct_span_code_err};
use rustc_hir::attrs::{AttributeKind, EiiImplResolution};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, FnSig, HirId, ItemKind};
use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr};
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
@ -169,11 +170,23 @@ fn check_no_generics<'tcx>(
eii_attr_span: Span,
) -> Result<(), ErrorGuaranteed> {
let generics = tcx.generics_of(external_impl);
if generics.own_requires_monomorphization() {
if generics.own_requires_monomorphization()
// When an EII implementation is automatically generated by the `#[eii]` macro,
// it will directly refer to the foreign item, not through a macro.
// We don't want to emit this error if it's an implementation that's generated by the `#[eii]` macro,
// since in that case it looks like a duplicate error: the declaration of the EII already can't contain generics.
// So, we check here if at least one of the eii impls has ImplResolution::Macro, which indicates it's
// not generated as part of the declaration.
&& find_attr!(
tcx.get_all_attrs(external_impl),
AttributeKind::EiiImpls(impls) if impls.iter().any(|i| matches!(i.resolution, EiiImplResolution::Macro(_)))
)
{
tcx.dcx().emit_err(EiiWithGenerics {
span: tcx.def_span(external_impl),
attr: eii_attr_span,
eii_name,
impl_name: tcx.item_name(external_impl),
});
}

View file

@ -1655,10 +1655,12 @@ pub(crate) struct LifetimesOrBoundsMismatchOnEii {
#[derive(Diagnostic)]
#[diag(hir_analysis_eii_with_generics)]
#[help]
pub(crate) struct EiiWithGenerics {
#[primary_span]
pub span: Span,
#[label]
pub attr: Span,
pub eii_name: Symbol,
pub impl_name: Symbol,
}

View file

@ -0,0 +1,13 @@
//@ check-fail
// Check that type parameters on EIIs are properly rejected.
// Specifically a regression test for https://github.com/rust-lang/rust/issues/149983.
#![feature(extern_item_impls)]
#[eii]
fn foo();
#[foo]
fn foo_impl<T>() {}
//~^ ERROR `foo_impl` cannot have generic parameters other than lifetimes
fn main() {}

View file

@ -0,0 +1,12 @@
error: `foo_impl` cannot have generic parameters other than lifetimes
--> $DIR/generic_implementation.rs:10:1
|
LL | #[foo]
| ------ required by this attribute
LL | fn foo_impl<T>() {}
| ^^^^^^^^^^^^^^^^
|
= help: `#[foo]` marks the implementation of an "externally implementable item"
error: aborting due to 1 previous error

View file

@ -0,0 +1,10 @@
//@ check-fail
// Check that type parameters on EIIs are properly rejected.
// Specifically a regression test for https://github.com/rust-lang/rust/issues/149983.
#![feature(extern_item_impls)]
#[eii]
fn foo<T>() {}
//~^ ERROR externally implementable items may not have type parameters
fn main() {}

View file

@ -0,0 +1,11 @@
error[E0044]: externally implementable items may not have type parameters
--> $DIR/type_params_149983.rs:7:1
|
LL | fn foo<T>() {}
| ^^^^^^^^^^^ can't have type parameters
|
= help: replace the type parameters with concrete types like `u32`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0044`.