Skip to content

Commit 5953e50

Browse files
committed
Auto merge of #152568 - JonathanBrouwer:port_lang, r=<try>
Port `#[lang]` and `#[panic_handler]` to the new attribute parsers
2 parents d7daac0 + e697bc0 commit 5953e50

File tree

17 files changed

+143
-86
lines changed

17 files changed

+143
-86
lines changed

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::path::PathBuf;
22

33
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
4+
use rustc_hir::LangItem;
45
use rustc_hir::attrs::{
56
BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior,
67
DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcLayoutType,
@@ -12,7 +13,7 @@ use rustc_span::Symbol;
1213
use super::prelude::*;
1314
use super::util::parse_single_integer;
1415
use crate::session_diagnostics::{
15-
AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange,
16+
AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, UnknownLangItem,
1617
};
1718

1819
pub(crate) struct RustcMainParser;
@@ -626,6 +627,32 @@ impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
626627
}
627628
}
628629

630+
pub(crate) struct LangParser;
631+
632+
impl<S: Stage> SingleAttributeParser<S> for LangParser {
633+
const PATH: &[Symbol] = &[sym::lang];
634+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
635+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
636+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes`
637+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
638+
639+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
640+
let Some(nv) = args.name_value() else {
641+
cx.expected_name_value(cx.attr_span, None);
642+
return None;
643+
};
644+
let Some(name) = nv.value_as_str() else {
645+
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
646+
return None;
647+
};
648+
let Some(lang_item) = LangItem::from_name(name) else {
649+
cx.emit_err(UnknownLangItem { span: cx.attr_span, name });
650+
return None;
651+
};
652+
Some(AttributeKind::Lang(lang_item, cx.attr_span))
653+
}
654+
}
655+
629656
pub(crate) struct RustcHasIncoherentInherentImplsParser;
630657

631658
impl<S: Stage> NoArgsAttributeParser<S> for RustcHasIncoherentInherentImplsParser {
@@ -641,6 +668,15 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcHasIncoherentInherentImplsParse
641668
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;
642669
}
643670

671+
pub(crate) struct PanicHandlerParser;
672+
673+
impl<S: Stage> NoArgsAttributeParser<S> for PanicHandlerParser {
674+
const PATH: &[Symbol] = &[sym::panic_handler];
675+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
676+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes`
677+
const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::Lang(LangItem::PanicImpl, span);
678+
}
679+
644680
pub(crate) struct RustcHiddenTypeOfOpaquesParser;
645681

646682
impl<S: Stage> NoArgsAttributeParser<S> for RustcHiddenTypeOfOpaquesParser {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ attribute_parsers!(
181181
Single<IgnoreParser>,
182182
Single<InlineParser>,
183183
Single<InstructionSetParser>,
184+
Single<LangParser>,
184185
Single<LinkNameParser>,
185186
Single<LinkOrdinalParser>,
186187
Single<LinkSectionParser>,
@@ -253,6 +254,7 @@ attribute_parsers!(
253254
Single<WithoutArgs<NoMangleParser>>,
254255
Single<WithoutArgs<NoStdParser>>,
255256
Single<WithoutArgs<NonExhaustiveParser>>,
257+
Single<WithoutArgs<PanicHandlerParser>>,
256258
Single<WithoutArgs<PanicRuntimeParser>>,
257259
Single<WithoutArgs<ParenSugarParser>>,
258260
Single<WithoutArgs<PassByValueParser>>,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,15 @@ pub(crate) struct DocAliasMalformed {
10131013
pub span: Span,
10141014
}
10151015

1016+
#[derive(Diagnostic)]
1017+
#[diag("definition of an unknown lang item: `{$name}`", code = E0522)]
1018+
pub(crate) struct UnknownLangItem {
1019+
#[primary_span]
1020+
#[label("definition of unknown lang item `{$name}`")]
1021+
pub span: Span,
1022+
pub name: Symbol,
1023+
}
1024+
10161025
#[derive(Diagnostic)]
10171026
#[diag("target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`")]
10181027
pub(crate) struct UnsupportedInstructionSet<'a> {

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_hir::attrs::{
88
};
99
use rustc_hir::def::DefKind;
1010
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
11-
use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
11+
use rustc_hir::{self as hir, Attribute, find_attr};
1212
use rustc_middle::middle::codegen_fn_attrs::{
1313
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs,
1414
};
@@ -504,7 +504,7 @@ fn handle_lang_items(
504504
attrs: &[Attribute],
505505
codegen_fn_attrs: &mut CodegenFnAttrs,
506506
) {
507-
let lang_item = lang_items::extract(attrs).and_then(|(name, _)| LangItem::from_name(name));
507+
let lang_item = find_attr!(attrs, AttributeKind::Lang(lang, _) => lang);
508508

509509
// Weak lang items have the same semantics as "std internal" symbols in the
510510
// sense that they're preserved through all our LTO passes and only

compiler/rustc_error_codes/src/error_codes/E0264.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ Erroneous code example:
77
#![allow(internal_features)]
88
99
extern "C" {
10-
#[lang = "cake"] // error: unknown external lang item: `cake`
11-
fn cake();
10+
#[lang = "copy"] // error: unknown external lang item: `copy`
11+
fn copy();
1212
}
1313
```
1414

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_ast::token::DocFragmentKind;
88
use rustc_ast::{AttrStyle, Path, ast};
99
use rustc_data_structures::fx::FxIndexMap;
1010
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
11+
use rustc_hir::LangItem;
1112
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
1213
use rustc_span::def_id::DefId;
1314
use rustc_span::hygiene::Transparency;
@@ -953,6 +954,9 @@ pub enum AttributeKind {
953954
/// Represents `#[instruction_set]`
954955
InstructionSet(InstructionSetAttr),
955956

957+
/// Represents `#[lang]`
958+
Lang(LangItem, Span),
959+
956960
/// Represents `#[link]`.
957961
Link(ThinVec<LinkEntry>, Span),
958962

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl AttributeKind {
5050
Ignore { .. } => No,
5151
Inline(..) => No,
5252
InstructionSet(..) => No,
53+
Lang(..) => Yes,
5354
Link(..) => No,
5455
LinkName { .. } => Yes, // Needed for rustdoc
5556
LinkOrdinal { .. } => No,

compiler/rustc_hir/src/lang_items.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
88
//! * Functions called by the compiler itself.
99
10-
use rustc_ast::attr::AttributeExt;
1110
use rustc_data_structures::fx::FxIndexMap;
1211
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
13-
use rustc_macros::{BlobDecodable, Encodable, HashStable_Generic};
14-
use rustc_span::{Span, Symbol, kw, sym};
12+
use rustc_macros::{BlobDecodable, Encodable, HashStable_Generic, PrintAttribute};
13+
use rustc_span::{Symbol, kw, sym};
1514

15+
use crate::attrs::PrintAttribute;
1616
use crate::def_id::DefId;
1717
use crate::{MethodKind, Target};
1818

@@ -75,7 +75,7 @@ macro_rules! language_item_table {
7575
$( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
7676
) => {
7777
/// A representation of all the valid lang items in Rust.
78-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, BlobDecodable)]
78+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, BlobDecodable, PrintAttribute)]
7979
pub enum LangItem {
8080
$(
8181
#[doc = concat!("The `", stringify!($name), "` lang item.")]
@@ -150,18 +150,6 @@ impl<CTX> HashStable<CTX> for LangItem {
150150
}
151151
}
152152

153-
/// Extracts the first `lang = "$name"` out of a list of attributes.
154-
/// The `#[panic_handler]` attribute is also extracted out when found.
155-
pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
156-
attrs.iter().find_map(|attr| {
157-
Some(match attr {
158-
_ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span()),
159-
_ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span()),
160-
_ => return None,
161-
})
162-
})
163-
}
164-
165153
language_item_table! {
166154
// Variant name, Name, Getter method name, Target Generic requirements;
167155
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);

compiler/rustc_passes/src/check_attr.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
256256
| AttributeKind::Fundamental
257257
| AttributeKind::Ignore { .. }
258258
| AttributeKind::InstructionSet(..)
259+
| AttributeKind::Lang(..)
259260
| AttributeKind::LinkName { .. }
260261
| AttributeKind::LinkOrdinal { .. }
261262
| AttributeKind::LinkSection { .. }
@@ -395,8 +396,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
395396
// need to be fixed
396397
| sym::deprecated_safe // FIXME(deprecated_safe)
397398
// internal
398-
| sym::panic_handler
399-
| sym::lang
400399
| sym::default_lib_allocator
401400
| sym::rustc_diagnostic_item
402401
| sym::rustc_nonnull_optimization_guaranteed
@@ -786,15 +785,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
786785
Target::Fn => {
787786
// `#[track_caller]` is not valid on weak lang items because they are called via
788787
// `extern` declarations and `#[track_caller]` would alter their ABI.
789-
if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
790-
&& let Some(item) = hir::LangItem::from_name(lang_item)
788+
if let Some(item) = find_attr!(attrs, AttributeKind::Lang(item, _) => item)
791789
&& item.is_weak()
792790
{
793791
let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
794792

795793
self.dcx().emit_err(errors::LangItemWithTrackCaller {
796794
attr_span,
797-
name: lang_item,
795+
name: item.name(),
798796
sig_span: sig.span,
799797
});
800798
}
@@ -858,7 +856,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
858856
Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
859857
| Target::Fn => {
860858
// `#[target_feature]` is not allowed in lang items.
861-
if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
859+
if let Some(lang_item) = find_attr!(attrs, AttributeKind::Lang(lang, _) => lang)
862860
// Calling functions with `#[target_feature]` is
863861
// not unsafe on WASM, see #84988
864862
&& !self.tcx.sess.target.is_like_wasm
@@ -868,7 +866,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
868866

869867
self.dcx().emit_err(errors::LangItemWithTargetFeature {
870868
attr_span,
871-
name: lang_item,
869+
name: lang_item.name(),
872870
sig_span: sig.span,
873871
});
874872
}

compiler/rustc_passes/src/dead.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_middle::ty::{self, AssocTag, TyCtxt};
2222
use rustc_middle::{bug, span_bug};
2323
use rustc_session::lint::builtin::DEAD_CODE;
2424
use rustc_session::lint::{self, LintExpectationId};
25-
use rustc_span::{Symbol, kw, sym};
25+
use rustc_span::{Symbol, kw};
2626

2727
use crate::errors::{
2828
ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment,
@@ -706,12 +706,6 @@ fn has_allow_dead_code_or_lang_attr(
706706
tcx: TyCtxt<'_>,
707707
def_id: LocalDefId,
708708
) -> Option<ComesFromAllowExpect> {
709-
fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
710-
tcx.has_attr(def_id, sym::lang)
711-
// Stable attribute for #[lang = "panic_impl"]
712-
|| tcx.has_attr(def_id, sym::panic_handler)
713-
}
714-
715709
fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
716710
let hir_id = tcx.local_def_id_to_hir_id(def_id);
717711
let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level;
@@ -732,7 +726,9 @@ fn has_allow_dead_code_or_lang_attr(
732726

733727
if has_allow_expect_dead_code(tcx, def_id) {
734728
Some(ComesFromAllowExpect::Yes)
735-
} else if has_used_like_attr(tcx, def_id) || has_lang_attr(tcx, def_id) {
729+
} else if has_used_like_attr(tcx, def_id)
730+
|| find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Lang(..))
731+
{
736732
Some(ComesFromAllowExpect::No)
737733
} else {
738734
None

0 commit comments

Comments
 (0)