diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
index d406c30b83ef3..e4ced2e37c55d 100644
--- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
@@ -1,6 +1,6 @@
use rustc_feature::{AttributeTemplate, template};
-use rustc_hir::attrs::AttributeKind;
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
+use rustc_hir::attrs::{AttributeKind, Linkage};
use rustc_span::{Span, Symbol, sym};
use crate::attributes::{
@@ -129,3 +129,77 @@ impl SingleAttributeParser for LinkOrdinalParser {
Some(LinkOrdinal { ordinal, span: cx.attr_span })
}
}
+
+pub(crate) struct LinkageParser;
+
+impl SingleAttributeParser for LinkageParser {
+ const PATH: &[Symbol] = &[sym::linkage];
+
+ const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+
+ const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error;
+
+ const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
+ "available_externally",
+ "common",
+ "extern_weak",
+ "external",
+ "internal",
+ "linkonce",
+ "linkonce_odr",
+ "weak",
+ "weak_odr",
+ ]);
+
+ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option {
+ let Some(name_value) = args.name_value() else {
+ cx.expected_name_value(cx.attr_span, Some(sym::linkage));
+ return None;
+ };
+
+ let Some(value) = name_value.value_as_str() else {
+ cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
+ return None;
+ };
+
+ // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+ // applicable to variable declarations and may not really make sense for
+ // Rust code in the first place but allow them anyway and trust that the
+ // user knows what they're doing. Who knows, unanticipated use cases may pop
+ // up in the future.
+ //
+ // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+ // and don't have to be, LLVM treats them as no-ops.
+ let linkage = match value {
+ sym::available_externally => Linkage::AvailableExternally,
+ sym::common => Linkage::Common,
+ sym::extern_weak => Linkage::ExternalWeak,
+ sym::external => Linkage::External,
+ sym::internal => Linkage::Internal,
+ sym::linkonce => Linkage::LinkOnceAny,
+ sym::linkonce_odr => Linkage::LinkOnceODR,
+ sym::weak => Linkage::WeakAny,
+ sym::weak_odr => Linkage::WeakODR,
+
+ _ => {
+ cx.expected_specific_argument(
+ name_value.value_span,
+ vec![
+ "available_externally",
+ "common",
+ "extern_weak",
+ "external",
+ "internal",
+ "linkonce",
+ "linkonce_odr",
+ "weak",
+ "weak_odr",
+ ],
+ );
+ return None;
+ }
+ };
+
+ Some(AttributeKind::Linkage(linkage, cx.attr_span))
+ }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 1420753a44ea2..6045a8b28a225 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -27,7 +27,7 @@ use crate::attributes::dummy::DummyParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::link_attrs::{
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
- LinkSectionParser, StdInternalSymbolParser,
+ LinkSectionParser, LinkageParser, StdInternalSymbolParser,
};
use crate::attributes::lint_helpers::{
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@@ -167,6 +167,7 @@ attribute_parsers!(
Single,
Single,
Single,
+ Single,
Single,
Single,
Single,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 5d9416b59fcec..c0ca35f9ff83a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -677,12 +677,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// - is the trait from the local crate? If not, we can't suggest changing signatures
/// - `Span` of the argument in the trait definition
fn is_error_in_trait(&self, local: Local) -> (bool, bool, Option) {
+ let tcx = self.infcx.tcx;
if self.body.local_kind(local) != LocalKind::Arg {
return (false, false, None);
}
let my_def = self.body.source.def_id();
let Some(td) =
- self.infcx.tcx.impl_of_assoc(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x))
+ tcx.trait_impl_of_assoc(my_def).and_then(|id| self.infcx.tcx.trait_id_of_impl(id))
else {
return (false, false, None);
};
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index c3aa205d5aab3..a960b96b91c20 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1773,10 +1773,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
locations,
);
- assert!(!matches!(
- tcx.impl_of_assoc(def_id).map(|imp| tcx.def_kind(imp)),
- Some(DefKind::Impl { of_trait: true })
- ));
+ assert_eq!(tcx.trait_impl_of_assoc(def_id), None);
self.prove_predicates(
args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
locations,
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index bec546badc9cf..a56466750e75c 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -281,8 +281,8 @@ fn data_id_for_static(
.abi
.bytes();
- let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
- || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
+ let linkage = if import_linkage == rustc_hir::attrs::Linkage::ExternalWeak
+ || import_linkage == rustc_hir::attrs::Linkage::WeakAny
{
Linkage::Preemptible
} else {
@@ -332,8 +332,8 @@ fn data_id_for_static(
let linkage = if definition {
crate::linkage::get_static_linkage(tcx, def_id)
- } else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
- || attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
+ } else if attrs.linkage == Some(rustc_hir::attrs::Linkage::ExternalWeak)
+ || attrs.linkage == Some(rustc_hir::attrs::Linkage::WeakAny)
{
Linkage::Preemptible
} else {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 8ec3599b63d89..7e77781dc2fc1 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -18,12 +18,11 @@ use rustc_codegen_ssa::{
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
+use rustc_hir::attrs::Linkage as RLinkage;
use rustc_metadata::fs::copy_to_stdout;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::mono::{
- CodegenUnit, Linkage as RLinkage, MonoItem, MonoItemData, Visibility,
-};
+use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility};
use rustc_session::Session;
use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
diff --git a/compiler/rustc_codegen_cranelift/src/linkage.rs b/compiler/rustc_codegen_cranelift/src/linkage.rs
index ca853aac15892..d76ab9d0109f0 100644
--- a/compiler/rustc_codegen_cranelift/src/linkage.rs
+++ b/compiler/rustc_codegen_cranelift/src/linkage.rs
@@ -1,4 +1,5 @@
-use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
+use rustc_hir::attrs::Linkage as RLinkage;
+use rustc_middle::mir::mono::{MonoItem, Visibility};
use crate::prelude::*;
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index c105916bbb2b5..e9d72e457a086 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -8,8 +8,8 @@ use rustc_codegen_ssa::ModuleCodegen;
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
+use rustc_hir::attrs::Linkage;
use rustc_middle::dep_graph;
-use rustc_middle::mir::mono::Linkage;
#[cfg(feature = "master")]
use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 873f1f1951c10..619277eba8b83 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -5,13 +5,13 @@ use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRang
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
};
+use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::interpret::{
self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint,
};
-use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index ff188c437daea..35d44d21bcbf6 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -1,11 +1,12 @@
#[cfg(feature = "master")]
use gccjit::{FnAttribute, VarAttribute};
use rustc_codegen_ssa::traits::PreDefineCodegenMethods;
+use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 5dda836988c81..9cc5d8dbc21cf 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -18,9 +18,10 @@ use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::attrs::Linkage;
use rustc_middle::dep_graph;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::DebugInfo;
use rustc_span::Symbol;
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 6b06daf3477f8..9ec7b0f80aee7 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -4,6 +4,7 @@ use rustc_abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange};
use rustc_codegen_ssa::common;
use rustc_codegen_ssa::traits::*;
use rustc_hir::LangItem;
+use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -11,7 +12,7 @@ use rustc_middle::mir::interpret::{
Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer, Scalar as InterpScalar,
read_target_uint,
};
-use rustc_middle::mir::mono::{Linkage, MonoItem};
+use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 6cbf2dbf7d3fd..2c3a84499ac55 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -533,31 +533,26 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
// First, let's see if this is a method within an inherent impl. Because
// if yes, we want to make the result subroutine DIE a child of the
// subroutine's self-type.
- if let Some(impl_def_id) = cx.tcx.impl_of_assoc(instance.def_id()) {
- // If the method does *not* belong to a trait, proceed
- if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
- let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
- instance.args,
- cx.typing_env(),
- cx.tcx.type_of(impl_def_id),
- );
-
- // Only "class" methods are generally understood by LLVM,
- // so avoid methods on other types (e.g., `<*mut T>::null`).
- if let ty::Adt(def, ..) = impl_self_ty.kind()
- && !def.is_box()
- {
- // Again, only create type information if full debuginfo is enabled
- if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param()
- {
- return (type_di_node(cx, impl_self_ty), true);
- } else {
- return (namespace::item_namespace(cx, def.did()), false);
- }
+ // For trait method impls we still use the "parallel namespace"
+ // strategy
+ if let Some(imp_def_id) = cx.tcx.inherent_impl_of_assoc(instance.def_id()) {
+ let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions(
+ instance.args,
+ cx.typing_env(),
+ cx.tcx.type_of(imp_def_id),
+ );
+
+ // Only "class" methods are generally understood by LLVM,
+ // so avoid methods on other types (e.g., `<*mut T>::null`).
+ if let ty::Adt(def, ..) = impl_self_ty.kind()
+ && !def.is_box()
+ {
+ // Again, only create type information if full debuginfo is enabled
+ if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() {
+ return (type_di_node(cx, impl_self_ty), true);
+ } else {
+ return (namespace::item_namespace(cx, def.did()), false);
}
- } else {
- // For trait method impls we still use the "parallel namespace"
- // strategy
}
}
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index f9edaded60de6..5075befae8a54 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -1,8 +1,9 @@
use rustc_codegen_ssa::traits::*;
+use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_session::config::CrateType;
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 0494666bda923..77096822fdc4d 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -306,7 +306,8 @@ fn exported_generic_symbols_provider_local<'tcx>(
let mut symbols: Vec<_> = vec![];
if tcx.local_crate_exports_generics() {
- use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
+ use rustc_hir::attrs::Linkage;
+ use rustc_middle::mir::mono::{MonoItem, Visibility};
use rustc_middle::ty::InstanceKind;
// Normally, we require that shared monomorphizations are not hidden,
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 287787eb3d1ff..a36a772bc9719 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -11,7 +11,6 @@ use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
};
-use rustc_middle::mir::mono::Linkage;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{self as ty, TyCtxt};
@@ -26,31 +25,6 @@ use crate::target_features::{
check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr,
};
-fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
- use rustc_middle::mir::mono::Linkage::*;
-
- // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
- // applicable to variable declarations and may not really make sense for
- // Rust code in the first place but allow them anyway and trust that the
- // user knows what they're doing. Who knows, unanticipated use cases may pop
- // up in the future.
- //
- // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
- // and don't have to be, LLVM treats them as no-ops.
- match name {
- "available_externally" => AvailableExternally,
- "common" => Common,
- "extern_weak" => ExternalWeak,
- "external" => External,
- "internal" => Internal,
- "linkonce" => LinkOnceAny,
- "linkonce_odr" => LinkOnceODR,
- "weak" => WeakAny,
- "weak_odr" => WeakODR,
- _ => tcx.dcx().span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
- }
-}
-
/// In some cases, attributes are only valid on functions, but it's the `check_attr`
/// pass that checks that they aren't used anywhere else, rather than this module.
/// In these cases, we bail from performing further checks that are only meaningful for
@@ -103,13 +77,6 @@ fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option, did: LocalDefId, attr: &Attribute) -> Option {
- let val = attr.value_str()?;
- let linkage = linkage_by_name(tcx, did, val.as_str());
- Some(linkage)
-}
-
// FIXME(jdonszelmann): remove when no_sanitize becomes a parsed attr
fn parse_no_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option {
let list = attr.meta_item_list()?;
@@ -332,6 +299,28 @@ fn process_builtin_attrs(
AttributeKind::StdInternalSymbol(_) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
}
+ AttributeKind::Linkage(linkage, _) => {
+ let linkage = Some(*linkage);
+
+ if tcx.is_foreign_item(did) {
+ codegen_fn_attrs.import_linkage = linkage;
+
+ if tcx.is_mutable_static(did.into()) {
+ let mut diag = tcx.dcx().struct_span_err(
+ attr.span(),
+ "extern mutable statics are not allowed with `#[linkage]`",
+ );
+ diag.note(
+ "marking the extern static mutable would allow changing which \
+ symbol the static references rather than make the target of the \
+ symbol mutable",
+ );
+ diag.emit();
+ }
+ } else {
+ codegen_fn_attrs.linkage = linkage;
+ }
+ }
_ => {}
}
}
@@ -349,28 +338,6 @@ fn process_builtin_attrs(
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
- sym::linkage => {
- let linkage = parse_linkage_attr(tcx, did, attr);
-
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.import_linkage = linkage;
-
- if tcx.is_mutable_static(did.into()) {
- let mut diag = tcx.dcx().struct_span_err(
- attr.span(),
- "extern mutable statics are not allowed with `#[linkage]`",
- );
- diag.note(
- "marking the extern static mutable would allow changing which \
- symbol the static references rather than make the target of the \
- symbol mutable",
- );
- diag.emit();
- }
- } else {
- codegen_fn_attrs.linkage = linkage;
- }
- }
sym::no_sanitize => {
interesting_spans.no_sanitize = Some(attr.span());
codegen_fn_attrs.no_sanitize |=
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index 2a9b5c9019b9f..31784cabf4af3 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -1,6 +1,6 @@
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
-use rustc_hir::attrs::InstructionSetAttr;
-use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility};
+use rustc_hir::attrs::{InstructionSetAttr, Linkage};
+use rustc_middle::mir::mono::{MonoItemData, Visibility};
use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt};
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index b9040c330fb10..8f03dc1e6b5e0 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -1,5 +1,6 @@
+use rustc_hir::attrs::Linkage;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
+use rustc_middle::mir::mono::{MonoItem, MonoItemData, Visibility};
use rustc_middle::ty::layout::HasTyCtxt;
use tracing::debug;
diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs
index 9f735546558b0..8d5f0a5b939a2 100644
--- a/compiler/rustc_codegen_ssa/src/traits/declare.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs
@@ -1,5 +1,6 @@
+use rustc_hir::attrs::Linkage;
use rustc_hir::def_id::DefId;
-use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::Instance;
pub trait PreDefineCodegenMethods<'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index b1cc0cc2878aa..64cb934ac8d00 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -731,18 +731,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
) {
let tcx = *self.tcx;
- let trait_def_id = tcx.trait_of_assoc(def_id).unwrap();
+ let trait_def_id = tcx.parent(def_id);
let virtual_trait_ref = ty::TraitRef::from_assoc(tcx, trait_def_id, virtual_instance.args);
let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
- let concrete_method = Instance::expect_resolve_for_vtable(
- tcx,
- self.typing_env,
- def_id,
- virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
- self.cur_span(),
- );
+ let concrete_method = {
+ let _trace = enter_trace_span!(M, resolve::expect_resolve_for_vtable, ?def_id);
+ Instance::expect_resolve_for_vtable(
+ tcx,
+ self.typing_env,
+ def_id,
+ virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
+ self.cur_span(),
+ )
+ };
assert_eq!(concrete_instance, concrete_method);
}
@@ -825,7 +828,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
place
}
};
- let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
+ let instance = {
+ let _trace =
+ enter_trace_span!(M, resolve::resolve_drop_in_place, ty = ?place.layout.ty);
+ ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
+ };
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
let arg = self.mplace_to_ref(&place)?;
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index de4fbc7b4752e..e3afeda5b7c97 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -16,8 +16,8 @@ use super::{
FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok, throw_ub,
throw_ub_custom,
};
-use crate::fluent_generated as fluent;
use crate::interpret::Writeable;
+use crate::{enter_trace_span, fluent_generated as fluent};
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub fn cast(
@@ -81,13 +81,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// The src operand does not matter, just its type
match *src.layout.ty.kind() {
ty::FnDef(def_id, args) => {
- let instance = ty::Instance::resolve_for_fn_ptr(
- *self.tcx,
- self.typing_env,
- def_id,
- args,
- )
- .ok_or_else(|| err_inval!(TooGeneric))?;
+ let instance = {
+ let _trace = enter_trace_span!(M, resolve::resolve_for_fn_ptr, ?def_id);
+ ty::Instance::resolve_for_fn_ptr(
+ *self.tcx,
+ self.typing_env,
+ def_id,
+ args,
+ )
+ .ok_or_else(|| err_inval!(TooGeneric))?
+ };
let fn_ptr = self.fn_ptr(FnVal::Instance(instance));
self.write_pointer(fn_ptr, dest)?;
@@ -114,12 +117,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// The src operand does not matter, just its type
match *src.layout.ty.kind() {
ty::Closure(def_id, args) => {
- let instance = ty::Instance::resolve_closure(
- *self.tcx,
- def_id,
- args,
- ty::ClosureKind::FnOnce,
- );
+ let instance = {
+ let _trace = enter_trace_span!(M, resolve::resolve_closure, ?def_id);
+ ty::Instance::resolve_closure(
+ *self.tcx,
+ def_id,
+ args,
+ ty::ClosureKind::FnOnce,
+ )
+ };
let fn_ptr = self.fn_ptr(FnVal::Instance(instance));
self.write_pointer(fn_ptr, dest)?;
}
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index d4f2bb8257db0..a8a1ac1c9809e 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -344,6 +344,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
def: DefId,
args: GenericArgsRef<'tcx>,
) -> InterpResult<'tcx, ty::Instance<'tcx>> {
+ let _trace = enter_trace_span!(M, resolve::try_resolve, def = ?def);
trace!("resolve: {:?}, {:#?}", def, args);
trace!("typing_env: {:#?}", self.typing_env);
trace!("args: {:#?}", args);
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 76e470b69dce3..f1995b3f132f6 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -560,7 +560,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
"Async Drop must be expanded or reset to sync in runtime MIR"
);
let place = self.eval_place(place)?;
- let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
+ let instance = {
+ let _trace =
+ enter_trace_span!(M, resolve::resolve_drop_in_place, ty = ?place.layout.ty);
+ Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
+ };
if let ty::InstanceKind::DropGlue(_, None) = instance.def {
// This is the branch we enter if and only if the dropped type has no drop glue
// whatsoever. This can happen as a result of monomorphizing a drop of a
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index e02edf5fe24db..510fc83297829 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -187,6 +187,24 @@ pub enum CfgEntry {
Version(Option, Span),
}
+/// Possible values for the `#[linkage]` attribute, allowing to specify the
+/// linkage type for a `MonoItem`.
+///
+/// See for more details about these variants.
+#[derive(Encodable, Decodable, Clone, Copy, Debug, PartialEq, Eq, Hash)]
+#[derive(HashStable_Generic, PrintAttribute)]
+pub enum Linkage {
+ AvailableExternally,
+ Common,
+ ExternalWeak,
+ External,
+ Internal,
+ LinkOnceAny,
+ LinkOnceODR,
+ WeakAny,
+ WeakODR,
+}
+
/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
@@ -360,6 +378,9 @@ pub enum AttributeKind {
/// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
LinkSection { name: Symbol, span: Span },
+ /// Represents `#[linkage]`.
+ Linkage(Linkage, Span),
+
/// Represents `#[loop_match]`.
LoopMatch(Span),
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index 7ce624dcc550a..84a975523f2c8 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -46,6 +46,7 @@ impl AttributeKind {
LinkName { .. } => Yes, // Needed for rustdoc
LinkOrdinal { .. } => No,
LinkSection { .. } => Yes, // Needed for rustdoc
+ Linkage(..) => No,
LoopMatch(..) => No,
MacroEscape(..) => No,
MacroTransparency(..) => Yes,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index e8feb721984d5..0cc03ef7b5b24 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1310,6 +1310,7 @@ impl AttributeExt for Attribute {
Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span,
Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span,
Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span,
+ Attribute::Parsed(AttributeKind::Linkage(_, span)) => *span,
a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 6767e5ed88d4d..e482725619398 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -445,10 +445,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m_def_id: LocalDefId,
) -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> {
- let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
- let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
+ let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());
+ let trait_m = tcx.associated_item(impl_m.trait_item_def_id.unwrap());
let impl_trait_ref =
- tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
+ tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity();
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during instantiation later.
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c642435b9893c..e6a1f6d8d8bb7 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -2287,8 +2287,7 @@ fn lint_redundant_lifetimes<'tcx>(
// Proceed
}
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
- let parent_def_id = tcx.local_parent(owner_id);
- if matches!(tcx.def_kind(parent_def_id), DefKind::Impl { of_trait: true }) {
+ if tcx.trait_impl_of_assoc(owner_id.to_def_id()).is_some() {
// Don't check for redundant lifetimes for associated items of trait
// implementations, since the signature is required to be compatible
// with the trait, even if the implementation implies some lifetimes
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 6013430e1ff3d..aca3840712e79 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2378,6 +2378,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.filter_map(|variant| {
let sole_field = &variant.single_field();
+ // When expected_ty and expr_ty are the same ADT, we prefer to compare their internal generic params,
+ // When the current variant has a sole field whose type is still an unresolved inference variable,
+ // suggestions would be often wrong. So suppress the suggestion. See #145294.
+ if let (ty::Adt(exp_adt, _), ty::Adt(act_adt, _)) = (expected.kind(), expr_ty.kind())
+ && exp_adt.did() == act_adt.did()
+ && sole_field.ty(self.tcx, args).is_ty_var() {
+ return None;
+ }
+
let field_is_local = sole_field.did.is_local();
let field_is_accessible =
sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 4f65acd8001ed..29006732aade5 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -24,10 +24,8 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
match &ty.kind {
TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => {
- if let Some(impl_did) = cx.tcx.impl_of_assoc(ty.hir_id.owner.to_def_id()) {
- if cx.tcx.impl_trait_ref(impl_did).is_some() {
- return;
- }
+ if cx.tcx.trait_impl_of_assoc(ty.hir_id.owner.to_def_id()).is_some() {
+ return;
}
if let Some(t) = path_for_pass_by_value(cx, inner_ty) {
cx.emit_span_lint(
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index b0afc333ebe2f..f8a692313f030 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1904,10 +1904,9 @@ impl InvalidAtomicOrdering {
if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind
&& recognized_names.contains(&method_path.ident.name)
&& let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
- && let Some(impl_did) = cx.tcx.impl_of_assoc(m_def_id)
- && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
// skip extension traits, only lint functions from the standard library
- && cx.tcx.trait_id_of_impl(impl_did).is_none()
+ && let Some(impl_did) = cx.tcx.inherent_impl_of_assoc(m_def_id)
+ && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
&& let parent = cx.tcx.parent(adt.did())
&& cx.tcx.is_diagnostic_item(sym::atomic_mod, parent)
&& ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did()))
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 52341df074085..2852c4cbd34c7 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -2,13 +2,12 @@ use std::borrow::Cow;
use rustc_abi::Align;
use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
-use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::Symbol;
use rustc_target::spec::SanitizerSet;
-use crate::mir::mono::Linkage;
use crate::ty::{InstanceKind, TyCtxt};
impl<'tcx> TyCtxt<'tcx> {
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 785ddd1ee2980..e3e04c9d1800b 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -181,11 +181,7 @@ impl EffectiveVisibilities {
// nominal visibility. For some items nominal visibility doesn't make sense so we
// don't check this condition for them.
let is_impl = matches!(tcx.def_kind(def_id), DefKind::Impl { .. });
- let is_associated_item_in_trait_impl = tcx
- .impl_of_assoc(def_id.to_def_id())
- .and_then(|impl_id| tcx.trait_id_of_impl(impl_id))
- .is_some();
- if !is_impl && !is_associated_item_in_trait_impl {
+ if !is_impl && tcx.trait_impl_of_assoc(def_id.to_def_id()).is_none() {
let nominal_vis = tcx.visibility(def_id);
if !nominal_vis.is_at_least(ev.reachable, tcx) {
span_bug!(
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 0d98e055d9563..440771b3d68a0 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
use rustc_data_structures::unord::UnordMap;
use rustc_hashes::Hash128;
use rustc_hir::ItemId;
-use rustc_hir::attrs::InlineAttr;
+use rustc_hir::attrs::{InlineAttr, Linkage};
use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_query_system::ich::StableHashingContext;
@@ -368,22 +368,6 @@ pub struct MonoItemData {
pub size_estimate: usize,
}
-/// Specifies the linkage type for a `MonoItem`.
-///
-/// See for more details about these variants.
-#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
-pub enum Linkage {
- External,
- AvailableExternally,
- LinkOnceAny,
- LinkOnceODR,
- WeakAny,
- WeakODR,
- Internal,
- ExternalWeak,
- Common,
-}
-
/// Specifies the symbol visibility with regards to dynamic linking.
///
/// Visibility doesn't have any effect when linkage is internal.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 73e1661106eaf..e70c98ab70425 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1925,21 +1925,50 @@ impl<'tcx> TyCtxt<'tcx> {
self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id)
}
- /// If the given `DefId` is an associated item, returns the `DefId` of the parent trait or impl.
- pub fn assoc_parent(self, def_id: DefId) -> Option {
- self.def_kind(def_id).is_assoc().then(|| self.parent(def_id))
+ /// If the given `DefId` is an associated item, returns the `DefId` and `DefKind` of the parent trait or impl.
+ pub fn assoc_parent(self, def_id: DefId) -> Option<(DefId, DefKind)> {
+ if !self.def_kind(def_id).is_assoc() {
+ return None;
+ }
+ let parent = self.parent(def_id);
+ let def_kind = self.def_kind(parent);
+ Some((parent, def_kind))
}
/// If the given `DefId` is an associated item of a trait,
/// returns the `DefId` of the trait; otherwise, returns `None`.
pub fn trait_of_assoc(self, def_id: DefId) -> Option {
- self.assoc_parent(def_id).filter(|id| self.def_kind(id) == DefKind::Trait)
+ match self.assoc_parent(def_id) {
+ Some((id, DefKind::Trait)) => Some(id),
+ _ => None,
+ }
}
/// If the given `DefId` is an associated item of an impl,
/// returns the `DefId` of the impl; otherwise returns `None`.
pub fn impl_of_assoc(self, def_id: DefId) -> Option {
- self.assoc_parent(def_id).filter(|id| matches!(self.def_kind(id), DefKind::Impl { .. }))
+ match self.assoc_parent(def_id) {
+ Some((id, DefKind::Impl { .. })) => Some(id),
+ _ => None,
+ }
+ }
+
+ /// If the given `DefId` is an associated item of an inherent impl,
+ /// returns the `DefId` of the impl; otherwise, returns `None`.
+ pub fn inherent_impl_of_assoc(self, def_id: DefId) -> Option {
+ match self.assoc_parent(def_id) {
+ Some((id, DefKind::Impl { of_trait: false })) => Some(id),
+ _ => None,
+ }
+ }
+
+ /// If the given `DefId` is an associated item of a trait impl,
+ /// returns the `DefId` of the impl; otherwise, returns `None`.
+ pub fn trait_impl_of_assoc(self, def_id: DefId) -> Option {
+ match self.assoc_parent(def_id) {
+ Some((id, DefKind::Impl { of_trait: true })) => Some(id),
+ _ => None,
+ }
}
pub fn is_exportable(self, def_id: DefId) -> bool {
diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs
index 6d61ac2dd8037..a9acb1da5a3e0 100644
--- a/compiler/rustc_mir_transform/src/check_call_recursion.rs
+++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs
@@ -43,8 +43,8 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
// First check if `body` is an `fn drop()` of `Drop`
if let DefKind::AssocFn = tcx.def_kind(def_id)
- && let Some(trait_ref) =
- tcx.impl_of_assoc(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
+ && let Some(impl_id) = tcx.trait_impl_of_assoc(def_id.to_def_id())
+ && let trait_ref = tcx.impl_trait_ref(impl_id).unwrap()
&& tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop)
// avoid erroneous `Drop` impls from causing ICEs below
&& let sig = tcx.fn_sig(def_id).instantiate_identity()
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index dcb812c78993e..100104e9de03e 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -40,7 +40,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place)
{
let def_id = self.body.source.instance.def_id();
- if let Some(impl_def_id) = self.tcx.impl_of_assoc(def_id)
+ if let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(def_id)
&& self.tcx.is_builtin_derived(impl_def_id)
{
// If we ever reach here it means that the generated derive
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index c687036f544dc..c6760b3583f20 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -75,7 +75,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id))
}
ty::InstanceKind::FnPtrShim(def_id, ty) => {
- let trait_ = tcx.trait_of_assoc(def_id).unwrap();
+ let trait_ = tcx.parent(def_id);
// Supports `Fn` or `async Fn` traits.
let adjustment = match tcx
.fn_trait_kind_from_def_id(trait_)
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index d76b27d9970b6..628ea2b63de6b 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -104,7 +104,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::sync;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir::LangItem;
-use rustc_hir::attrs::InlineAttr;
+use rustc_hir::attrs::{InlineAttr, Linkage};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
use rustc_hir::definitions::DefPathDataName;
@@ -112,7 +112,7 @@ use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
use rustc_middle::mir::mono::{
- CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
+ CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, MonoItem, MonoItemData,
MonoItemPartitions, Visibility,
};
use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
@@ -650,17 +650,18 @@ fn characteristic_def_id_of_mono_item<'tcx>(
// its self-type. If the self-type does not provide a characteristic
// DefId, we use the location of the impl after all.
- if tcx.trait_of_assoc(def_id).is_some() {
+ let assoc_parent = tcx.assoc_parent(def_id);
+
+ if let Some((_, DefKind::Trait)) = assoc_parent {
let self_ty = instance.args.type_at(0);
// This is a default implementation of a trait method.
return characteristic_def_id_of_type(self_ty).or(Some(def_id));
}
- if let Some(impl_def_id) = tcx.impl_of_assoc(def_id) {
- if tcx.sess.opts.incremental.is_some()
- && tcx
- .trait_id_of_impl(impl_def_id)
- .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Drop))
+ if let Some((impl_def_id, DefKind::Impl { of_trait })) = assoc_parent {
+ if of_trait
+ && tcx.sess.opts.incremental.is_some()
+ && tcx.is_lang_item(tcx.trait_id_of_impl(impl_def_id).unwrap(), LangItem::Drop)
{
// Put `Drop::drop` into the same cgu as `drop_in_place`
// since `drop_in_place` is the only thing that can
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 165f8fe199519..df1db65c06e01 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -332,6 +332,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => {
self.check_coroutine(attr_span, target)
}
+ &Attribute::Parsed(AttributeKind::Linkage(_, attr_span)) => {
+ self.check_linkage(attr_span, span, target);
+ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
match attr.path().as_slice() {
@@ -395,7 +398,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
self.check_autodiff(hir_id, attr, span, target)
}
- [sym::linkage, ..] => self.check_linkage(attr, span, target),
[
// ok
sym::allow
@@ -2707,7 +2709,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
- fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
+ fn check_linkage(&self, attr_span: Span, span: Span, target: Target) {
match target {
Target::Fn
| Target::Method(..)
@@ -2715,7 +2717,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| Target::ForeignStatic
| Target::ForeignFn => {}
_ => {
- self.dcx().emit_err(errors::Linkage { attr_span: attr.span(), span });
+ self.dcx().emit_err(errors::Linkage { attr_span, span });
}
}
}
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index de52973acbb4a..08d06402000ae 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -371,7 +371,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
/// will be ignored for the purposes of dead code analysis (see PR #85200
/// for discussion).
fn should_ignore_item(&mut self, def_id: DefId) -> bool {
- if let Some(impl_of) = self.tcx.impl_of_assoc(def_id) {
+ if let Some(impl_of) = self.tcx.trait_impl_of_assoc(def_id) {
if !self.tcx.is_automatically_derived(impl_of) {
return false;
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 8526b233ba222..c5fcbdfb42fe7 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1016,16 +1016,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.emit()
}
- /// Lookup typo candidate in scope for a macro or import.
- fn early_lookup_typo_candidate(
+ pub(crate) fn add_scope_set_candidates(
&mut self,
+ suggestions: &mut Vec,
scope_set: ScopeSet<'ra>,
parent_scope: &ParentScope<'ra>,
- ident: Ident,
+ ctxt: SyntaxContext,
filter_fn: &impl Fn(Res) -> bool,
- ) -> Option {
- let mut suggestions = Vec::new();
- let ctxt = ident.span.ctxt();
+ ) {
self.cm().visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
match scope {
Scope::DeriveHelpers(expn_id) => {
@@ -1041,28 +1039,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
Scope::DeriveHelpersCompat => {
- let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
- if filter_fn(res) {
- for derive in parent_scope.derives {
- let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
- let Ok((Some(ext), _)) = this.reborrow().resolve_macro_path(
- derive,
- Some(MacroKind::Derive),
- parent_scope,
- false,
- false,
- None,
- None,
- ) else {
- continue;
- };
- suggestions.extend(
- ext.helper_attrs
- .iter()
- .map(|name| TypoSuggestion::typo_from_name(*name, res)),
- );
- }
- }
+ // Never recommend deprecated helper attributes.
}
Scope::MacroRules(macro_rules_scope) => {
if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() {
@@ -1076,7 +1053,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
Scope::Module(module, _) => {
- this.add_module_candidates(module, &mut suggestions, filter_fn, None);
+ this.add_module_candidates(module, suggestions, filter_fn, None);
}
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(
@@ -1134,6 +1111,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None::<()>
});
+ }
+
+ /// Lookup typo candidate in scope for a macro or import.
+ fn early_lookup_typo_candidate(
+ &mut self,
+ scope_set: ScopeSet<'ra>,
+ parent_scope: &ParentScope<'ra>,
+ ident: Ident,
+ filter_fn: &impl Fn(Res) -> bool,
+ ) -> Option {
+ let mut suggestions = Vec::new();
+ let ctxt = ident.span.ctxt();
+ self.add_scope_set_candidates(&mut suggestions, scope_set, parent_scope, ctxt, filter_fn);
// Make sure error reporting is deterministic.
suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 7ab932d9f2a03..dc01c94af5729 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -459,17 +459,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
Scope::DeriveHelpersCompat => {
- // FIXME: Try running this logic earlier, to allocate name bindings for
- // legacy derive helpers when creating an attribute invocation with
- // following derives. Legacy derive helpers are not common, so it shouldn't
- // affect performance. It should also allow to remove the `derives`
- // component from `ParentScope`.
let mut result = Err(Determinacy::Determined);
for derive in parent_scope.derives {
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
match this.reborrow().resolve_macro_path(
derive,
- Some(MacroKind::Derive),
+ MacroKind::Derive,
parent_scope,
true,
force,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index e52cbeb733ac0..1e4ab57a3160a 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4315,7 +4315,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
qself,
path,
ns,
- path_span,
source.defer_to_typeck(),
finalize,
source,
@@ -4438,7 +4437,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
qself: &Option>,
path: &[Segment],
primary_ns: Namespace,
- span: Span,
defer_to_typeck: bool,
finalize: Finalize,
source: PathSource<'_, 'ast, 'ra>,
@@ -4463,21 +4461,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}
assert!(primary_ns != MacroNS);
-
- if qself.is_none() {
- let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
- let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
- if let Ok((_, res)) = self.r.cm().resolve_macro_path(
- &path,
- None,
- &self.parent_scope,
- false,
- false,
- None,
- None,
- ) {
- return Ok(Some(PartialRes::new(res)));
- }
+ if qself.is_none()
+ && let PathResult::NonModule(res) =
+ self.r.cm().maybe_resolve_path(path, Some(MacroNS), &self.parent_scope, None)
+ {
+ return Ok(Some(res));
}
Ok(fin_res)
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c8cab5a0fe9a1..6a753b380359f 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -38,8 +38,8 @@ use crate::late::{
};
use crate::ty::fast_reject::SimplifiedType;
use crate::{
- Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, errors,
- path_names_to_string,
+ Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, ScopeSet, Segment,
+ errors, path_names_to_string,
};
type Res = def::Res;
@@ -2458,45 +2458,30 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
}
+ if let RibKind::Module(module) = rib.kind
+ && let ModuleKind::Block = module.kind
+ {
+ self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
+ } else if let RibKind::Module(module) = rib.kind {
+ // Encountered a module item, abandon ribs and look into that module and preludes.
+ self.r.add_scope_set_candidates(
+ &mut names,
+ ScopeSet::Late(ns, module, None),
+ &self.parent_scope,
+ ctxt,
+ filter_fn,
+ );
+ break;
+ }
+
if let RibKind::MacroDefinition(def) = rib.kind
&& def == self.r.macro_def(ctxt)
{
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
ctxt.remove_mark();
- continue;
- }
-
- // Items in scope
- if let RibKind::Module(module) = rib.kind {
- // Items from this module
- self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
-
- if let ModuleKind::Block = module.kind {
- // We can see through blocks
- } else {
- // Items from the prelude
- if !module.no_implicit_prelude {
- names.extend(self.r.extern_prelude.keys().flat_map(|ident| {
- let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
- filter_fn(res)
- .then_some(TypoSuggestion::typo_from_ident(ident.0, res))
- }));
-
- if let Some(prelude) = self.r.prelude {
- self.r.add_module_candidates(prelude, &mut names, &filter_fn, None);
- }
- }
- break;
- }
}
}
- // Add primitive types to the mix
- if filter_fn(Res::PrimTy(PrimTy::Bool)) {
- names.extend(PrimTy::ALL.iter().map(|prim_ty| {
- TypoSuggestion::typo_from_name(prim_ty.name(), Res::PrimTy(*prim_ty))
- }))
- }
} else {
// Search in module.
let mod_path = &path[..path.len() - 1];
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 9f25635f1fd1a..72ed899024168 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -398,7 +398,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
resolution.exts = Some(
match self.cm().resolve_macro_path(
&resolution.path,
- Some(MacroKind::Derive),
+ MacroKind::Derive,
&parent_scope,
true,
force,
@@ -563,7 +563,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
) -> Result<(Arc, Res), Indeterminate> {
let (ext, res) = match self.cm().resolve_macro_or_delegation_path(
path,
- Some(kind),
+ kind,
parent_scope,
true,
force,
@@ -710,7 +710,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
pub(crate) fn resolve_macro_path<'r>(
self: CmResolver<'r, 'ra, 'tcx>,
path: &ast::Path,
- kind: Option,
+ kind: MacroKind,
parent_scope: &ParentScope<'ra>,
trace: bool,
force: bool,
@@ -733,7 +733,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn resolve_macro_or_delegation_path<'r>(
mut self: CmResolver<'r, 'ra, 'tcx>,
ast_path: &ast::Path,
- kind: Option,
+ kind: MacroKind,
parent_scope: &ParentScope<'ra>,
trace: bool,
force: bool,
@@ -747,7 +747,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Possibly apply the macro helper hack
if deleg_impl.is_none()
- && kind == Some(MacroKind::Bang)
+ && kind == MacroKind::Bang
&& let [segment] = path.as_slice()
&& segment.ident.span.ctxt().outer_expn_data().local_inner_macros
{
@@ -775,7 +775,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
if trace {
- let kind = kind.expect("macro kind must be specified if tracing is enabled");
// FIXME: Should be an output of Speculative Resolution.
self.multi_segment_macro_resolutions.borrow_mut().push((
path,
@@ -790,10 +789,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
res
} else {
- let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro);
let binding = self.reborrow().early_resolve_ident_in_lexical_scope(
path[0].ident,
- scope_set,
+ ScopeSet::Macro(kind),
parent_scope,
None,
force,
@@ -805,7 +803,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
if trace {
- let kind = kind.expect("macro kind must be specified if tracing is enabled");
// FIXME: Should be an output of Speculative Resolution.
self.single_segment_macro_resolutions.borrow_mut().push((
path[0].ident,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index acbed7a9eed81..416ce27367e5e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -545,6 +545,7 @@ symbols! {
autodiff_forward,
autodiff_reverse,
automatically_derived,
+ available_externally,
avx,
avx10_target_feature,
avx512_target_feature,
@@ -676,6 +677,7 @@ symbols! {
cold_path,
collapse_debuginfo,
column,
+ common,
compare_bytes,
compare_exchange,
compare_exchange_weak,
@@ -956,6 +958,7 @@ symbols! {
extern_prelude,
extern_system_varargs,
extern_types,
+ extern_weak,
external,
external_doc,
f,
@@ -1213,6 +1216,7 @@ symbols! {
instruction_set,
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
integral,
+ internal,
internal_features,
into_async_iter_into_iter,
into_future,
@@ -1287,6 +1291,8 @@ symbols! {
linkage,
linker,
linker_messages,
+ linkonce,
+ linkonce_odr,
lint_reasons,
literal,
load,
@@ -2360,6 +2366,8 @@ symbols! {
wasm_abi,
wasm_import_module,
wasm_target_feature,
+ weak,
+ weak_odr,
where_clause_attrs,
while_let,
width,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 581191b2036d2..884d53732fe2a 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1507,7 +1507,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
let tcx = selcx.tcx();
let self_ty = obligation.predicate.self_ty();
let item_def_id = obligation.predicate.def_id;
- let trait_def_id = tcx.trait_of_assoc(item_def_id).unwrap();
+ let trait_def_id = tcx.parent(item_def_id);
let args = tcx.mk_args(&[self_ty.into()]);
let (term, obligations) = if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) {
let discriminant_def_id =
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 6546dde39ac27..c5f0cb8016e38 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1569,6 +1569,15 @@ impl *const [T] {
}
}
+impl *const T {
+ /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`.
+ #[inline]
+ #[unstable(feature = "ptr_cast_array", issue = "144514")]
+ pub const fn cast_array(self) -> *const [T; N] {
+ self.cast()
+ }
+}
+
impl *const [T; N] {
/// Returns a raw pointer to the array's buffer.
///
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 4add964141ae5..3fe4b08d459e0 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1990,6 +1990,15 @@ impl *mut [T] {
}
}
+impl *mut T {
+ /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`.
+ #[inline]
+ #[unstable(feature = "ptr_cast_array", issue = "144514")]
+ pub const fn cast_array(self) -> *mut [T; N] {
+ self.cast()
+ }
+}
+
impl *mut [T; N] {
/// Returns a raw pointer to the array's buffer.
///
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index da382b8715e96..117eb18826e49 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -193,6 +193,13 @@ impl NonNull {
// requirements for a reference.
unsafe { &mut *self.cast().as_ptr() }
}
+
+ /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`.
+ #[inline]
+ #[unstable(feature = "ptr_cast_array", issue = "144514")]
+ pub const fn cast_array(self) -> NonNull<[T; N]> {
+ self.cast()
+ }
}
impl NonNull {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 64f5b5dd83137..dfbb3628350a8 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -328,7 +328,7 @@ impl [T] {
} else {
// SAFETY: We explicitly check for the correct number of elements,
// and do not let the reference outlive the slice.
- Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) })
+ Some(unsafe { &*(self.as_ptr().cast_array()) })
}
}
@@ -359,7 +359,7 @@ impl [T] {
// SAFETY: We explicitly check for the correct number of elements,
// do not let the reference outlive the slice,
// and require exclusive access to the entire slice to mutate the chunk.
- Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) })
+ Some(unsafe { &mut *(self.as_mut_ptr().cast_array()) })
}
}
@@ -387,7 +387,7 @@ impl [T] {
// SAFETY: We explicitly check for the correct number of elements,
// and do not let the references outlive the slice.
- Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail))
+ Some((unsafe { &*(first.as_ptr().cast_array()) }, tail))
}
/// Returns a mutable array reference to the first `N` items in the slice and the remaining
@@ -420,7 +420,7 @@ impl [T] {
// SAFETY: We explicitly check for the correct number of elements,
// do not let the reference outlive the slice,
// and enforce exclusive mutability of the chunk by the split.
- Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail))
+ Some((unsafe { &mut *(first.as_mut_ptr().cast_array()) }, tail))
}
/// Returns an array reference to the last `N` items in the slice and the remaining slice.
@@ -448,7 +448,7 @@ impl [T] {
// SAFETY: We explicitly check for the correct number of elements,
// and do not let the references outlive the slice.
- Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) }))
+ Some((init, unsafe { &*(last.as_ptr().cast_array()) }))
}
/// Returns a mutable array reference to the last `N` items in the slice and the remaining
@@ -482,7 +482,7 @@ impl [T] {
// SAFETY: We explicitly check for the correct number of elements,
// do not let the reference outlive the slice,
// and enforce exclusive mutability of the chunk by the split.
- Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }))
+ Some((init, unsafe { &mut *(last.as_mut_ptr().cast_array()) }))
}
/// Returns an array reference to the last `N` items in the slice.
@@ -511,7 +511,7 @@ impl [T] {
// SAFETY: We explicitly check for the correct number of elements,
// and do not let the references outlive the slice.
- Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) })
+ Some(unsafe { &*(last.as_ptr().cast_array()) })
}
/// Returns a mutable array reference to the last `N` items in the slice.
@@ -542,7 +542,7 @@ impl [T] {
// SAFETY: We explicitly check for the correct number of elements,
// do not let the reference outlive the slice,
// and require exclusive access to the entire slice to mutate the chunk.
- Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })
+ Some(unsafe { &mut *(last.as_mut_ptr().cast_array()) })
}
/// Returns a reference to an element or subslice depending on the type of
@@ -846,7 +846,7 @@ impl [T] {
#[must_use]
pub const fn as_array(&self) -> Option<&[T; N]> {
if self.len() == N {
- let ptr = self.as_ptr() as *const [T; N];
+ let ptr = self.as_ptr().cast_array();
// SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length.
let me = unsafe { &*ptr };
@@ -864,7 +864,7 @@ impl [T] {
#[must_use]
pub const fn as_mut_array(&mut self) -> Option<&mut [T; N]> {
if self.len() == N {
- let ptr = self.as_mut_ptr() as *mut [T; N];
+ let ptr = self.as_mut_ptr().cast_array();
// SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length.
let me = unsafe { &mut *ptr };
diff --git a/library/coretests/tests/io/borrowed_buf.rs b/library/coretests/tests/io/borrowed_buf.rs
index 4074148436cf6..aaa98d26ff8b9 100644
--- a/library/coretests/tests/io/borrowed_buf.rs
+++ b/library/coretests/tests/io/borrowed_buf.rs
@@ -66,7 +66,7 @@ fn clear() {
#[test]
fn set_init() {
- let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16];
+ let buf: &mut [_] = &mut [MaybeUninit::zeroed(); 16];
let mut rbuf: BorrowedBuf<'_> = buf.into();
unsafe {
@@ -134,7 +134,7 @@ fn reborrow_written() {
#[test]
fn cursor_set_init() {
- let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16];
+ let buf: &mut [_] = &mut [MaybeUninit::zeroed(); 16];
let mut rbuf: BorrowedBuf<'_> = buf.into();
unsafe {
diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs
index 41d1dd3ce674b..03d7fddc2faef 100644
--- a/library/std/src/sync/mpsc.rs
+++ b/library/std/src/sync/mpsc.rs
@@ -697,14 +697,14 @@ impl SyncSender {
/// let sync_sender2 = sync_sender.clone();
///
/// // First thread owns sync_sender
- /// thread::spawn(move || {
+ /// let handle1 = thread::spawn(move || {
/// sync_sender.send(1).unwrap();
/// sync_sender.send(2).unwrap();
/// // Thread blocked
/// });
///
/// // Second thread owns sync_sender2
- /// thread::spawn(move || {
+ /// let handle2 = thread::spawn(move || {
/// // This will return an error and send
/// // no message if the buffer is full
/// let _ = sync_sender2.try_send(3);
@@ -722,6 +722,10 @@ impl SyncSender {
/// Ok(msg) => println!("message {msg} received"),
/// Err(_) => println!("the third message was never sent"),
/// }
+ ///
+ /// // Wait for threads to complete
+ /// handle1.join().unwrap();
+ /// handle2.join().unwrap();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_send(&self, t: T) -> Result<(), TrySendError> {
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index cce88d936b71b..24b6cff130974 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -51,17 +51,16 @@ pub trait FromInner {
fn from_inner(inner: Inner) -> Self;
}
-// Computes (value*numer)/denom without overflow, as long as both
-// (numer*denom) and the overall result fit into i64 (which is the case
-// for our time conversions).
+// Computes (value*numerator)/denom without overflow, as long as both (numerator*denom) and the
+// overall result fit into i64 (which is the case for our time conversions).
#[allow(dead_code)] // not used on all platforms
-pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 {
+pub fn mul_div_u64(value: u64, numerator: u64, denom: u64) -> u64 {
let q = value / denom;
let r = value % denom;
// Decompose value as (value/denom*denom + value%denom),
- // substitute into (value*numer)/denom and simplify.
- // r < denom, so (denom*numer) is the upper bound of (r*numer)
- q * numer + r * numer / denom
+ // substitute into (value*numerator)/denom and simplify.
+ // r < denom, so (denom*numerator) is the upper bound of (r*numerator)
+ q * numerator + r * numerator / denom
}
pub fn ignore_notfound(result: crate::io::Result) -> crate::io::Result<()> {
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index b942e4bfa61eb..b53494ed98d4a 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -23,6 +23,7 @@
- [Linker-plugin-based LTO](linker-plugin-lto.md)
- [Checking Conditional Configurations](check-cfg.md)
- [Cargo Specifics](check-cfg/cargo-specifics.md)
+- [Remap source paths](remap-source-paths.md)
- [Exploit Mitigations](exploit-mitigations.md)
- [Symbol Mangling](symbol-mangling/index.md)
- [v0 Symbol Format](symbol-mangling/v0.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index d45ad1be27b8c..0b15fbc24dfc2 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -418,22 +418,15 @@ This flag takes a number that specifies the width of the terminal in characters.
Formatting of diagnostics will take the width into consideration to make them better fit on the screen.
-## `--remap-path-prefix`: remap source names in output
+## `--remap-path-prefix`: remap source paths in output
Remap source path prefixes in all output, including compiler diagnostics,
-debug information, macro expansions, etc. It takes a value of the form
-`FROM=TO` where a path prefix equal to `FROM` is rewritten to the value `TO`.
-The `FROM` may itself contain an `=` symbol, but the `TO` value may not. This
-flag may be specified multiple times.
-
-This is useful for normalizing build products, for example by removing the
-current directory out of pathnames emitted into the object files. The
-replacement is purely textual, with no consideration of the current system's
-pathname syntax. For example `--remap-path-prefix foo=bar` will match
-`foo/lib.rs` but not `./foo/lib.rs`.
-
-When multiple remappings are given and several of them match, the **last**
-matching one is applied.
+debug information, macro expansions, etc. It takes a value of the form `FROM=TO`
+where a path prefix equal to `FROM` is rewritten to the value `TO`. This flag may be
+specified multiple times.
+
+Refer to the [Remap source paths](remap-source-paths.md) section of this book for
+further details and explanation.
## `--json`: configure json messages printed by the compiler
diff --git a/src/doc/rustc/src/remap-source-paths.md b/src/doc/rustc/src/remap-source-paths.md
new file mode 100644
index 0000000000000..03f5d98091cc6
--- /dev/null
+++ b/src/doc/rustc/src/remap-source-paths.md
@@ -0,0 +1,53 @@
+# Remap source paths
+
+`rustc` supports remapping source paths prefixes **as a best effort** in all compiler generated
+output, including compiler diagnostics, debugging information, macro expansions, etc.
+
+This is useful for normalizing build products, for example by removing the current directory
+out of the paths emitted into object files.
+
+The remapping is done via the `--remap-path-prefix` option.
+
+## `--remap-path-prefix`
+
+It takes a value of the form `FROM=TO` where a path prefix equal to `FROM` is rewritten
+to the value `TO`. `FROM` may itself contain an `=` symbol, but `TO` value may not.
+
+The replacement is purely textual, with no consideration of the current system's path separator.
+
+When multiple remappings are given and several of them match, the **last** matching one is applied.
+
+### Example
+
+```bash
+rustc --remap-path-prefix "/home/user/project=/redacted"
+```
+
+This example replaces all occurrences of `/home/user/project` in emitted paths with `/redacted`.
+
+## Caveats and Limitations
+
+### Linkers generated paths
+
+On some platforms like `x86_64-pc-windows-msvc`, the linker may embed absolute host paths and compiler
+arguments into debug info files (like `.pdb`) independently of `rustc`.
+
+Additionally, on Apple platforms, linkers generate [OSO entries] which are not remapped by the compiler
+and need to be manually remapped with `-oso_prefix`.
+
+The `--remap-path-prefix` option does not affect these linker-generated paths.
+
+### Textual replacement only
+
+The remapping is strictly textual and does not account for different path separator conventions across
+platforms. Care must be taken when specifying prefixes, especially on Windows where both `/` and `\` may
+appear in paths.
+
+### External tools
+
+Paths introduced by external tools or environment variables may not be covered by `--remap-path-prefix`
+unless explicitly accounted for.
+
+For example, generated code introduced by Cargo's build script may still contain un-remapped paths.
+
+[OSO entries]: https://wiki.dwarfstd.org/Apple%27s_%22Lazy%22_DWARF_Scheme.md
diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs
index 7ee012c4da239..a81d8dd6035e0 100644
--- a/src/librustdoc/html/markdown/footnotes.rs
+++ b/src/librustdoc/html/markdown/footnotes.rs
@@ -23,6 +23,8 @@ struct FootnoteDef<'a> {
content: Vec>,
/// The number that appears in the footnote reference and list.
id: usize,
+ /// The number of footnote references.
+ num_refs: usize,
}
impl<'a, I: Iterator>> Footnotes<'a, I> {
@@ -33,21 +35,25 @@ impl<'a, I: Iterator>> Footnotes<'a, I> {
Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes, start_id }
}
- fn get_entry(&mut self, key: &str) -> (&mut Vec>, usize) {
+ fn get_entry(&mut self, key: &str) -> (&mut Vec>, usize, &mut usize) {
let new_id = self.footnotes.len() + 1 + self.start_id;
let key = key.to_owned();
- let FootnoteDef { content, id } =
- self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id });
+ let FootnoteDef { content, id, num_refs } = self
+ .footnotes
+ .entry(key)
+ .or_insert(FootnoteDef { content: Vec::new(), id: new_id, num_refs: 0 });
// Don't allow changing the ID of existing entries, but allow changing the contents.
- (content, *id)
+ (content, *id, num_refs)
}
fn handle_footnote_reference(&mut self, reference: &CowStr<'a>) -> Event<'a> {
// When we see a reference (to a footnote we may not know) the definition of,
// reserve a number for it, and emit a link to that number.
- let (_, id) = self.get_entry(reference);
+ let (_, id, num_refs) = self.get_entry(reference);
+ *num_refs += 1;
+ let fnref_suffix = if *num_refs <= 1 { "".to_owned() } else { format!("-{num_refs}") };
let reference = format!(
- "{1}",
+ "{1}",
id,
// Although the ID count is for the whole page, the footnote reference
// are local to the item so we make this ID "local" when displayed.
@@ -85,7 +91,7 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> {
// When we see a footnote definition, collect the associated content, and store
// that for rendering later.
let content = self.collect_footnote_def();
- let (entry_content, _) = self.get_entry(&def);
+ let (entry_content, _, _) = self.get_entry(&def);
*entry_content = content;
}
Some(e) => return Some(e),
@@ -113,7 +119,7 @@ fn render_footnotes_defs(mut footnotes: Vec>) -> String {
// browser generated for
are right.
footnotes.sort_by_key(|x| x.id);
- for FootnoteDef { mut content, id } in footnotes {
+ for FootnoteDef { mut content, id, num_refs } in footnotes {
write!(ret, "
").unwrap();
let mut is_paragraph = false;
if let Some(&Event::End(TagEnd::Paragraph)) = content.last() {
@@ -121,7 +127,16 @@ fn render_footnotes_defs(mut footnotes: Vec>) -> String {
is_paragraph = true;
}
html::push_html(&mut ret, content.into_iter());
- write!(ret, " ↩").unwrap();
+ if num_refs <= 1 {
+ write!(ret, " ↩").unwrap();
+ } else {
+ // There are multiple references to single footnote. Make the first
+ // back link a single "a" element to make touch region larger.
+ write!(ret, " ↩ 1").unwrap();
+ for refid in 2..=num_refs {
+ write!(ret, " {refid}").unwrap();
+ }
+ }
if is_paragraph {
ret.push_str("
");
}
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index a8e2151afe610..1b5d9d50996c7 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -32,6 +32,8 @@ pub enum AccessKind {
///
/// A `None` namespace indicates we are looking for a module.
fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option) -> Option {
+ let _trace = enter_trace_span!("try_resolve_did", ?path);
+
/// Yield all children of the given item, that have the given name.
fn find_children<'tcx: 'a, 'a>(
tcx: TyCtxt<'tcx>,
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index b5b35797fec2f..6e56fdfe35aef 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -322,8 +322,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Since our emulated ticks in `mach_absolute_time` *are* nanoseconds,
// no scaling needs to happen.
- let (numer, denom) = (1, 1);
- this.write_int_fields(&[numer.into(), denom.into()], &info)?;
+ let (numerator, denom) = (1, 1);
+ this.write_int_fields(&[numerator.into(), denom.into()], &info)?;
interp_ok(Scalar::from_i32(0)) // KERN_SUCCESS
}
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index e9e0efc459442..03ed9499e26c5 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -341,7 +341,7 @@ impl Canonicalized {
for &w in unique_words {
unique_mapping.entry(w).or_insert_with(|| {
canonical_words.push(w);
- UniqueMapping::Canonical(canonical_words.len())
+ UniqueMapping::Canonical(canonical_words.len() - 1)
});
}
assert_eq!(canonicalized_words.len() + canonical_words.len(), unique_words.len());
diff --git a/tests/rustdoc/footnote-reference-ids.rs b/tests/rustdoc/footnote-reference-ids.rs
new file mode 100644
index 0000000000000..ffa04e1d7675d
--- /dev/null
+++ b/tests/rustdoc/footnote-reference-ids.rs
@@ -0,0 +1,23 @@
+// This test ensures that multiple references to a single footnote and
+// corresponding back links work as expected.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ has - '//*[@class="docblock"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1'
+//@ has - '//*[@class="docblock"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2'
+//@ has - '//*[@class="docblock"]/p/sup[@id="fnref2-2"]/a[@href="#fn2"]' '2'
+//@ has - '//li[@id="fn1"]/p' 'meow'
+//@ has - '//li[@id="fn1"]/p/a[@href="#fnref1"]' '↩'
+//@ has - '//li[@id="fn2"]/p' 'uwu'
+//@ has - '//li[@id="fn2"]/p/a[@href="#fnref2"]/sup' '1'
+//@ has - '//li[@id="fn2"]/p/sup/a[@href="#fnref2-2"]' '2'
+
+//! # Footnote, references and back links
+//!
+//! Single: [^a].
+//!
+//! Double: [^b] [^b].
+//!
+//! [^a]: meow
+//! [^b]: uwu
diff --git a/tests/rustdoc/footnote-reference-in-footnote-def.rs b/tests/rustdoc/footnote-reference-in-footnote-def.rs
index db3f9a59ef830..504d0bdb8f79f 100644
--- a/tests/rustdoc/footnote-reference-in-footnote-def.rs
+++ b/tests/rustdoc/footnote-reference-in-footnote-def.rs
@@ -9,7 +9,7 @@
//@ has - '//li[@id="fn1"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2'
//@ has - '//li[@id="fn1"]//a[@href="#fn2"]' '2'
//@ has - '//li[@id="fn2"]/p' 'uwu'
-//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1'
+//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1-2"]/a[@href="#fn1"]' '1'
//@ has - '//li[@id="fn2"]//a[@href="#fn1"]' '1'
//! # footnote-hell
diff --git a/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs b/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs
new file mode 100644
index 0000000000000..128af50ce3691
--- /dev/null
+++ b/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs
@@ -0,0 +1,8 @@
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive, attributes(arg))]
+pub fn derive(_: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
diff --git a/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs b/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs
new file mode 100644
index 0000000000000..17c9ad1bd48e6
--- /dev/null
+++ b/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs
@@ -0,0 +1,20 @@
+// Regression test for .
+//@ proc-macro: derive_macro_with_helper.rs
+//@ edition: 2018
+//@ check-pass
+
+macro_rules! expand {
+ ($text:expr) => {
+ #[derive(derive_macro_with_helper::Derive)]
+ // This inert attr is completely valid because it follows the grammar
+ // `#` `[` SimplePath DelimitedTokenStream `]`.
+ // However, we used to incorrectly delay a bug here and ICE when trying to parse `$text` as
+ // the inside of a "meta item list" which may only begin with literals or paths.
+ #[arg($text)]
+ pub struct Foo;
+ };
+}
+
+expand!(1 + 1);
+
+fn main() {}
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 705050e9a7deb..aa4891459aaf2 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -90,25 +90,6 @@ error: malformed `cfi_encoding` attribute input
LL | #[cfi_encoding]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
-error: malformed `linkage` attribute input
- --> $DIR/malformed-attrs.rs:170:5
- |
-LL | #[linkage]
- | ^^^^^^^^^^
- |
- = note: for more information, visit
-help: the following are the possible correct uses
- |
-LL | #[linkage = "available_externally"]
- | ++++++++++++++++++++++++
-LL | #[linkage = "common"]
- | ++++++++++
-LL | #[linkage = "extern_weak"]
- | +++++++++++++++
-LL | #[linkage = "external"]
- | ++++++++++++
- = and 5 other candidates
-
error: malformed `allow` attribute input
--> $DIR/malformed-attrs.rs:175:1
|
@@ -659,6 +640,24 @@ LL | #[unsafe(ffi_const = 1)]
| | didn't expect any arguments here
| help: must be of the form: `#[ffi_const]`
+error[E0539]: malformed `linkage` attribute input
+ --> $DIR/malformed-attrs.rs:170:5
+ |
+LL | #[linkage]
+ | ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
+ |
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL | #[linkage = "available_externally"]
+ | ++++++++++++++++++++++++
+LL | #[linkage = "common"]
+ | ++++++++++
+LL | #[linkage = "extern_weak"]
+ | +++++++++++++++
+LL | #[linkage = "external"]
+ | ++++++++++++
+ = and 5 other candidates
+
error[E0565]: malformed `automatically_derived` attribute input
--> $DIR/malformed-attrs.rs:188:1
|
diff --git a/tests/ui/hygiene/arguments.stderr b/tests/ui/hygiene/arguments.stderr
index 0d8d652b6f33d..fe92daf643796 100644
--- a/tests/ui/hygiene/arguments.stderr
+++ b/tests/ui/hygiene/arguments.stderr
@@ -1,6 +1,9 @@
error[E0412]: cannot find type `S` in this scope
--> $DIR/arguments.rs:14:8
|
+LL | struct S;
+ | - you might have meant to refer to this struct
+...
LL | m!(S, S);
| ^ not found in this scope
diff --git a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
index a5d509fab996f..fe3a12e93a7e7 100644
--- a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
+++ b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
@@ -3,6 +3,11 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope
|
LL | let x = MyStruct {};
| ^^^^^^^^ not found in this scope
+ |
+ ::: $DIR/auxiliary/use_by_macro.rs:15:1
+ |
+LL | x!(my_struct);
+ | ------------- you might have meant to refer to this struct
error: aborting due to 1 previous error
diff --git a/tests/ui/hygiene/globs.stderr b/tests/ui/hygiene/globs.stderr
index 31f25b182f1f5..85946bf34bc53 100644
--- a/tests/ui/hygiene/globs.stderr
+++ b/tests/ui/hygiene/globs.stderr
@@ -48,7 +48,10 @@ error[E0425]: cannot find function `f` in this scope
--> $DIR/globs.rs:61:12
|
LL | n!(f);
- | ----- in this macro invocation
+ | -----
+ | | |
+ | | you might have meant to refer to this function
+ | in this macro invocation
...
LL | $j();
| -- due to this macro variable
@@ -56,15 +59,16 @@ LL | $j();
LL | n!(f);
| ^ not found in this scope
|
- = help: consider importing this function:
- foo::f
= note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find function `f` in this scope
--> $DIR/globs.rs:65:17
|
LL | n!(f);
- | ----- in this macro invocation
+ | -----
+ | | |
+ | | you might have meant to refer to this function
+ | in this macro invocation
...
LL | $j();
| -- due to this macro variable
@@ -72,8 +76,6 @@ LL | $j();
LL | f
| ^ not found in this scope
|
- = help: consider importing this function:
- foo::f
= note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors
diff --git a/tests/ui/linkage-attr/linkage3.rs b/tests/ui/linkage-attr/linkage3.rs
index f95e5eecc48f7..74a6fd6600b8e 100644
--- a/tests/ui/linkage-attr/linkage3.rs
+++ b/tests/ui/linkage-attr/linkage3.rs
@@ -5,7 +5,7 @@
extern "C" {
#[linkage = "foo"]
static foo: *const i32;
-//~^ ERROR: invalid linkage specified
+//~^^ ERROR: malformed `linkage` attribute input [E0539]
}
fn main() {
diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr
index 5f7b7ef227c84..f1215f09aeafc 100644
--- a/tests/ui/linkage-attr/linkage3.stderr
+++ b/tests/ui/linkage-attr/linkage3.stderr
@@ -1,8 +1,27 @@
-error: invalid linkage specified
- --> $DIR/linkage3.rs:7:5
+error[E0539]: malformed `linkage` attribute input
+ --> $DIR/linkage3.rs:6:5
|
-LL | static foo: *const i32;
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | #[linkage = "foo"]
+ | ^^^^^^^^^^^^-----^
+ | |
+ | valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `internal`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr`
+ |
+help: try changing it to one of the following valid forms of the attribute
+ |
+LL - #[linkage = "foo"]
+LL + #[linkage = "available_externally"]
+ |
+LL - #[linkage = "foo"]
+LL + #[linkage = "common"]
+ |
+LL - #[linkage = "foo"]
+LL + #[linkage = "extern_weak"]
+ |
+LL - #[linkage = "foo"]
+LL + #[linkage = "external"]
+ |
+ = and 5 other candidates
error: aborting due to 1 previous error
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/proc-macro/proc-macro-attributes.stderr b/tests/ui/proc-macro/proc-macro-attributes.stderr
index 2cc57383eb39c..892728901fb99 100644
--- a/tests/ui/proc-macro/proc-macro-attributes.stderr
+++ b/tests/ui/proc-macro/proc-macro-attributes.stderr
@@ -2,7 +2,13 @@ error: cannot find attribute `C` in this scope
--> $DIR/proc-macro-attributes.rs:9:3
|
LL | #[C]
- | ^ help: a derive helper attribute with a similar name exists: `B`
+ | ^
+ |
+help: the derive macro `B` accepts the similarly named `B` attribute
+ |
+LL - #[C]
+LL + #[B]
+ |
error[E0659]: `B` is ambiguous
--> $DIR/proc-macro-attributes.rs:6:3
diff --git a/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs
new file mode 100644
index 0000000000000..cfe167cf88d76
--- /dev/null
+++ b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs
@@ -0,0 +1,26 @@
+// Suppress the suggestion that adding a wrapper.
+// When expected_ty and expr_ty are the same ADT,
+// we prefer to compare their internal generic params,
+// so when the current variant corresponds to an unresolved infer,
+// the suggestion is rejected.
+// e.g. `Ok(Some("hi"))` is type of `Result