diff --git a/RELEASES.md b/RELEASES.md
index c396cd8069d6d..c1cf337ea8d2a 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,134 @@
+Version 1.95 (2026-04-16)
+==========================
+
+
+
+Language
+--------
+- [Stabilize `if let` guards on match arms](https://github.com/rust-lang/rust/pull/141295)
+- [`irrefutable_let_patterns` lint no longer lints on let chains](https://github.com/rust-lang/rust/pull/146832)
+- [Support importing path-segment keywords with renaming](https://github.com/rust-lang/rust/pull/146972)
+- [Stabilize inline assembly for PowerPC and PowerPC64](https://github.com/rust-lang/rust/pull/147996)
+- [const-eval: be more consistent in the behavior of padding during typed copies](https://github.com/rust-lang/rust/pull/148967)
+- [Const blocks are no longer evaluated to determine if expressions involving fallible operations can implicitly be constant-promoted.](https://github.com/rust-lang/rust/pull/150557). Expressions whose ability to implicitly be promoted would depend on the result of a const block are no longer implicitly promoted.
+- [Make operational semantics of pattern matching independent of crate and module](https://github.com/rust-lang/rust/pull/150681)
+
+
+
+
+Compiler
+--------
+- [Stabilize `--remap-path-scope` for controlling the scoping of how paths get remapped in the resulting binary](https://github.com/rust-lang/rust/pull/147611)
+
+
+
+
+Platform Support
+----------------
+- [Promote `powerpc64-unknown-linux-musl` to Tier 2 with host tools](https://github.com/rust-lang/rust/pull/149962)
+- [Promote `aarch64-apple-tvos` to Tier 2](https://github.com/rust-lang/rust/pull/152021)
+- [Promote `aarch64-apple-tvos-sim` to Tier 2](https://github.com/rust-lang/rust/pull/152021)
+- [Promote `aarch64-apple-watchos` to Tier 2](https://github.com/rust-lang/rust/pull/152021)
+- [Promote `aarch64-apple-watchos-sim` to Tier 2](https://github.com/rust-lang/rust/pull/152021)
+- [Promote `aarch64-apple-visionos` to Tier 2](https://github.com/rust-lang/rust/pull/152021)
+- [Promote `aarch64-apple-visionos-sim` to Tier 2](https://github.com/rust-lang/rust/pull/152021)
+
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
+
+
+
+Libraries
+---------
+- [`thread::scope`: document how join interacts with TLS destructors](https://github.com/rust-lang/rust/pull/149482)
+- [Speed up `str::contains` on aarch64 targets with `neon` target feature enabled by default](https://github.com/rust-lang/rust/pull/152176)
+
+
+
+
+Stabilized APIs
+---------------
+
+- [`MaybeUninit<[T; N]>: From<[MaybeUninit; N]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3CMaybeUninit%3C%5BT;+N%5D%3E%3E-for-%5BMaybeUninit%3CT%3E;+N%5D)
+- [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit; N]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E)
+- [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E)
+- [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit; N]>`](https://doc.rust-lang.org/beta/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E)
+- [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E)
+- [`[MaybeUninit; N]: From>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E)
+- [`Cell<[T; N]>: AsRef<[Cell; N]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E;+N%5D%3E-for-Cell%3C%5BT;+N%5D%3E)
+- [`Cell<[T; N]>: AsRef<[Cell]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT;+N%5D%3E)
+- [`Cell<[T]>: AsRef<[Cell]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT%5D%3E)
+- [`bool: TryFrom<{integer}>`](https://doc.rust-lang.org/stable/std/primitive.bool.html#impl-TryFrom%3Cu128%3E-for-bool)
+- [`AtomicPtr::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.update)
+- [`AtomicPtr::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.try_update)
+- [`AtomicBool::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.update)
+- [`AtomicBool::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.try_update)
+- [`AtomicIn::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.update)
+- [`AtomicIn::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.try_update)
+- [`AtomicUn::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.update)
+- [`AtomicUn::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.try_update)
+- [`cfg_select!`](https://doc.rust-lang.org/stable/std/macro.cfg_select.html)
+- [`mod core::range`](https://doc.rust-lang.org/stable/core/range/index.html)
+- [`core::range::RangeInclusive`](https://doc.rust-lang.org/stable/core/range/struct.RangeInclusive.html)
+- [`core::range::RangeInclusiveIter`](https://doc.rust-lang.org/stable/core/range/struct.RangeInclusiveIter.html)
+- [`core::hint::cold_path`](https://doc.rust-lang.org/stable/core/hint/fn.cold_path.html)
+- [`<*const T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked)
+- [`<*mut T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked-1)
+- [`<*mut T>::as_mut_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut_unchecked)
+
+
+These previously stable APIs are now stable in const contexts:
+
+- [`fmt::from_fn`](https://doc.rust-lang.org/stable/std/fmt/fn.from_fn.html)
+- [`ControlFlow::is_break`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_break)
+- [`ControlFlow::is_continue`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_continue)
+
+
+
+
+Cargo
+-----
+- [docs(report): enhance man pages for `cargo report *`](https://github.com/rust-lang/cargo/pull/16430/)
+
+Rustdoc
+-----
+- [In search results, rank unstable items lower](https://github.com/rust-lang/rust/pull/149460)
+- [Add new "hide deprecated items" setting in rustdoc](https://github.com/rust-lang/rust/pull/151091)
+
+
+Compatibility Notes
+-------------------
+- [Array coercions may now result in less inference constraints than before](https://github.com/rust-lang/rust/pull/140283)
+- Importing `$crate` without renaming, i.e. `use $crate::{self};`, is now no longer permitted due to stricter error checking for `self` imports.
+- [const-eval: be more consistent in the behavior of padding during typed copies.](https://github.com/rust-lang/rust/pull/148967)
+ In very rare cases, this may cause compilation errors due to bytes from parts of a pointer ending up in the padding bytes of a `const` or `static`.
+- [A future-incompatibility warning lint `ambiguous_glob_imported_traits` is now reported when using an ambiguously glob imported trait](https://github.com/rust-lang/rust/pull/149058)
+- [Check lifetime bounds of types mentioning only type parameters](https://github.com/rust-lang/rust/pull/149389)
+- [Report more visibility-related ambiguous import errors](https://github.com/rust-lang/rust/pull/149596)
+- [Deprecate `Eq::assert_receiver_is_total_eq` and emit future compatibility warnings on manual impls](https://github.com/rust-lang/rust/pull/149978)
+- [powerpc64: Use the ELF ABI version set in target spec instead of guessing](https://github.com/rust-lang/rust/pull/150468) (fixes the ELF ABI used by the OpenBSD target)
+- Matching on a `#[non_exhaustive]` enum [now reads the discriminant, even if the enum has only one variant](https://github.com/rust-lang/rust/pull/150681). This can cause closures to capture values that they previously wouldn't.
+- `mut ref` and `mut ref mut` patterns, part of the unstable [Match Ergonomics 2024 RFC](https://github.com/rust-lang/rust/issues/123076), were accidentally allowed on stable within struct pattern field shorthand. These patterns are now correctly feature-gated as unstable in this position.
+- [Add future-compatibility warning for derive helper attributes which conflict with built-in attributes](https://github.com/rust-lang/rust/pull/151152)
+- [JSON target specs](https://doc.rust-lang.org/rustc/targets/custom.html) have been destabilized and now require `-Z unstable-options` to use. Previously, they could not be used without the standard library, which has no stable build mechanism. In preparation for the `build-std` project adding that support, JSON target specs are being proactively gated to ensure they remain unstable even if `build-std` is stabilized. Cargo now includes the `-Z json-target-spec` CLI flag to automatically pass `-Z unstable-options` to the compiler when needed. See [#150151](https://github.com/rust-lang/rust/pull/150151), [#151534](https://github.com/rust-lang/rust/pull/150151), and [rust-lang/cargo#16557](https://github.com/rust-lang/cargo/pull/16557).
+- [The arguments of `#[feature]` attributes on invalid targets are now checked](https://github.com/rust-lang/rust/issues/153764)
+
+
+
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Update to LLVM 22](https://github.com/rust-lang/rust/pull/150722)
+
+
Version 1.94.1 (2026-03-26)
===========================
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index ae4989fcbc6c9..ad32fe7e488c1 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3918,6 +3918,13 @@ pub struct StaticItem {
pub mutability: Mutability,
pub expr: Option>,
pub define_opaque: Option>,
+
+ /// This static is an implementation of an externally implementable item (EII).
+ /// This means, there was an EII declared somewhere and this static is the
+ /// implementation that should be used for the declaration.
+ ///
+ /// For statics, there may be at most one `EiiImpl`, but this is a `ThinVec` to make usages of this field nicer.
+ pub eii_impls: ThinVec,
}
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 3939cb1901d44..080e9cb9235f9 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -213,8 +213,14 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
i: &ItemKind,
) -> Vec {
match i {
- ItemKind::Fn(box Fn { eii_impls, .. }) if eii_impls.is_empty() => Vec::new(),
- ItemKind::Fn(box Fn { eii_impls, .. }) => {
+ ItemKind::Fn(box Fn { eii_impls, .. })
+ | ItemKind::Static(box StaticItem { eii_impls, .. })
+ if eii_impls.is_empty() =>
+ {
+ Vec::new()
+ }
+ ItemKind::Fn(box Fn { eii_impls, .. })
+ | ItemKind::Static(box StaticItem { eii_impls, .. }) => {
vec![hir::Attribute::Parsed(AttributeKind::EiiImpls(
eii_impls.iter().map(|i| self.lower_eii_impl(i)).collect(),
))]
@@ -226,7 +232,6 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
ItemKind::ExternCrate(..)
| ItemKind::Use(..)
- | ItemKind::Static(..)
| ItemKind::Const(..)
| ItemKind::ConstBlock(..)
| ItemKind::Mod(..)
@@ -302,6 +307,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
mutability: m,
expr: e,
define_opaque,
+ eii_impls: _,
}) => {
let ident = self.lower_ident(*ident);
let ty = self
@@ -826,6 +832,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
expr: _,
safety,
define_opaque,
+ eii_impls: _,
}) => {
let ty = self
.lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 3e9c596148343..201fa63bfa33c 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -43,6 +43,7 @@ impl<'a> State<'a> {
expr,
safety,
define_opaque,
+ eii_impls,
}) => self.print_item_const(
*ident,
Some(*mutability),
@@ -53,6 +54,7 @@ impl<'a> State<'a> {
*safety,
ast::Defaultness::Implicit,
define_opaque.as_deref(),
+ eii_impls,
),
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
defaultness,
@@ -93,8 +95,12 @@ impl<'a> State<'a> {
safety: ast::Safety,
defaultness: ast::Defaultness,
define_opaque: Option<&[(ast::NodeId, ast::Path)]>,
+ eii_impls: &[EiiImpl],
) {
self.print_define_opaques(define_opaque);
+ for eii_impl in eii_impls {
+ self.print_eii_impl(eii_impl);
+ }
let (cb, ib) = self.head("");
self.print_visibility(vis);
self.print_safety(safety);
@@ -191,6 +197,7 @@ impl<'a> State<'a> {
mutability: mutbl,
expr: body,
define_opaque,
+ eii_impls,
}) => {
self.print_safety(*safety);
self.print_item_const(
@@ -203,6 +210,7 @@ impl<'a> State<'a> {
ast::Safety::Default,
ast::Defaultness::Implicit,
define_opaque.as_deref(),
+ eii_impls,
);
}
ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => {
@@ -234,6 +242,7 @@ impl<'a> State<'a> {
ast::Safety::Default,
*defaultness,
define_opaque.as_deref(),
+ &[],
);
}
ast::ItemKind::Fn(func) => {
@@ -602,6 +611,7 @@ impl<'a> State<'a> {
ast::Safety::Default,
*defaultness,
define_opaque.as_deref(),
+ &[],
);
}
ast::AssocItemKind::Type(box ast::TyAlias {
@@ -703,18 +713,8 @@ impl<'a> State<'a> {
self.print_define_opaques(define_opaque.as_deref());
- for EiiImpl { eii_macro_path, impl_safety, .. } in eii_impls {
- self.word("#[");
- if let Safety::Unsafe(..) = impl_safety {
- self.word("unsafe");
- self.popen();
- }
- self.print_path(eii_macro_path, false, 0);
- if let Safety::Unsafe(..) = impl_safety {
- self.pclose();
- }
- self.word("]");
- self.hardbreak();
+ for eii_impl in eii_impls {
+ self.print_eii_impl(eii_impl);
}
let body_cb_ib = body.as_ref().map(|body| (body, self.head("")));
@@ -741,6 +741,20 @@ impl<'a> State<'a> {
}
}
+ fn print_eii_impl(&mut self, eii: &ast::EiiImpl) {
+ self.word("#[");
+ if let Safety::Unsafe(..) = eii.impl_safety {
+ self.word("unsafe");
+ self.popen();
+ }
+ self.print_path(&eii.eii_macro_path, false, 0);
+ if let Safety::Unsafe(..) = eii.impl_safety {
+ self.pclose();
+ }
+ self.word("]");
+ self.hardbreak();
+ }
+
fn print_define_opaques(&mut self, define_opaque: Option<&[(ast::NodeId, ast::Path)]>) {
if let Some(define_opaque) = define_opaque {
self.word("#[define_opaque(");
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index f0cb348540da1..73b2727fdab0a 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -709,7 +709,8 @@ pub(crate) struct RustcEiiForeignItemParser;
impl NoArgsAttributeParser for RustcEiiForeignItemParser {
const PATH: &[Symbol] = &[sym::rustc_eii_foreign_item];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error;
- const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
+ const ALLOWED_TARGETS: AllowedTargets =
+ AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEiiForeignItem;
}
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs
index def4069f6b477..23db854252a37 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs
@@ -17,6 +17,7 @@ impl AttributeParser for OnConstParser {
template!(List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#]),
|this, cx, args| {
if !cx.features().diagnostic_on_const() {
+ // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs
return;
}
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs
index 006b3b66658e0..a79b7d6afbcdc 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs
@@ -24,6 +24,7 @@ impl OnMoveParser {
mode: Mode,
) {
if !cx.features().diagnostic_on_move() {
+ // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs
return;
}
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs
index bd5eb4cbf82c7..dcfba68a4cf8b 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs
@@ -18,6 +18,7 @@ impl OnUnknownParser {
mode: Mode,
) {
if !cx.features().diagnostic_on_unknown() {
+ // `UnknownDiagnosticAttribute` is emitted in rustc_resolve/macros.rs
return;
}
let span = cx.attr_span;
diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs
index 7b651ed848288..fd0ef8500c6c3 100644
--- a/compiler/rustc_builtin_macros/src/eii.rs
+++ b/compiler/rustc_builtin_macros/src/eii.rs
@@ -1,7 +1,8 @@
use rustc_ast::token::{Delimiter, TokenKind};
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_ast::{
- Attribute, DUMMY_NODE_ID, EiiDecl, EiiImpl, ItemKind, MetaItem, Path, StmtKind, Visibility, ast,
+ Attribute, DUMMY_NODE_ID, EiiDecl, EiiImpl, ItemKind, MetaItem, Mutability, Path, StmtKind,
+ Visibility, ast,
};
use rustc_ast_pretty::pprust::path_to_string;
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -10,8 +11,9 @@ use thin_vec::{ThinVec, thin_vec};
use crate::errors::{
EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe,
- EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroExpectedFunction,
- EiiSharedMacroInStatementPosition,
+ EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition,
+ EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticDefault,
+ EiiStaticMultipleImplementations, EiiStaticMutable,
};
/// ```rust
@@ -73,44 +75,72 @@ fn eii_(
});
return vec![orig_item];
} else {
- ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
+ ecx.dcx().emit_err(EiiSharedMacroTarget {
span: eii_attr_span,
name: path_to_string(&meta_item.path),
});
return vec![orig_item];
};
- let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } =
- item.as_ref()
- else {
- ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
- span: eii_attr_span,
- name: path_to_string(&meta_item.path),
- });
- return vec![Annotatable::Item(item)];
+ let ast::Item { attrs, id: _, span: _, vis, kind, tokens: _ } = item.as_ref();
+ let (item_span, foreign_item_name) = match kind {
+ ItemKind::Fn(func) => (func.sig.span, func.ident),
+ ItemKind::Static(stat) => {
+ // Statics with a default are not supported yet
+ if let Some(stat_body) = &stat.expr {
+ ecx.dcx().emit_err(EiiStaticDefault {
+ span: stat_body.span,
+ name: path_to_string(&meta_item.path),
+ });
+ return vec![];
+ }
+ // Statics must have an explicit name for the eii
+ if meta_item.is_word() {
+ ecx.dcx().emit_err(EiiStaticArgumentRequired {
+ span: eii_attr_span,
+ name: path_to_string(&meta_item.path),
+ });
+ return vec![];
+ }
+
+ // Mut statics are currently not supported
+ if stat.mutability == Mutability::Mut {
+ ecx.dcx().emit_err(EiiStaticMutable {
+ span: eii_attr_span,
+ name: path_to_string(&meta_item.path),
+ });
+ }
+
+ (item.span, stat.ident)
+ }
+ _ => {
+ ecx.dcx().emit_err(EiiSharedMacroTarget {
+ span: eii_attr_span,
+ name: path_to_string(&meta_item.path),
+ });
+ return vec![Annotatable::Item(item)];
+ }
};
+
// only clone what we need
let attrs = attrs.clone();
- let func = (**func).clone();
let vis = vis.clone();
let attrs_from_decl =
filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path);
- let Ok(macro_name) = name_for_impl_macro(ecx, &func, &meta_item) else {
+ let Ok(macro_name) = name_for_impl_macro(ecx, foreign_item_name, &meta_item) else {
// we don't need to wrap in Annotatable::Stmt conditionally since
// EII can't be used on items in statement position
return vec![Annotatable::Item(item)];
};
- // span of the declaring item without attributes
- let item_span = func.sig.span;
- let foreign_item_name = func.ident;
-
let mut module_items = Vec::new();
- if func.body.is_some() {
- module_items.push(generate_default_impl(
+ if let ItemKind::Fn(func) = kind
+ && func.body.is_some()
+ {
+ module_items.push(generate_default_func_impl(
ecx,
&func,
impl_unsafe,
@@ -125,7 +155,7 @@ fn eii_(
ecx,
eii_attr_span,
item_span,
- func,
+ kind,
vis,
&attrs_from_decl,
));
@@ -148,11 +178,11 @@ fn eii_(
/// declaration of the EII.
fn name_for_impl_macro(
ecx: &mut ExtCtxt<'_>,
- func: &ast::Fn,
+ item_ident: Ident,
meta_item: &MetaItem,
) -> Result {
if meta_item.is_word() {
- Ok(func.ident)
+ Ok(item_ident)
} else if let Some([first]) = meta_item.meta_item_list()
&& let Some(m) = first.meta_item()
&& m.path.segments.len() == 1
@@ -190,7 +220,7 @@ fn filter_attrs_for_multiple_eii_attr(
.collect()
}
-fn generate_default_impl(
+fn generate_default_func_impl(
ecx: &mut ExtCtxt<'_>,
func: &ast::Fn,
impl_unsafe: bool,
@@ -257,7 +287,7 @@ fn generate_foreign_item(
ecx: &mut ExtCtxt<'_>,
eii_attr_span: Span,
item_span: Span,
- mut func: ast::Fn,
+ item_kind: &ItemKind,
vis: Visibility,
attrs_from_decl: &[Attribute],
) -> Box {
@@ -268,30 +298,21 @@ fn generate_foreign_item(
// This attribute makes sure that we later know that this foreign item's symbol should not be.
foreign_item_attrs.push(ecx.attr_word(sym::rustc_eii_foreign_item, eii_attr_span));
- let abi = match func.sig.header.ext {
- // extern "X" fn => extern "X" {}
- ast::Extern::Explicit(lit, _) => Some(lit),
- // extern fn => extern {}
- ast::Extern::Implicit(_) => None,
- // fn => extern "Rust" {}
- ast::Extern::None => Some(ast::StrLit {
- symbol: sym::Rust,
- suffix: None,
- symbol_unescaped: sym::Rust,
- style: ast::StrStyle::Cooked,
- span: eii_attr_span,
- }),
+ // We set the abi to the default "rust" abi, which can be overridden by `generate_foreign_func`,
+ // if a specific abi was specified on the EII function
+ let mut abi = Some(ast::StrLit {
+ symbol: sym::Rust,
+ suffix: None,
+ symbol_unescaped: sym::Rust,
+ style: ast::StrStyle::Cooked,
+ span: eii_attr_span,
+ });
+ let foreign_kind = match item_kind {
+ ItemKind::Fn(func) => generate_foreign_func(func.clone(), &mut abi),
+ ItemKind::Static(stat) => generate_foreign_static(stat.clone()),
+ _ => unreachable!("Target was checked earlier"),
};
- // ABI has been moved to the extern {} block, so we remove it from the fn item.
- func.sig.header.ext = ast::Extern::None;
- func.body = None;
-
- // And mark safe functions explicitly as `safe fn`.
- if func.sig.header.safety == ast::Safety::Default {
- func.sig.header.safety = ast::Safety::Safe(func.sig.span);
- }
-
ecx.item(
eii_attr_span,
ThinVec::new(),
@@ -304,13 +325,46 @@ fn generate_foreign_item(
id: ast::DUMMY_NODE_ID,
span: item_span,
vis,
- kind: ast::ForeignItemKind::Fn(Box::new(func.clone())),
+ kind: foreign_kind,
tokens: None,
})]),
}),
)
}
+fn generate_foreign_func(
+ mut func: Box,
+ abi: &mut Option,
+) -> ast::ForeignItemKind {
+ match func.sig.header.ext {
+ // extern "X" fn => extern "X" {}
+ ast::Extern::Explicit(lit, _) => *abi = Some(lit),
+ // extern fn => extern {}
+ ast::Extern::Implicit(_) => *abi = None,
+ // no abi was specified, so we keep the default
+ ast::Extern::None => {}
+ };
+
+ // ABI has been moved to the extern {} block, so we remove it from the fn item.
+ func.sig.header.ext = ast::Extern::None;
+ func.body = None;
+
+ // And mark safe functions explicitly as `safe fn`.
+ if func.sig.header.safety == ast::Safety::Default {
+ func.sig.header.safety = ast::Safety::Safe(func.sig.span);
+ }
+
+ ast::ForeignItemKind::Fn(func)
+}
+
+fn generate_foreign_static(mut stat: Box) -> ast::ForeignItemKind {
+ if stat.safety == ast::Safety::Default {
+ stat.safety = ast::Safety::Safe(stat.ident.span);
+ }
+
+ ast::ForeignItemKind::Static(stat)
+}
+
/// Generate a stub macro (a bit like in core) that will roughly look like:
///
/// ```rust, ignore, example
@@ -453,19 +507,25 @@ pub(crate) fn eii_shared_macro(
{
item
} else {
- ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
- span,
- name: path_to_string(&meta_item.path),
- });
+ ecx.dcx().emit_err(EiiSharedMacroTarget { span, name: path_to_string(&meta_item.path) });
return vec![item];
};
- let ItemKind::Fn(f) = &mut i.kind else {
- ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
- span,
- name: path_to_string(&meta_item.path),
- });
- return vec![item];
+ let eii_impls = match &mut i.kind {
+ ItemKind::Fn(func) => &mut func.eii_impls,
+ ItemKind::Static(stat) => {
+ if !stat.eii_impls.is_empty() {
+ // Reject multiple implementations on one static item
+ // because it might be unintuitive for libraries defining statics the defined statics may alias
+ ecx.dcx().emit_err(EiiStaticMultipleImplementations { span });
+ }
+ &mut stat.eii_impls
+ }
+ _ => {
+ ecx.dcx()
+ .emit_err(EiiSharedMacroTarget { span, name: path_to_string(&meta_item.path) });
+ return vec![item];
+ }
};
let is_default = if meta_item.is_word() {
@@ -483,7 +543,7 @@ pub(crate) fn eii_shared_macro(
return vec![item];
};
- f.eii_impls.push(EiiImpl {
+ eii_impls.push(EiiImpl {
node_id: DUMMY_NODE_ID,
inner_span: meta_item.path.span,
eii_macro_path: meta_item.path.clone(),
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index b5ac84337465a..ad641beb87d98 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -1117,8 +1117,42 @@ pub(crate) struct EiiExternTargetExpectedUnsafe {
}
#[derive(Diagnostic)]
-#[diag("`#[{$name}]` is only valid on functions")]
-pub(crate) struct EiiSharedMacroExpectedFunction {
+#[diag("`#[{$name}]` is only valid on functions and statics")]
+pub(crate) struct EiiSharedMacroTarget {
+ #[primary_span]
+ pub span: Span,
+ pub name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag("static cannot implement multiple EIIs")]
+#[note(
+ "this is not allowed because multiple externally implementable statics that alias may be unintuitive"
+)]
+pub(crate) struct EiiStaticMultipleImplementations {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag("`#[{$name}]` cannot be used on statics with a value")]
+pub(crate) struct EiiStaticDefault {
+ #[primary_span]
+ pub span: Span,
+ pub name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag("`#[{$name}]` requires the name as an explicit argument when used on a static")]
+pub(crate) struct EiiStaticArgumentRequired {
+ #[primary_span]
+ pub span: Span,
+ pub name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag("`#[{$name}]` cannot be used on mutable statics")]
+pub(crate) struct EiiStaticMutable {
#[primary_span]
pub span: Span,
pub name: String,
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 0783282bc6e56..2c0a6ff01018c 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -135,7 +135,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
let ty = self.get_type_of_global(aliasee);
for (alias, linkage, visibility) in aliases {
- let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, *alias));
+ let instance = Instance::mono(self.tcx, *alias);
+ let symbol_name = self.tcx.symbol_name(instance);
tracing::debug!("STATIC ALIAS: {alias:?} {linkage:?} {visibility:?}");
let lldecl = llvm::add_alias(
@@ -145,6 +146,13 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
aliasee,
&CString::new(symbol_name.name).unwrap(),
);
+ // Add the alias name to the set of cached items, so there is no duplicate
+ // instance added to it during the normal `external static` codegen
+ let prev_entry = self.instances.borrow_mut().insert(instance, lldecl);
+
+ // If there already was a previous entry, then `add_static_aliases` was called multiple times for the same `alias`
+ // which would result in incorrect codegen
+ assert!(prev_entry.is_none(), "An instance was already present for {instance:?}");
llvm::set_visibility(lldecl, base::visibility_to_llvm(*visibility));
llvm::set_linkage(lldecl, base::linkage_to_llvm(*linkage));
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 05e6b78132aeb..01886a97f55a2 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -715,6 +715,7 @@ impl<'a> ExtCtxt<'a> {
mutability,
expr: Some(expr),
define_opaque: None,
+ eii_impls: Default::default(),
}
.into(),
),
diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs
index 29213058d1d5e..956e68773b796 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs
@@ -15,7 +15,7 @@ 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};
-use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::regions::InferCtxtRegionExt;
@@ -26,7 +26,10 @@ use super::potentially_plural_count;
use crate::check::compare_impl_item::{
CheckNumberOfEarlyBoundRegionsError, check_number_of_early_bound_regions,
};
-use crate::errors::{EiiWithGenerics, LifetimesOrBoundsMismatchOnEii};
+use crate::errors::{
+ EiiDefkindMismatch, EiiDefkindMismatchStaticMutability, EiiDefkindMismatchStaticSafety,
+ EiiWithGenerics, LifetimesOrBoundsMismatchOnEii,
+};
/// Checks whether the signature of some `external_impl`, matches
/// the signature of `declaration`, which it is supposed to be compatible
@@ -38,14 +41,7 @@ pub(crate) fn compare_eii_function_types<'tcx>(
eii_name: Symbol,
eii_attr_span: Span,
) -> Result<(), ErrorGuaranteed> {
- // Error recovery can resolve the EII target to another value item with the same name,
- // such as a tuple-struct constructor. Skip the comparison in that case and rely on the
- // earlier name-resolution error instead of ICEing while building EII diagnostics.
- // See .
- if !is_foreign_function(tcx, foreign_item) {
- return Ok(());
- }
-
+ check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
let external_impl_span = tcx.def_span(external_impl);
@@ -152,6 +148,118 @@ pub(crate) fn compare_eii_function_types<'tcx>(
Ok(())
}
+pub(crate) fn compare_eii_statics<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ external_impl: LocalDefId,
+ external_impl_ty: Ty<'tcx>,
+ foreign_item: DefId,
+ eii_name: Symbol,
+ eii_attr_span: Span,
+) -> Result<(), ErrorGuaranteed> {
+ check_eii_target(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?;
+
+ let external_impl_span = tcx.def_span(external_impl);
+ let cause = ObligationCause::new(
+ external_impl_span,
+ external_impl,
+ ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item },
+ );
+
+ let param_env = ParamEnv::empty();
+
+ let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
+ let ocx = ObligationCtxt::new_with_diagnostics(infcx);
+
+ let declaration_ty = tcx.type_of(foreign_item).instantiate_identity();
+ debug!(?declaration_ty);
+
+ // FIXME: Copied over from compare impl items, same issue:
+ // We'd want to keep more accurate spans than "the method signature" when
+ // processing the comparison between the trait and impl fn, but we sadly lose them
+ // and point at the whole signature when a trait bound or specific input or output
+ // type would be more appropriate. In other places we have a `Vec`
+ // corresponding to their `Vec`, but we don't have that here.
+ // Fixing this would improve the output of test `issue-83765.rs`.
+ let result = ocx.sup(&cause, param_env, declaration_ty, external_impl_ty);
+
+ if let Err(terr) = result {
+ debug!(?external_impl_ty, ?declaration_ty, ?terr, "sub_types failed");
+
+ let mut diag = struct_span_code_err!(
+ tcx.dcx(),
+ cause.span,
+ E0806,
+ "static `{}` has a type that is incompatible with the declaration of `#[{eii_name}]`",
+ tcx.item_name(external_impl)
+ );
+ diag.span_note(eii_attr_span, "expected this because of this attribute");
+
+ return Err(diag.emit());
+ }
+
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = ocx.evaluate_obligations_error_on_ambiguity();
+ if !errors.is_empty() {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
+ return Err(reported);
+ }
+
+ // Finally, resolve all regions. This catches wily misuses of
+ // lifetime parameters.
+ let errors = infcx.resolve_regions(external_impl, param_env, []);
+ if !errors.is_empty() {
+ return Err(infcx
+ .tainted_by_errors()
+ .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(external_impl, &errors)));
+ }
+
+ Ok(())
+}
+
+fn check_eii_target(
+ tcx: TyCtxt<'_>,
+ external_impl: LocalDefId,
+ foreign_item: DefId,
+ eii_name: Symbol,
+ eii_attr_span: Span,
+) -> Result<(), ErrorGuaranteed> {
+ // Error recovery can resolve the EII target to another value item with the same name,
+ // such as a tuple-struct constructor. Skip the comparison in that case and rely on the
+ // earlier name-resolution error instead of ICEing while building EII diagnostics.
+ // See .
+ if !tcx.is_foreign_item(foreign_item) {
+ return Err(tcx.dcx().delayed_bug("EII is a foreign item"));
+ }
+ let expected_kind = tcx.def_kind(foreign_item);
+ let actual_kind = tcx.def_kind(external_impl);
+
+ match expected_kind {
+ // Correct target
+ _ if expected_kind == actual_kind => Ok(()),
+ DefKind::Static { mutability: m1, safety: s1, .. }
+ if let DefKind::Static { mutability: m2, safety: s2, .. } = actual_kind =>
+ {
+ Err(if s1 != s2 {
+ tcx.dcx().emit_err(EiiDefkindMismatchStaticSafety { span: eii_attr_span, eii_name })
+ } else if m1 != m2 {
+ tcx.dcx()
+ .emit_err(EiiDefkindMismatchStaticMutability { span: eii_attr_span, eii_name })
+ } else {
+ unreachable!()
+ })
+ }
+ // Not checked by attr target checking
+ DefKind::Fn | DefKind::Static { .. } => Err(tcx.dcx().emit_err(EiiDefkindMismatch {
+ span: eii_attr_span,
+ eii_name,
+ expected_kind: expected_kind.descr(foreign_item),
+ })),
+ // Checked by attr target checking
+ _ => Err(tcx.dcx().delayed_bug("Attribute should not be allowed by target checking")),
+ }
+}
+
/// Checks a bunch of different properties of the impl/trait methods for
/// compatibility, such as asyncness, number of argument, self receiver kind,
/// and number of early- and late-bound generics.
@@ -451,7 +559,3 @@ fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&'
let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id);
tcx.hir_fn_sig_by_hir_id(hir_id)
}
-
-fn is_foreign_function(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- tcx.is_foreign_item(def_id) && matches!(tcx.def_kind(def_id), DefKind::Fn)
-}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 424a75bd4dcb3..d5f17a5cbb75b 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -41,7 +41,7 @@ use rustc_trait_selection::traits::{
};
use tracing::{debug, instrument};
-use super::compare_eii::compare_eii_function_types;
+use super::compare_eii::{compare_eii_function_types, compare_eii_statics};
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
use crate::errors;
@@ -1208,7 +1208,7 @@ fn check_item_fn(
decl: &hir::FnDecl<'_>,
) -> Result<(), ErrorGuaranteed> {
enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
- check_eiis(tcx, def_id);
+ check_eiis_fn(tcx, def_id);
let sig = tcx.fn_sig(def_id).instantiate_identity();
check_fn_or_method(wfcx, sig, decl, def_id);
@@ -1216,7 +1216,7 @@ fn check_item_fn(
})
}
-fn check_eiis(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) {
// does the function have an EiiImpl attribute? that contains the defid of a *macro*
// that was used to mark the implementation. This is a two step process.
for EiiImpl { resolution, span, .. } in
@@ -1243,6 +1243,33 @@ fn check_eiis(tcx: TyCtxt<'_>, def_id: LocalDefId) {
}
}
+fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) {
+ // does the function have an EiiImpl attribute? that contains the defid of a *macro*
+ // that was used to mark the implementation. This is a two step process.
+ for EiiImpl { resolution, span, .. } in
+ find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_iter().flatten()
+ {
+ let (foreign_item, name) = match resolution {
+ EiiImplResolution::Macro(def_id) => {
+ // we expect this macro to have the `EiiMacroFor` attribute, that points to a function
+ // signature that we'd like to compare the function we're currently checking with
+ if let Some(foreign_item) =
+ find_attr!(tcx, *def_id, EiiDeclaration(EiiDecl {foreign_item: t, ..}) => *t)
+ {
+ (foreign_item, tcx.item_name(*def_id))
+ } else {
+ tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII");
+ continue;
+ }
+ }
+ EiiImplResolution::Known(decl) => (decl.foreign_item, decl.name.name),
+ EiiImplResolution::Error(_eg) => continue,
+ };
+
+ let _ = compare_eii_statics(tcx, def_id, ty, foreign_item, name, *span);
+ }
+}
+
#[instrument(level = "debug", skip(tcx))]
pub(crate) fn check_static_item<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -1251,6 +1278,10 @@ pub(crate) fn check_static_item<'tcx>(
should_check_for_sync: bool,
) -> Result<(), ErrorGuaranteed> {
enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
+ if should_check_for_sync {
+ check_eiis_static(tcx, item_id, ty);
+ }
+
let span = tcx.ty_span(item_id);
let loc = Some(WellFormedLoc::Ty(item_id));
let item_ty = wfcx.deeply_normalize(span, loc, ty);
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 1abafd4547ce6..f353ace0b3886 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1933,3 +1933,28 @@ pub(crate) struct ImplUnpinForPinProjectedType {
pub adt_span: Span,
pub adt_name: Symbol,
}
+
+#[derive(Diagnostic)]
+#[diag("`#[{$eii_name}]` must be used on a {$expected_kind}")]
+pub(crate) struct EiiDefkindMismatch {
+ #[primary_span]
+ pub span: Span,
+ pub eii_name: Symbol,
+ pub expected_kind: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag("mutability does not match with the definition of`#[{$eii_name}]`")]
+pub(crate) struct EiiDefkindMismatchStaticMutability {
+ #[primary_span]
+ pub span: Span,
+ pub eii_name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag("safety does not match with the definition of`#[{$eii_name}]`")]
+pub(crate) struct EiiDefkindMismatchStaticSafety {
+ #[primary_span]
+ pub span: Span,
+ pub eii_name: Symbol,
+}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index ab3683f598208..df85aa7d041a5 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1235,6 +1235,7 @@ impl<'a> Parser<'a> {
mutability: _,
expr,
define_opaque,
+ eii_impls: _,
}) => {
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
AssocItemKind::Const(Box::new(ConstItem {
@@ -1503,6 +1504,7 @@ impl<'a> Parser<'a> {
},
safety: Safety::Default,
define_opaque: None,
+ eii_impls: ThinVec::default(),
}))
}
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
@@ -1636,7 +1638,15 @@ impl<'a> Parser<'a> {
self.expect_semi()?;
- let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None };
+ let item = StaticItem {
+ ident,
+ ty,
+ safety,
+ mutability,
+ expr,
+ define_opaque: None,
+ eii_impls: ThinVec::default(),
+ };
Ok(ItemKind::Static(Box::new(item)))
}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 54d34ef26a021..45478df40e8bf 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -551,9 +551,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) {
for EiiImpl { span, inner_span, resolution, impl_marked_unsafe, is_default: _ } in impls {
match target {
- Target::Fn => {}
+ Target::Fn | Target::Static => {}
_ => {
- self.dcx().emit_err(errors::EiiImplNotFunction { span: *span });
+ self.dcx().emit_err(errors::EiiImplTarget { span: *span });
}
}
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 5de43f24b2dc6..9d4f7a3cbbea2 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1175,8 +1175,8 @@ pub(crate) struct ReprAlignShouldBeAlignStatic {
}
#[derive(Diagnostic)]
-#[diag("`eii_macro_for` is only valid on functions")]
-pub(crate) struct EiiImplNotFunction {
+#[diag("`eii_macro_for` is only valid on functions and statics")]
+pub(crate) struct EiiImplTarget {
#[primary_span]
pub span: Span,
}
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 427a75c6bff4d..78dcb0620e5b1 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -274,6 +274,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
expr: _,
safety,
define_opaque: _,
+ eii_impls: _,
}) => {
let safety = match safety {
ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 9e0f04e82b472..4d855037ca170 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2983,7 +2983,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
- let binding = self.resolution(crate_module, binding_key)?.binding()?;
+ let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
return None;
};
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 55518276a4f0f..cd7790f27b5f5 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -114,7 +114,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
let module = self.r.expect_module(module_id.to_def_id());
for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
- let Some(mut decl) = name_resolution.borrow().binding() else {
+ let Some(mut decl) = name_resolution.borrow().best_decl() else {
continue;
};
// Set the given effective visibility level to `Level::Direct` and
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index bcc754fd984da..8c7bf61949a29 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1521,20 +1521,24 @@ pub(crate) struct RedundantImportVisibility {
#[diag("unknown diagnostic attribute")]
pub(crate) struct UnknownDiagnosticAttribute {
#[subdiagnostic]
- pub typo: Option,
+ pub help: Option,
}
#[derive(Subdiagnostic)]
-#[suggestion(
- "an attribute with a similar name exists",
- style = "verbose",
- code = "{typo_name}",
- applicability = "machine-applicable"
-)]
-pub(crate) struct UnknownDiagnosticAttributeTypoSugg {
- #[primary_span]
- pub span: Span,
- pub typo_name: Symbol,
+pub(crate) enum UnknownDiagnosticAttributeHelp {
+ #[suggestion(
+ "an attribute with a similar name exists",
+ style = "verbose",
+ code = "{typo_name}",
+ applicability = "machine-applicable"
+ )]
+ Typo {
+ #[primary_span]
+ span: Span,
+ typo_name: Symbol,
+ },
+ #[help("add `#![feature({$feature})]` to the crate attributes to enable")]
+ UseFeature { feature: Symbol },
}
// FIXME: Make this properly translatable.
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index e24e65d55c00f..a94f3ea435e2c 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -289,15 +289,22 @@ impl<'ra> NameResolution<'ra> {
NameResolution { single_imports: FxIndexSet::default(), orig_ident_span, .. }
}
- /// Returns the binding for the name if it is known or None if it not known.
- pub(crate) fn binding(&self) -> Option> {
- self.best_decl().and_then(|binding| {
- if !binding.is_glob_import() || self.single_imports.is_empty() {
- Some(binding)
- } else {
- None
- }
- })
+ /// Returns the best declaration if it is not going to change, and `None` if the best
+ /// declaration may still change to something else.
+ /// FIXME: this function considers `single_imports`, but not `unexpanded_invocations`, so
+ /// the returned declaration may actually change after expanding macros in the same module,
+ /// because of this fact we have glob overwriting (`select_glob_decl`). Consider using
+ /// `unexpanded_invocations` here and avoiding glob overwriting entirely, if it doesn't cause
+ /// code breakage in practice.
+ /// FIXME: relationship between this function and similar `DeclData::determined` is unclear.
+ pub(crate) fn determined_decl(&self) -> Option> {
+ if self.non_glob_decl.is_some() {
+ self.non_glob_decl
+ } else if self.glob_decl.is_some() && self.single_imports.is_empty() {
+ self.glob_decl
+ } else {
+ None
+ }
}
pub(crate) fn best_decl(&self) -> Option> {
@@ -482,41 +489,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
orig_ident_span,
warn_ambiguity,
|this, resolution| {
- if let Some(old_decl) = resolution.best_decl() {
- assert_ne!(decl, old_decl);
- assert!(!decl.warn_ambiguity.get());
- if res == Res::Err && old_decl.res() != Res::Err {
- // Do not override real declarations with `Res::Err`s from error recovery.
- return Ok(());
- }
- match (old_decl.is_glob_import(), decl.is_glob_import()) {
- (true, true) => {
- resolution.glob_decl =
- Some(this.select_glob_decl(old_decl, decl, warn_ambiguity));
- }
- (old_glob @ true, false) | (old_glob @ false, true) => {
- let (glob_decl, non_glob_decl) =
- if old_glob { (old_decl, decl) } else { (decl, old_decl) };
- resolution.non_glob_decl = Some(non_glob_decl);
- if let Some(old_glob_decl) = resolution.glob_decl
- && old_glob_decl != glob_decl
- {
- resolution.glob_decl =
- Some(this.select_glob_decl(old_glob_decl, glob_decl, false));
- } else {
- resolution.glob_decl = Some(glob_decl);
- }
- }
- (false, false) => {
- return Err(old_decl);
- }
- }
+ assert!(!decl.warn_ambiguity.get());
+ if decl.is_glob_import() {
+ resolution.glob_decl = Some(match resolution.glob_decl {
+ Some(old_decl) => this.select_glob_decl(
+ old_decl,
+ decl,
+ warn_ambiguity && resolution.non_glob_decl.is_none(),
+ ),
+ None => decl,
+ })
} else {
- if decl.is_glob_import() {
- resolution.glob_decl = Some(decl);
- } else {
- resolution.non_glob_decl = Some(decl);
- }
+ resolution.non_glob_decl = Some(match resolution.non_glob_decl {
+ Some(old_decl) => return Err(old_decl),
+ None => decl,
+ })
}
Ok(())
@@ -543,11 +530,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let resolution = &mut *self
.resolution_or_default(module, key, orig_ident_span)
.borrow_mut_unchecked();
- let old_decl = resolution.binding();
+ let old_decl = resolution.determined_decl();
let t = f(self, resolution);
- if let Some(binding) = resolution.binding()
+ if let Some(binding) = resolution.determined_decl()
&& old_decl != Some(binding)
{
(binding, t, warn_ambiguity || old_decl.is_some())
@@ -573,13 +560,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
if self.is_accessible_from(binding.vis(), scope) {
let import_decl = self.new_import_decl(binding, *import);
- let _ = self.try_plant_decl_into_local_module(
+ self.try_plant_decl_into_local_module(
ident,
orig_ident_span,
key.ns,
import_decl,
warn_ambiguity,
- );
+ )
+ .expect("planting a glob cannot fail");
}
}
@@ -598,6 +586,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.per_ns(|this, ns| {
let module = import.parent_scope.module;
let ident = IdentKey::new(target);
+ // This can fail, dummies are inserted only in non-occupied slots.
let _ = this.try_plant_decl_into_local_module(
ident,
target.span,
@@ -1676,7 +1665,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.iter()
.filter_map(|(key, resolution)| {
let resolution = resolution.borrow();
- resolution.binding().map(|binding| (*key, binding, resolution.orig_ident_span))
+ resolution.determined_decl().map(|decl| (*key, decl, resolution.orig_ident_span))
})
.collect::>();
for (mut key, binding, orig_ident_span) in bindings {
@@ -1692,15 +1681,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let import_decl = self.new_import_decl(binding, import);
let warn_ambiguity = self
.resolution(import.parent_scope.module, key)
- .and_then(|r| r.binding())
+ .and_then(|r| r.determined_decl())
.is_some_and(|binding| binding.warn_ambiguity_recursive());
- let _ = self.try_plant_decl_into_local_module(
+ self.try_plant_decl_into_local_module(
key.ident,
orig_ident_span,
key.ns,
import_decl,
warn_ambiguity,
- );
+ )
+ .expect("planting a glob cannot fail");
}
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 2c287045be7a9..56e26b1ac6cbe 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -530,9 +530,8 @@ impl PathSource<'_, '_, '_> {
},
_ => "value",
},
- PathSource::ReturnTypeNotation
- | PathSource::Delegation
- | PathSource::ExternItemImpl => "function",
+ PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
+ PathSource::ExternItemImpl => "function or static",
PathSource::PreciseCapturingArg(..) => "type or const parameter",
PathSource::Macro => "macro",
PathSource::Module => "module",
@@ -625,7 +624,13 @@ impl PathSource<'_, '_, '_> {
},
PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
PathSource::ExternItemImpl => {
- matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..), _))
+ matches!(
+ res,
+ Res::Def(
+ DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Static { .. },
+ _
+ )
+ )
}
PathSource::PreciseCapturingArg(ValueNS) => {
matches!(res, Res::Def(DefKind::ConstParam, _))
@@ -1095,21 +1100,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
debug!("(resolving function) entering function");
if let FnKind::Fn(_, _, f) = fn_kind {
- for EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. } in &f.eii_impls
- {
- // See docs on the `known_eii_macro_resolution` field:
- // if we already know the resolution statically, don't bother resolving it.
- if let Some(target) = known_eii_macro_resolution {
- self.smart_resolve_path(
- *node_id,
- &None,
- &target.foreign_item,
- PathSource::ExternItemImpl,
- );
- } else {
- self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro);
- }
- }
+ self.resolve_eii(&f.eii_impls);
}
// Create a value rib for the function.
@@ -2905,7 +2896,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
self.parent_scope.module = orig_module;
}
- ItemKind::Static(box ast::StaticItem { ident, ty, expr, define_opaque, .. }) => {
+ ItemKind::Static(box ast::StaticItem {
+ ident,
+ ty,
+ expr,
+ define_opaque,
+ eii_impls,
+ ..
+ }) => {
self.with_static_rib(def_kind, |this| {
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
this.visit_ty(ty);
@@ -2917,6 +2915,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}
});
self.resolve_define_opaques(define_opaque);
+ self.resolve_eii(&eii_impls);
}
ItemKind::Const(box ast::ConstItem {
@@ -5496,6 +5495,23 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}
}
}
+
+ fn resolve_eii(&mut self, eii_impls: &[EiiImpl]) {
+ for EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. } in eii_impls {
+ // See docs on the `known_eii_macro_resolution` field:
+ // if we already know the resolution statically, don't bother resolving it.
+ if let Some(target) = known_eii_macro_resolution {
+ self.smart_resolve_path(
+ *node_id,
+ &None,
+ &target.foreign_item,
+ PathSource::ExternItemImpl,
+ );
+ } else {
+ self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro);
+ }
+ }
+ }
}
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index d75f2981a7724..7334131a1c01d 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1101,9 +1101,11 @@ impl<'ra> DeclData<'ra> {
!(certainly_before_other_or_simultaneously || certainly_before_invoc_or_simultaneously)
}
- // Its purpose is to postpone the determination of a single binding because
- // we can't predict whether it will be overwritten by recently expanded macros.
- // FIXME: How can we integrate it with the `update_resolution`?
+ /// Returns whether this declaration may be shadowed or overwritten by something else later.
+ /// FIXME: this function considers `unexpanded_invocations`, but not `single_imports`, so
+ /// the declaration may not be as "determined" as we think.
+ /// FIXME: relationship between this function and similar `NameResolution::determined_decl`
+ /// is unclear.
fn determined(&self) -> bool {
match &self.kind {
DeclKind::Import { source_decl, import, .. } if import.is_glob() => {
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 67a896bdd7557..13bda9c98c0a7 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -712,34 +712,55 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
}
- let diagnostic_attributes: &[(Symbol, bool)] = &[
- (sym::on_unimplemented, true),
- (sym::do_not_recommend, true),
- (sym::on_move, true),
- (sym::on_const, self.tcx.features().diagnostic_on_const()),
- (sym::on_unknown, self.tcx.features().diagnostic_on_unknown()),
+ const DIAGNOSTIC_ATTRIBUTES: &[(Symbol, Option)] = &[
+ (sym::on_unimplemented, None),
+ (sym::do_not_recommend, None),
+ (sym::on_move, Some(sym::diagnostic_on_move)),
+ (sym::on_const, Some(sym::diagnostic_on_const)),
+ (sym::on_unknown, Some(sym::diagnostic_on_unknown)),
];
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
&& let [namespace, attribute, ..] = &*path.segments
&& namespace.ident.name == sym::diagnostic
- && !diagnostic_attributes
- .iter()
- .any(|(attr, stable)| *stable && attribute.ident.name == *attr)
+ && !DIAGNOSTIC_ATTRIBUTES.iter().any(|(attr, feature)| {
+ attribute.ident.name == *attr
+ && feature.is_none_or(|f| self.tcx.features().enabled(f))
+ })
{
+ let name = attribute.ident.name;
let span = attribute.span();
- let candidates = diagnostic_attributes
- .iter()
- .filter_map(|(sym, stable)| stable.then_some(*sym))
- .collect::>();
- let typo = find_best_match_for_name(&candidates, attribute.ident.name, Some(5))
- .map(|typo_name| errors::UnknownDiagnosticAttributeTypoSugg { span, typo_name });
+
+ let help = 'help: {
+ if self.tcx.sess.is_nightly_build() {
+ for (attr, feature) in DIAGNOSTIC_ATTRIBUTES {
+ if let Some(feature) = *feature
+ && *attr == name
+ {
+ break 'help Some(errors::UnknownDiagnosticAttributeHelp::UseFeature {
+ feature,
+ });
+ }
+ }
+ }
+
+ let candidates = DIAGNOSTIC_ATTRIBUTES
+ .iter()
+ .filter_map(|(attr, feature)| {
+ feature.is_none_or(|f| self.tcx.features().enabled(f)).then_some(*attr)
+ })
+ .collect::>();
+
+ find_best_match_for_name(&candidates, name, None).map(|typo_name| {
+ errors::UnknownDiagnosticAttributeHelp::Typo { span, typo_name }
+ })
+ };
self.tcx.sess.psess.buffer_lint(
UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
span,
node_id,
- errors::UnknownDiagnosticAttribute { typo },
+ errors::UnknownDiagnosticAttribute { help },
);
}
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index cfff7da60a6a4..c96c0649753fd 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -339,6 +339,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
expr: le,
safety: ls,
define_opaque: _,
+ eii_impls: _,
}),
Static(box StaticItem {
ident: ri,
@@ -347,6 +348,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
expr: re,
safety: rs,
define_opaque: _,
+ eii_impls: _,
}),
) => eq_id(*li, *ri) && lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_deref(), re.as_deref()),
(
@@ -540,6 +542,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
expr: le,
safety: ls,
define_opaque: _,
+ eii_impls: _,
}),
Static(box StaticItem {
ident: ri,
@@ -548,6 +551,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
expr: re,
safety: rs,
define_opaque: _,
+ eii_impls: _,
}),
) => eq_id(*li, *ri) && eq_ty(lt, rt) && lm == rm && eq_expr_opt(le.as_deref(), re.as_deref()) && ls == rs,
(
diff --git a/tests/ui/eii/attribute_targets.stderr b/tests/ui/eii/attribute_targets.stderr
index bf04c323c95ca..8166609e19740 100644
--- a/tests/ui/eii/attribute_targets.stderr
+++ b/tests/ui/eii/attribute_targets.stderr
@@ -1,106 +1,106 @@
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:7:1
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:9:1
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:13:1
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:15:1
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:21:1
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:23:1
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:27:1
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:29:1
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:32:5
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:34:5
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:39:1
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:41:1
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:44:5
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:46:5
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:51:1
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:53:1
|
LL | #[eii]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:56:5
|
LL | #[foo]
| ^^^^^^
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/attribute_targets.rs:58:5
|
LL | #[eii]
diff --git a/tests/ui/eii/default/call_default.rs b/tests/ui/eii/default/call_default.rs
index b60a1dd0b2156..8806c7fa7d8ce 100644
--- a/tests/ui/eii/default/call_default.rs
+++ b/tests/ui/eii/default/call_default.rs
@@ -3,7 +3,7 @@
//@ run-pass
//@ check-run-results
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests EIIs with default implementations.
// When there's no explicit declaration, the default should be called from the declaring crate.
diff --git a/tests/ui/eii/default/call_default_panics.rs b/tests/ui/eii/default/call_default_panics.rs
index 96b2742aa8e0a..db664e0cbcb0d 100644
--- a/tests/ui/eii/default/call_default_panics.rs
+++ b/tests/ui/eii/default/call_default_panics.rs
@@ -5,7 +5,7 @@
//@ needs-unwind
//@ exec-env:RUST_BACKTRACE=1
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// A small test to make sure that unwinding works properly.
//
diff --git a/tests/ui/eii/default/call_impl.rs b/tests/ui/eii/default/call_impl.rs
index b887697574892..1a972774beaeb 100644
--- a/tests/ui/eii/default/call_impl.rs
+++ b/tests/ui/eii/default/call_impl.rs
@@ -4,7 +4,7 @@
//@ run-pass
//@ check-run-results
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests EIIs with default implementations.
// When an explicit implementation is given in one dependency, and the declaration is in another,
diff --git a/tests/ui/eii/default/local_crate.rs b/tests/ui/eii/default/local_crate.rs
index d98c2fac4234e..fd4fd459c52fb 100644
--- a/tests/ui/eii/default/local_crate.rs
+++ b/tests/ui/eii/default/local_crate.rs
@@ -1,7 +1,7 @@
//@ run-pass
//@ check-run-results
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests EIIs with default implementations.
// In the same crate, when there's no explicit declaration, the default should be called.
diff --git a/tests/ui/eii/default/local_crate_explicit.rs b/tests/ui/eii/default/local_crate_explicit.rs
index a4cc54fcd31fc..200905b8753a0 100644
--- a/tests/ui/eii/default/local_crate_explicit.rs
+++ b/tests/ui/eii/default/local_crate_explicit.rs
@@ -1,7 +1,7 @@
//@ run-pass
//@ check-run-results
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests EIIs with default implementations.
// In the same crate, the explicit implementation should get priority.
diff --git a/tests/ui/eii/duplicate/duplicate1.rs b/tests/ui/eii/duplicate/duplicate1.rs
index 3269778aca0c4..2128cac70eb30 100644
--- a/tests/ui/eii/duplicate/duplicate1.rs
+++ b/tests/ui/eii/duplicate/duplicate1.rs
@@ -2,7 +2,7 @@
//@ aux-build: impl1.rs
//@ aux-build: impl2.rs
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// tests that EIIs error properly, even if the conflicting implementations live in another crate.
#![feature(extern_item_impls)]
diff --git a/tests/ui/eii/duplicate/duplicate2.rs b/tests/ui/eii/duplicate/duplicate2.rs
index 4c883d28d74a4..b0f1b1266e4ca 100644
--- a/tests/ui/eii/duplicate/duplicate2.rs
+++ b/tests/ui/eii/duplicate/duplicate2.rs
@@ -3,7 +3,7 @@
//@ aux-build: impl2.rs
//@ aux-build: impl3.rs
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests the error message when there are multiple implementations of an EII in many crates.
#![feature(extern_item_impls)]
diff --git a/tests/ui/eii/duplicate/duplicate3.rs b/tests/ui/eii/duplicate/duplicate3.rs
index b046760745097..4b2b0fc111b58 100644
--- a/tests/ui/eii/duplicate/duplicate3.rs
+++ b/tests/ui/eii/duplicate/duplicate3.rs
@@ -4,7 +4,7 @@
//@ aux-build: impl3.rs
//@ aux-build: impl4.rs
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests the error message when there are multiple implementations of an EII in many crates.
#![feature(extern_item_impls)]
diff --git a/tests/ui/eii/duplicate/multiple_impls.rs b/tests/ui/eii/duplicate/multiple_impls.rs
index c02c783223ac3..5ce2a27e16957 100644
--- a/tests/ui/eii/duplicate/multiple_impls.rs
+++ b/tests/ui/eii/duplicate/multiple_impls.rs
@@ -1,7 +1,7 @@
//@ run-pass
//@ check-run-results
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests whether one function could implement two EIIs.
#![feature(extern_item_impls)]
diff --git a/tests/ui/eii/eii-declaration-not-fn-issue-152337.rs b/tests/ui/eii/eii-declaration-not-fn-issue-152337.rs
index 8564a5a748477..0d71f4854d344 100644
--- a/tests/ui/eii/eii-declaration-not-fn-issue-152337.rs
+++ b/tests/ui/eii/eii-declaration-not-fn-issue-152337.rs
@@ -6,7 +6,7 @@
const A: () = ();
#[eii]
fn A() {} //~ ERROR the name `A` is defined multiple times
-//~^ ERROR expected function, found constant
-//~| ERROR expected function, found constant
+//~^ ERROR expected function or static, found constant
+//~| ERROR expected function or static, found constant
fn main() {}
diff --git a/tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr b/tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr
index ea4ec604e7aa4..34998f33cc92e 100644
--- a/tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr
+++ b/tests/ui/eii/eii-declaration-not-fn-issue-152337.stderr
@@ -9,17 +9,17 @@ LL | fn A() {}
|
= note: `A` must be defined only once in the value namespace of this module
-error[E0423]: expected function, found constant `self::A`
+error[E0423]: expected function or static, found constant `self::A`
--> $DIR/eii-declaration-not-fn-issue-152337.rs:8:4
|
LL | fn A() {}
- | ^ not a function
+ | ^ not a function or static
-error[E0423]: expected function, found constant `A`
+error[E0423]: expected function or static, found constant `A`
--> $DIR/eii-declaration-not-fn-issue-152337.rs:8:4
|
LL | fn A() {}
- | ^ not a function
+ | ^ not a function or static
error: aborting due to 3 previous errors
diff --git a/tests/ui/eii/error_statement_position.stderr b/tests/ui/eii/error_statement_position.stderr
index f14e6c33e64f5..c6af18044db8d 100644
--- a/tests/ui/eii/error_statement_position.stderr
+++ b/tests/ui/eii/error_statement_position.stderr
@@ -1,4 +1,4 @@
-error: `#[eii]` is only valid on functions
+error: `#[eii]` is only valid on functions and statics
--> $DIR/error_statement_position.rs:8:5
|
LL | #[eii]
diff --git a/tests/ui/eii/errors.rs b/tests/ui/eii/errors.rs
index 5fcf33336b402..bc6c17f463a78 100644
--- a/tests/ui/eii/errors.rs
+++ b/tests/ui/eii/errors.rs
@@ -25,11 +25,9 @@ unsafe extern "Rust" {
safe fn bar(x: u64) -> u64;
}
-#[foo] //~ ERROR `#[foo]` is only valid on functions
-static X: u64 = 4;
-#[foo] //~ ERROR `#[foo]` is only valid on functions
+#[foo] //~ ERROR `#[foo]` is only valid on functions and statics
const Y: u64 = 4;
-#[foo] //~ ERROR `#[foo]` is only valid on functions
+#[foo] //~ ERROR `#[foo]` is only valid on functions and statics
macro bar() {}
#[foo()]
diff --git a/tests/ui/eii/errors.stderr b/tests/ui/eii/errors.stderr
index c7eb96a9c2190..553ae622cb36f 100644
--- a/tests/ui/eii/errors.stderr
+++ b/tests/ui/eii/errors.stderr
@@ -52,47 +52,41 @@ error: `#[eii_declaration(...)]` expects a list of one or two elements
LL | #[eii_declaration = "unsafe"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/errors.rs:28:1
|
LL | #[foo]
| ^^^^^^
-error: `#[foo]` is only valid on functions
+error: `#[foo]` is only valid on functions and statics
--> $DIR/errors.rs:30:1
|
LL | #[foo]
| ^^^^^^
-error: `#[foo]` is only valid on functions
- --> $DIR/errors.rs:32:1
- |
-LL | #[foo]
- | ^^^^^^
-
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
- --> $DIR/errors.rs:35:1
+ --> $DIR/errors.rs:33:1
|
LL | #[foo()]
| ^^^^^^^^
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
- --> $DIR/errors.rs:37:1
+ --> $DIR/errors.rs:35:1
|
LL | #[foo(default, bar)]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
- --> $DIR/errors.rs:39:1
+ --> $DIR/errors.rs:37:1
|
LL | #[foo("default")]
| ^^^^^^^^^^^^^^^^^
error: `#[foo]` expected no arguments or a single argument: `#[foo(default)]`
- --> $DIR/errors.rs:41:1
+ --> $DIR/errors.rs:39:1
|
LL | #[foo = "default"]
| ^^^^^^^^^^^^^^^^^^
-error: aborting due to 15 previous errors
+error: aborting due to 14 previous errors
diff --git a/tests/ui/eii/linking/codegen_cross_crate.rs b/tests/ui/eii/linking/codegen_cross_crate.rs
index 2958a0f10521b..192aac5920704 100644
--- a/tests/ui/eii/linking/codegen_cross_crate.rs
+++ b/tests/ui/eii/linking/codegen_cross_crate.rs
@@ -3,7 +3,7 @@
//@ aux-build: codegen_cross_crate_other_crate.rs
//@ compile-flags: -O
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests whether calling EIIs works with the declaration in another crate.
diff --git a/tests/ui/eii/linking/codegen_single_crate.rs b/tests/ui/eii/linking/codegen_single_crate.rs
index 8e85c354bba1c..d0e9c015da418 100644
--- a/tests/ui/eii/linking/codegen_single_crate.rs
+++ b/tests/ui/eii/linking/codegen_single_crate.rs
@@ -1,7 +1,7 @@
//@ run-pass
//@ check-run-results
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
// Tests whether calling EIIs works with the declaration in the same crate.
#![feature(extern_item_impls)]
diff --git a/tests/ui/eii/linking/same-symbol.rs b/tests/ui/eii/linking/same-symbol.rs
index baf36ff4f5a0a..afba9b7750262 100644
--- a/tests/ui/eii/linking/same-symbol.rs
+++ b/tests/ui/eii/linking/same-symbol.rs
@@ -1,7 +1,7 @@
//@ run-pass
//@ check-run-results
//@ ignore-backends: gcc
-// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
//@ ignore-windows
#![feature(extern_item_impls)]
diff --git a/tests/ui/eii/shadow_builtin.rs b/tests/ui/eii/shadow_builtin.rs
new file mode 100644
index 0000000000000..5f619b79d01a4
--- /dev/null
+++ b/tests/ui/eii/shadow_builtin.rs
@@ -0,0 +1,17 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether calling EIIs works with the declaration in the same crate.
+#![feature(extern_item_impls)]
+
+#[eii(inline)]
+//~^ ERROR `#[inline]` required, but not found
+fn test(x: u64);
+
+#[inline]
+//~^ ERROR `inline` is ambiguous
+fn test_impl(x: u64) {
+ println!("{x:?}")
+}
+
+fn main() { }
diff --git a/tests/ui/eii/shadow_builtin.stderr b/tests/ui/eii/shadow_builtin.stderr
new file mode 100644
index 0000000000000..d48e66a18af20
--- /dev/null
+++ b/tests/ui/eii/shadow_builtin.stderr
@@ -0,0 +1,26 @@
+error[E0659]: `inline` is ambiguous
+ --> $DIR/shadow_builtin.rs:11:3
+ |
+LL | #[inline]
+ | ^^^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a builtin attribute
+ = note: `inline` could refer to a built-in attribute
+note: `inline` could also refer to the attribute macro defined here
+ --> $DIR/shadow_builtin.rs:7:1
+ |
+LL | #[eii(inline)]
+ | ^^^^^^^^^^^^^^
+ = help: use `crate::inline` to refer to this attribute macro unambiguously
+
+error: `#[inline]` required, but not found
+ --> $DIR/shadow_builtin.rs:7:7
+ |
+LL | #[eii(inline)]
+ | ^^^^^^ expected because `#[inline]` was declared here in crate `shadow_builtin`
+ |
+ = help: expected at least one implementation in crate `shadow_builtin` or any of its dependencies
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/eii/static/argument_required.rs b/tests/ui/eii/static/argument_required.rs
new file mode 100644
index 0000000000000..114b8a35de5cf
--- /dev/null
+++ b/tests/ui/eii/static/argument_required.rs
@@ -0,0 +1,11 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii]
+//~^ ERROR `#[eii]` requires the name as an explicit argument when used on a static
+static HELLO: u64;
+
+fn main() { }
diff --git a/tests/ui/eii/static/argument_required.stderr b/tests/ui/eii/static/argument_required.stderr
new file mode 100644
index 0000000000000..9e5ee398f77d8
--- /dev/null
+++ b/tests/ui/eii/static/argument_required.stderr
@@ -0,0 +1,8 @@
+error: `#[eii]` requires the name as an explicit argument when used on a static
+ --> $DIR/argument_required.rs:7:1
+ |
+LL | #[eii]
+ | ^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/auxiliary/cross_crate_decl.rs b/tests/ui/eii/static/auxiliary/cross_crate_decl.rs
new file mode 100644
index 0000000000000..06b7daca22074
--- /dev/null
+++ b/tests/ui/eii/static/auxiliary/cross_crate_decl.rs
@@ -0,0 +1,6 @@
+//@ no-prefer-dynamic
+#![crate_type = "rlib"]
+#![feature(extern_item_impls)]
+
+#[eii(eii1)]
+pub static DECL1: u64;
diff --git a/tests/ui/eii/static/auxiliary/cross_crate_def.rs b/tests/ui/eii/static/auxiliary/cross_crate_def.rs
new file mode 100644
index 0000000000000..70933440a62be
--- /dev/null
+++ b/tests/ui/eii/static/auxiliary/cross_crate_def.rs
@@ -0,0 +1,9 @@
+//@ no-prefer-dynamic
+#![crate_type = "rlib"]
+#![feature(extern_item_impls)]
+
+#[eii(eii1)]
+pub static DECL1: u64;
+
+#[eii1]
+pub static EII1_IMPL: u64 = 5;
diff --git a/tests/ui/eii/static/cross_crate_decl.rs b/tests/ui/eii/static/cross_crate_decl.rs
new file mode 100644
index 0000000000000..63e3511198e1d
--- /dev/null
+++ b/tests/ui/eii/static/cross_crate_decl.rs
@@ -0,0 +1,21 @@
+//@ run-pass
+//@ check-run-results
+//@ aux-build: cross_crate_decl.rs
+//@ compile-flags: -O
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether calling EIIs works with the declaration in another crate.
+
+extern crate cross_crate_decl as codegen;
+
+#[codegen::eii1]
+static EII1_IMPL: u64 = 5;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{}", EII1_IMPL);
+ // through the alias
+ println!("{}", codegen::DECL1);
+}
diff --git a/tests/ui/eii/static/cross_crate_decl.run.stdout b/tests/ui/eii/static/cross_crate_decl.run.stdout
new file mode 100644
index 0000000000000..fd3c81a4d7631
--- /dev/null
+++ b/tests/ui/eii/static/cross_crate_decl.run.stdout
@@ -0,0 +1,2 @@
+5
+5
diff --git a/tests/ui/eii/static/cross_crate_def.rs b/tests/ui/eii/static/cross_crate_def.rs
new file mode 100644
index 0000000000000..a0b6afbfd760b
--- /dev/null
+++ b/tests/ui/eii/static/cross_crate_def.rs
@@ -0,0 +1,18 @@
+//@ run-pass
+//@ check-run-results
+//@ aux-build: cross_crate_def.rs
+//@ compile-flags: -O
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether calling EIIs works with the declaration and definition in another crate.
+
+extern crate cross_crate_def as codegen;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{}", codegen::EII1_IMPL);
+ // through the alias
+ println!("{}", codegen::DECL1);
+}
diff --git a/tests/ui/eii/static/cross_crate_def.run.stdout b/tests/ui/eii/static/cross_crate_def.run.stdout
new file mode 100644
index 0000000000000..fd3c81a4d7631
--- /dev/null
+++ b/tests/ui/eii/static/cross_crate_def.run.stdout
@@ -0,0 +1,2 @@
+5
+5
diff --git a/tests/ui/eii/static/duplicate.rs b/tests/ui/eii/static/duplicate.rs
new file mode 100644
index 0000000000000..12b2e56c07e4e
--- /dev/null
+++ b/tests/ui/eii/static/duplicate.rs
@@ -0,0 +1,25 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+static HELLO: u64;
+
+#[hello]
+static HELLO_IMPL1: u64 = 5;
+//~^ ERROR multiple implementations of `#[hello]`
+
+#[hello]
+static HELLO_IMPL2: u64 = 6;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{HELLO_IMPL1}");
+ println!("{HELLO_IMPL2}");
+
+ // through the alias
+ println!("{HELLO}");
+}
diff --git a/tests/ui/eii/static/duplicate.stderr b/tests/ui/eii/static/duplicate.stderr
new file mode 100644
index 0000000000000..270664c8c74c6
--- /dev/null
+++ b/tests/ui/eii/static/duplicate.stderr
@@ -0,0 +1,13 @@
+error: multiple implementations of `#[hello]`
+ --> $DIR/duplicate.rs:11:1
+ |
+LL | static HELLO_IMPL1: u64 = 5;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ first implemented here in crate `duplicate`
+...
+LL | static HELLO_IMPL2: u64 = 6;
+ | ----------------------- also implemented here in crate `duplicate`
+ |
+ = help: an "externally implementable item" can only have a single implementation in the final artifact. When multiple implementations are found, also in different crates, they conflict
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/mismatch_fn_static.rs b/tests/ui/eii/static/mismatch_fn_static.rs
new file mode 100644
index 0000000000000..298fdca18d967
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_fn_static.rs
@@ -0,0 +1,14 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+fn hello() -> u64;
+
+#[hello]
+//~^ ERROR `#[hello]` must be used on a function
+static HELLO_IMPL: u64 = 5;
+
+fn main() { }
diff --git a/tests/ui/eii/static/mismatch_fn_static.stderr b/tests/ui/eii/static/mismatch_fn_static.stderr
new file mode 100644
index 0000000000000..e8fa5f85b1f13
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_fn_static.stderr
@@ -0,0 +1,8 @@
+error: `#[hello]` must be used on a function
+ --> $DIR/mismatch_fn_static.rs:10:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/mismatch_mut.rs b/tests/ui/eii/static/mismatch_mut.rs
new file mode 100644
index 0000000000000..87c2c4128aa5e
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_mut.rs
@@ -0,0 +1,22 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+//~^ ERROR `#[eii]` cannot be used on mutable statics
+static mut HELLO: u64;
+
+#[hello]
+//~^ ERROR mutability does not match with the definition of`#[hello]`
+static HELLO_IMPL: u64 = 5;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{HELLO_IMPL}");
+
+ // through the alias
+ println!("{}", unsafe { HELLO });
+}
diff --git a/tests/ui/eii/static/mismatch_mut.stderr b/tests/ui/eii/static/mismatch_mut.stderr
new file mode 100644
index 0000000000000..537ac0de3c3a2
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_mut.stderr
@@ -0,0 +1,14 @@
+error: `#[eii]` cannot be used on mutable statics
+ --> $DIR/mismatch_mut.rs:7:1
+ |
+LL | #[eii(hello)]
+ | ^^^^^^^^^^^^^
+
+error: mutability does not match with the definition of`#[hello]`
+ --> $DIR/mismatch_mut.rs:11:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/eii/static/mismatch_mut2.rs b/tests/ui/eii/static/mismatch_mut2.rs
new file mode 100644
index 0000000000000..ab525e418adeb
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_mut2.rs
@@ -0,0 +1,21 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+static HELLO: u64;
+
+#[hello]
+//~^ ERROR mutability does not match with the definition of`#[hello]`
+static mut HELLO_IMPL: u64 = 5;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{}", unsafe { HELLO_IMPL });
+
+ // through the alias
+ println!("{HELLO}");
+}
diff --git a/tests/ui/eii/static/mismatch_mut2.stderr b/tests/ui/eii/static/mismatch_mut2.stderr
new file mode 100644
index 0000000000000..6ac3df57697db
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_mut2.stderr
@@ -0,0 +1,8 @@
+error: mutability does not match with the definition of`#[hello]`
+ --> $DIR/mismatch_mut2.rs:10:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/mismatch_safety.rs b/tests/ui/eii/static/mismatch_safety.rs
new file mode 100644
index 0000000000000..f30326b0755c0
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_safety.rs
@@ -0,0 +1,21 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+unsafe static HELLO: u64;
+
+#[hello]
+//~^ ERROR safety does not match with the definition of`#[hello]`
+static HELLO_IMPL: u64 = 5;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{HELLO_IMPL}");
+
+ // through the alias
+ println!("{}", unsafe { HELLO });
+}
diff --git a/tests/ui/eii/static/mismatch_safety.stderr b/tests/ui/eii/static/mismatch_safety.stderr
new file mode 100644
index 0000000000000..d4fa85778ae11
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_safety.stderr
@@ -0,0 +1,8 @@
+error: safety does not match with the definition of`#[hello]`
+ --> $DIR/mismatch_safety.rs:10:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/mismatch_safety2.rs b/tests/ui/eii/static/mismatch_safety2.rs
new file mode 100644
index 0000000000000..dea45c26292d8
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_safety2.rs
@@ -0,0 +1,21 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+static HELLO: u64;
+
+#[hello]
+unsafe static HELLO_IMPL: u64 = 5;
+//~^ ERROR static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{HELLO_IMPL}");
+
+ // through the alias
+ println!("{}", unsafe { HELLO });
+}
diff --git a/tests/ui/eii/static/mismatch_safety2.stderr b/tests/ui/eii/static/mismatch_safety2.stderr
new file mode 100644
index 0000000000000..6957a6202b614
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_safety2.stderr
@@ -0,0 +1,8 @@
+error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+ --> $DIR/mismatch_safety2.rs:11:1
+ |
+LL | unsafe static HELLO_IMPL: u64 = 5;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/mismatch_static_fn.rs b/tests/ui/eii/static/mismatch_static_fn.rs
new file mode 100644
index 0000000000000..cd9a8109dc339
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_static_fn.rs
@@ -0,0 +1,16 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+static HELLO: u64;
+
+#[hello]
+//~^ ERROR `#[hello]` must be used on a static
+fn hello_impl() -> u64 {
+ 5
+}
+
+fn main() { }
diff --git a/tests/ui/eii/static/mismatch_static_fn.stderr b/tests/ui/eii/static/mismatch_static_fn.stderr
new file mode 100644
index 0000000000000..639e3cfa3beb3
--- /dev/null
+++ b/tests/ui/eii/static/mismatch_static_fn.stderr
@@ -0,0 +1,8 @@
+error: `#[hello]` must be used on a static
+ --> $DIR/mismatch_static_fn.rs:10:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/multiple_decls.rs b/tests/ui/eii/static/multiple_decls.rs
new file mode 100644
index 0000000000000..791e2725087f1
--- /dev/null
+++ b/tests/ui/eii/static/multiple_decls.rs
@@ -0,0 +1,12 @@
+#![feature(extern_item_impls)]
+
+const A: () = ();
+#[eii(A)]
+static A: u64;
+//~^ ERROR the name `A` is defined multiple times
+//~| ERROR expected function or static, found constant `A`
+
+#[A]
+static A_IMPL: u64 = 5;
+
+fn main() {}
diff --git a/tests/ui/eii/static/multiple_decls.stderr b/tests/ui/eii/static/multiple_decls.stderr
new file mode 100644
index 0000000000000..fcc5d93c5f993
--- /dev/null
+++ b/tests/ui/eii/static/multiple_decls.stderr
@@ -0,0 +1,21 @@
+error[E0428]: the name `A` is defined multiple times
+ --> $DIR/multiple_decls.rs:5:1
+ |
+LL | const A: () = ();
+ | ----------------- previous definition of the value `A` here
+LL | #[eii(A)]
+LL | static A: u64;
+ | ^^^^^^^^^^^^^^ `A` redefined here
+ |
+ = note: `A` must be defined only once in the value namespace of this module
+
+error[E0423]: expected function or static, found constant `A`
+ --> $DIR/multiple_decls.rs:5:8
+ |
+LL | static A: u64;
+ | ^ not a function or static
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0428.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/eii/static/multiple_impls.rs b/tests/ui/eii/static/multiple_impls.rs
new file mode 100644
index 0000000000000..8ad7d87040a36
--- /dev/null
+++ b/tests/ui/eii/static/multiple_impls.rs
@@ -0,0 +1,20 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether one function could implement two EIIs.
+#![feature(extern_item_impls)]
+
+#[eii(a)]
+static A: u64;
+
+#[eii(b)]
+static B: u64;
+
+#[a]
+#[b]
+//~^ ERROR static cannot implement multiple EIIs
+static IMPL: u64 = 5;
+
+fn main() {
+ println!("{A} {B} {IMPL}")
+}
diff --git a/tests/ui/eii/static/multiple_impls.run.stdout b/tests/ui/eii/static/multiple_impls.run.stdout
new file mode 100644
index 0000000000000..58945c2b48291
--- /dev/null
+++ b/tests/ui/eii/static/multiple_impls.run.stdout
@@ -0,0 +1 @@
+5 5 5
diff --git a/tests/ui/eii/static/multiple_impls.stderr b/tests/ui/eii/static/multiple_impls.stderr
new file mode 100644
index 0000000000000..b31331f2483f1
--- /dev/null
+++ b/tests/ui/eii/static/multiple_impls.stderr
@@ -0,0 +1,10 @@
+error: static cannot implement multiple EIIs
+ --> $DIR/multiple_impls.rs:14:1
+ |
+LL | #[b]
+ | ^^^^
+ |
+ = note: this is not allowed because multiple externally implementable statics that alias may be unintuitive
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/mut.rs b/tests/ui/eii/static/mut.rs
new file mode 100644
index 0000000000000..803ffc2297992
--- /dev/null
+++ b/tests/ui/eii/static/mut.rs
@@ -0,0 +1,21 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+//~^ ERROR `#[eii]` cannot be used on mutable statics
+static mut HELLO: u64;
+
+#[hello]
+static mut HELLO_IMPL: u64 = 5;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{}", unsafe { HELLO_IMPL });
+
+ // through the alias
+ println!("{}", unsafe { HELLO });
+}
diff --git a/tests/ui/eii/static/mut.run.stdout b/tests/ui/eii/static/mut.run.stdout
new file mode 100644
index 0000000000000..fd3c81a4d7631
--- /dev/null
+++ b/tests/ui/eii/static/mut.run.stdout
@@ -0,0 +1,2 @@
+5
+5
diff --git a/tests/ui/eii/static/mut.stderr b/tests/ui/eii/static/mut.stderr
new file mode 100644
index 0000000000000..cd3a0ca23c7f4
--- /dev/null
+++ b/tests/ui/eii/static/mut.stderr
@@ -0,0 +1,8 @@
+error: `#[eii]` cannot be used on mutable statics
+ --> $DIR/mut.rs:7:1
+ |
+LL | #[eii(hello)]
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eii/static/same_address.rs b/tests/ui/eii/static/same_address.rs
new file mode 100644
index 0000000000000..81de19406dc49
--- /dev/null
+++ b/tests/ui/eii/static/same_address.rs
@@ -0,0 +1,21 @@
+//@ run-pass
+//@ check-run-results
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs and their declarations share the same address
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+static HELLO: u64;
+
+#[hello]
+static HELLO_IMPL: u64 = 5;
+
+// what you would write:
+fn main() {
+ assert_eq!(
+ &HELLO as *const u64 as usize,
+ &HELLO_IMPL as *const u64 as usize,
+ )
+}
diff --git a/tests/ui/eii/static/simple.rs b/tests/ui/eii/static/simple.rs
new file mode 100644
index 0000000000000..661ab9b9835f2
--- /dev/null
+++ b/tests/ui/eii/static/simple.rs
@@ -0,0 +1,22 @@
+//@ run-pass
+//@ check-run-results
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests whether EIIs work on statics
+#![feature(extern_item_impls)]
+
+#[eii(hello)]
+static HELLO: u64;
+
+#[hello]
+static HELLO_IMPL: u64 = 5;
+
+// what you would write:
+fn main() {
+ // directly
+ println!("{HELLO_IMPL}");
+
+ // through the alias
+ println!("{HELLO}");
+}
diff --git a/tests/ui/eii/static/simple.run.stdout b/tests/ui/eii/static/simple.run.stdout
new file mode 100644
index 0000000000000..fd3c81a4d7631
--- /dev/null
+++ b/tests/ui/eii/static/simple.run.stdout
@@ -0,0 +1,2 @@
+5
+5
diff --git a/tests/ui/eii/static/subtype.rs b/tests/ui/eii/static/subtype.rs
new file mode 100644
index 0000000000000..d98e94fa90322
--- /dev/null
+++ b/tests/ui/eii/static/subtype.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests that mismatching types of the declaration and definition are rejected
+#![feature(extern_item_impls)]
+
+use std::ptr;
+
+#[eii(hello)]
+static HELLO: for<'a> fn(&'a u8) -> &'a u8;
+
+#[hello]
+static HELLO_IMPL: for<'a> fn(&'a u8) -> &'static u8 = |_| todo!();
+
+fn main() {
+
+}
diff --git a/tests/ui/eii/static/subtype_wrong.rs b/tests/ui/eii/static/subtype_wrong.rs
new file mode 100644
index 0000000000000..964a3d767b197
--- /dev/null
+++ b/tests/ui/eii/static/subtype_wrong.rs
@@ -0,0 +1,17 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests that mismatching types of the declaration and definition are rejected
+#![feature(extern_item_impls)]
+
+use std::ptr;
+
+#[eii(hello)]
+static HELLO: for<'a> fn(&'a u8) -> &'static u8;
+
+#[hello]
+static HELLO_IMPL: for<'a> fn(&'a u8) -> &'a u8 = |_| todo!();
+//~^ ERROR mismatched types
+
+fn main() {
+}
diff --git a/tests/ui/eii/static/subtype_wrong.stderr b/tests/ui/eii/static/subtype_wrong.stderr
new file mode 100644
index 0000000000000..a20074947c15d
--- /dev/null
+++ b/tests/ui/eii/static/subtype_wrong.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/subtype_wrong.rs:13:1
+ |
+LL | static HELLO_IMPL: for<'a> fn(&'a u8) -> &'a u8 = |_| todo!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'a> fn(&'a _) -> &'static _`
+ found fn pointer `for<'a> fn(&'a _) -> &'a _`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/eii/static/wrong_ty.rs b/tests/ui/eii/static/wrong_ty.rs
new file mode 100644
index 0000000000000..beee0a5a0857b
--- /dev/null
+++ b/tests/ui/eii/static/wrong_ty.rs
@@ -0,0 +1,18 @@
+//@ ignore-backends: gcc
+// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
+//@ ignore-windows
+// Tests that mismatching types of the declaration and definition are rejected
+#![feature(extern_item_impls)]
+
+use std::ptr;
+
+#[eii(hello)]
+static HELLO: u64;
+
+#[hello]
+static HELLO_IMPL: bool = true;
+//~^ ERROR static `HELLO_IMPL` has a type that is incompatible with the declaration of `#[hello]` [E0806]
+
+fn main() {
+
+}
diff --git a/tests/ui/eii/static/wrong_ty.stderr b/tests/ui/eii/static/wrong_ty.stderr
new file mode 100644
index 0000000000000..5095513527747
--- /dev/null
+++ b/tests/ui/eii/static/wrong_ty.stderr
@@ -0,0 +1,15 @@
+error[E0806]: static `HELLO_IMPL` has a type that is incompatible with the declaration of `#[hello]`
+ --> $DIR/wrong_ty.rs:13:1
+ |
+LL | static HELLO_IMPL: bool = true;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: expected this because of this attribute
+ --> $DIR/wrong_ty.rs:12:1
+ |
+LL | #[hello]
+ | ^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0806`.
diff --git a/tests/ui/feature-gates/feature-gate-diagnostic-on-move.rs b/tests/ui/feature-gates/feature-gate-diagnostic-on-move.rs
index a1f3b1fbbc860..a55a6260d6512 100644
--- a/tests/ui/feature-gates/feature-gate-diagnostic-on-move.rs
+++ b/tests/ui/feature-gates/feature-gate-diagnostic-on-move.rs
@@ -2,9 +2,8 @@
//! gate, but the fact that not adding the feature gate will cause the
//! diagnostic to not emit the custom diagnostic message
//!
-#[diagnostic::on_move(
- message = "Foo"
-)]
+#[diagnostic::on_move(message = "Foo")]
+//~^ WARN unknown diagnostic attribute
#[derive(Debug)]
struct Foo;
diff --git a/tests/ui/feature-gates/feature-gate-diagnostic-on-move.stderr b/tests/ui/feature-gates/feature-gate-diagnostic-on-move.stderr
index 9ba6f272cf92b..593120edd1700 100644
--- a/tests/ui/feature-gates/feature-gate-diagnostic-on-move.stderr
+++ b/tests/ui/feature-gates/feature-gate-diagnostic-on-move.stderr
@@ -1,5 +1,14 @@
+warning: unknown diagnostic attribute
+ --> $DIR/feature-gate-diagnostic-on-move.rs:5:15
+ |
+LL | #[diagnostic::on_move(message = "Foo")]
+ | ^^^^^^^
+ |
+ = help: add `#![feature(diagnostic_on_move)]` to the crate attributes to enable
+ = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
+
error[E0382]: use of moved value: `foo`
- --> $DIR/feature-gate-diagnostic-on-move.rs:16:15
+ --> $DIR/feature-gate-diagnostic-on-move.rs:15:15
|
LL | let foo = Foo;
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
@@ -9,14 +18,14 @@ LL | let bar = foo;
| ^^^ value used here after move
|
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
- --> $DIR/feature-gate-diagnostic-on-move.rs:11:17
+ --> $DIR/feature-gate-diagnostic-on-move.rs:10:17
|
LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value
| |
| in this function
note: if `Foo` implemented `Clone`, you could clone the value
- --> $DIR/feature-gate-diagnostic-on-move.rs:9:1
+ --> $DIR/feature-gate-diagnostic-on-move.rs:8:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -24,6 +33,6 @@ LL | struct Foo;
LL | takes_foo(foo);
| --- you could clone this value
-error: aborting due to 1 previous error
+error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/feature-gates/feature-gate-diagnostic-on-unknown.stderr b/tests/ui/feature-gates/feature-gate-diagnostic-on-unknown.stderr
index f6d7ffadaceae..d9c8071339b75 100644
--- a/tests/ui/feature-gates/feature-gate-diagnostic-on-unknown.stderr
+++ b/tests/ui/feature-gates/feature-gate-diagnostic-on-unknown.stderr
@@ -10,6 +10,7 @@ error: unknown diagnostic attribute
LL | #[diagnostic::on_unknown(message = "Tada")]
| ^^^^^^^^^^
|
+ = help: add `#![feature(diagnostic_on_unknown)]` to the crate attributes to enable
note: the lint level is defined here
--> $DIR/feature-gate-diagnostic-on-unknown.rs:1:9
|
diff --git a/tests/ui/imports/issue-56125.rs b/tests/ui/imports/issue-56125.rs
index 4e7e7ac67c572..a30ac36473bdd 100644
--- a/tests/ui/imports/issue-56125.rs
+++ b/tests/ui/imports/issue-56125.rs
@@ -15,7 +15,7 @@ mod m2 {
mod m3 {
mod empty {}
use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125`
- use issue_56125::*; //~ ERROR `issue_56125` is ambiguous
+ use issue_56125::*;
}
fn main() {}
diff --git a/tests/ui/imports/issue-56125.stderr b/tests/ui/imports/issue-56125.stderr
index 371130facf9d3..f9a169b17a2f9 100644
--- a/tests/ui/imports/issue-56125.stderr
+++ b/tests/ui/imports/issue-56125.stderr
@@ -54,24 +54,7 @@ LL | use issue_56125::non_last_segment::non_last_segment::*;
= help: consider adding an explicit import of `issue_56125` to disambiguate
= help: or use `self::issue_56125` to refer to this module unambiguously
-error[E0659]: `issue_56125` is ambiguous
- --> $DIR/issue-56125.rs:18:9
- |
-LL | use issue_56125::*;
- | ^^^^^^^^^^^ ambiguous name
- |
- = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
- = note: `issue_56125` could refer to a crate passed with `--extern`
- = help: use `::issue_56125` to refer to this crate unambiguously
-note: `issue_56125` could also refer to the module imported here
- --> $DIR/issue-56125.rs:18:9
- |
-LL | use issue_56125::*;
- | ^^^^^^^^^^^^^^
- = help: consider adding an explicit import of `issue_56125` to disambiguate
- = help: or use `self::issue_56125` to refer to this module unambiguously
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
Some errors have detailed explanations: E0432, E0659.
For more information about an error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.rs b/tests/ui/imports/shadow-glob-module-resolution-2.rs
index c3abd1f75542c..ac2901eb35290 100644
--- a/tests/ui/imports/shadow-glob-module-resolution-2.rs
+++ b/tests/ui/imports/shadow-glob-module-resolution-2.rs
@@ -14,7 +14,5 @@ use a::*;
use e as b;
//~^ ERROR: unresolved import `e`
use b::c::D as e;
-//~^ ERROR: cannot determine resolution for the import
-//~| ERROR: cannot determine resolution for the import
fn main() { }
diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.stderr b/tests/ui/imports/shadow-glob-module-resolution-2.stderr
index 26745384dee34..ba8a2ce2d29f8 100644
--- a/tests/ui/imports/shadow-glob-module-resolution-2.stderr
+++ b/tests/ui/imports/shadow-glob-module-resolution-2.stderr
@@ -1,17 +1,3 @@
-error: cannot determine resolution for the import
- --> $DIR/shadow-glob-module-resolution-2.rs:16:5
- |
-LL | use b::c::D as e;
- | ^^^^^^^^^^^^
-
-error: cannot determine resolution for the import
- --> $DIR/shadow-glob-module-resolution-2.rs:16:5
- |
-LL | use b::c::D as e;
- | ^^^^^^^^^^^^
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
error[E0432]: unresolved import `e`
--> $DIR/shadow-glob-module-resolution-2.rs:14:5
|
@@ -24,6 +10,6 @@ LL - use e as b;
LL + use a as b;
|
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/shadow-glob-module-resolution-4.rs b/tests/ui/imports/shadow-glob-module-resolution-4.rs
index 581cdc185d3f3..38fe7d17a367f 100644
--- a/tests/ui/imports/shadow-glob-module-resolution-4.rs
+++ b/tests/ui/imports/shadow-glob-module-resolution-4.rs
@@ -12,8 +12,6 @@ use e as b;
use b::C as e;
//~^ ERROR: unresolved import `b::C`
-//~| ERROR: cannot determine resolution for the import
-//~| ERROR: cannot determine resolution for the import
fn e() {}
diff --git a/tests/ui/imports/shadow-glob-module-resolution-4.stderr b/tests/ui/imports/shadow-glob-module-resolution-4.stderr
index 063beb612b132..d94a59347a5b8 100644
--- a/tests/ui/imports/shadow-glob-module-resolution-4.stderr
+++ b/tests/ui/imports/shadow-glob-module-resolution-4.stderr
@@ -1,23 +1,9 @@
-error: cannot determine resolution for the import
- --> $DIR/shadow-glob-module-resolution-4.rs:13:5
- |
-LL | use b::C as e;
- | ^^^^^^^^^
-
-error: cannot determine resolution for the import
- --> $DIR/shadow-glob-module-resolution-4.rs:13:5
- |
-LL | use b::C as e;
- | ^^^^^^^^^
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
error[E0432]: unresolved import `b::C`
--> $DIR/shadow-glob-module-resolution-4.rs:13:5
|
LL | use b::C as e;
| ^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0432`.