Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 6 additions & 13 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub fn parse_cfg_entry<S: Stage>(
else {
return Err(cx.adcx().expected_identifier(meta.path().span()));
};
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
parse_name_value(name, meta.path().span(), a.as_name_value(), meta.span(), cx)?
}
},
MetaItemOrLitParser::Lit(lit) => match lit.kind {
Expand Down Expand Up @@ -178,23 +178,16 @@ fn parse_cfg_entry_target<S: Stage>(
let mut result = ThinVec::new();
for sub_item in list.mixed() {
// First, validate that this is a NameValue item
let Some(sub_item) = sub_item.meta_item() else {
cx.adcx().expected_name_value(sub_item.span(), None);
continue;
};
let Some(nv) = sub_item.args().name_value() else {
cx.adcx().expected_name_value(sub_item.span(), None);
let Some((name, value)) = cx.expect_name_value(sub_item, sub_item.span(), None) else {
continue;
};

// Then, parse it as a name-value item
let Some(name) = sub_item.path().word_sym().filter(|s| !s.is_path_segment_keyword()) else {
return Err(cx.adcx().expected_identifier(sub_item.path().span()));
};
if name.is_path_segment_keyword() {
return Err(cx.adcx().expected_identifier(name.span));
}
let name = Symbol::intern(&format!("target_{name}"));
if let Ok(cfg) =
parse_name_value(name, sub_item.path().span(), Some(nv), sub_item.span(), cx)
{
if let Ok(cfg) = parse_name_value(name, sub_item.span(), Some(value), sub_item.span(), cx) {
result.push(cfg);
}
}
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ impl<S: Stage> SingleAttributeParser<S> for CfiEncodingParser {
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "encoding");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(name_value) = args.name_value() else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, Some(sym::cfi_encoding));
return None;
};
let name_value = cx.expect_name_value(args, cx.attr_span, Some(sym::cfi_encoding))?;

let Some(value_str) = name_value.value_as_str() else {
cx.adcx().expected_string_literal(name_value.value_span, None);
Expand Down
98 changes: 31 additions & 67 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,7 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let nv = cx.expect_name_value(args, cx.attr_span, None)?;
let Some(name) = nv.value_as_str() else {
cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
Expand All @@ -146,11 +142,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcObjcClassParser {
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "ClassName");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let nv = cx.expect_name_value(args, cx.attr_span, None)?;
let Some(classname) = nv.value_as_str() else {
// `#[rustc_objc_class = ...]` is expected to be used as an implementation detail
// inside a standard library macro, but `cx.expected_string_literal` exposes too much.
Expand All @@ -177,11 +169,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcObjcSelectorParser {
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "methodName");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let nv = cx.expect_name_value(args, cx.attr_span, None)?;
let Some(methname) = nv.value_as_str() else {
// `#[rustc_objc_selector = ...]` is expected to be used as an implementation detail
// inside a standard library macro, but `cx.expected_string_literal` exposes too much.
Expand Down Expand Up @@ -471,29 +459,20 @@ fn parse_tf_attribute<S: Stage>(
return features;
}
for item in list.mixed() {
let Some(name_value) = item.meta_item() else {
cx.adcx().expected_name_value(item.span(), Some(sym::enable));
let Some((ident, value)) = cx.expect_name_value(item, item.span(), Some(sym::enable))
else {
return features;
};

// Validate name
let Some(name) = name_value.path().word_sym() else {
cx.adcx().expected_name_value(name_value.path().span(), Some(sym::enable));
return features;
};
if name != sym::enable {
cx.adcx().expected_name_value(name_value.path().span(), Some(sym::enable));
if ident.name != sym::enable {
cx.adcx().expected_specific_argument(ident.span, &[sym::enable]);
return features;
}

// Use value
let Some(name_value) = name_value.args().name_value() else {
cx.adcx().expected_name_value(item.span(), Some(sym::enable));
return features;
};
let Some(value_str) = name_value.value_as_str() else {
cx.adcx()
.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
let Some(value_str) = value.value_as_str() else {
cx.adcx().expected_string_literal(value.value_span, Some(value.value_as_lit()));
return features;
};
for feature in value_str.as_str().split(",") {
Expand Down Expand Up @@ -592,14 +571,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
let mut rtsan = None;

for item in list.mixed() {
let Some(item) = item.meta_item() else {
cx.adcx().expected_name_value(item.span(), None);
continue;
};

let path = item.path().word_sym();
let Some(value) = item.args().name_value() else {
cx.adcx().expected_name_value(item.span(), path);
let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else {
continue;
};

Expand Down Expand Up @@ -628,20 +600,20 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
}
};

match path {
Some(sym::address) | Some(sym::kernel_address) => {
match ident.name {
sym::address | sym::kernel_address => {
apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
}
Some(sym::cfi) => apply(SanitizerSet::CFI),
Some(sym::kcfi) => apply(SanitizerSet::KCFI),
Some(sym::memory) => apply(SanitizerSet::MEMORY),
Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
Some(sym::thread) => apply(SanitizerSet::THREAD),
Some(sym::hwaddress) | Some(sym::kernel_hwaddress) => {
sym::cfi => apply(SanitizerSet::CFI),
sym::kcfi => apply(SanitizerSet::KCFI),
sym::memory => apply(SanitizerSet::MEMORY),
sym::memtag => apply(SanitizerSet::MEMTAG),
sym::shadow_call_stack => apply(SanitizerSet::SHADOWCALLSTACK),
sym::thread => apply(SanitizerSet::THREAD),
sym::hwaddress | sym::kernel_hwaddress => {
apply(SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS)
}
Some(sym::realtime) => match value.value_as_str() {
sym::realtime => match value.value_as_str() {
Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking),
Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking),
Some(sym::caller) => rtsan = Some(RtsanSetting::Caller),
Expand All @@ -654,7 +626,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
},
_ => {
cx.adcx().expected_specific_argument_strings(
item.path().span(),
ident.span,
&[
sym::address,
sym::kernel_address,
Expand Down Expand Up @@ -725,57 +697,49 @@ impl<S: Stage> SingleAttributeParser<S> for PatchableFunctionEntryParser {
let mut errored = false;

for item in meta_item_list.mixed() {
let Some(meta_item) = item.meta_item() else {
errored = true;
cx.adcx().expected_name_value(item.span(), None);
continue;
};

let Some(name_value_lit) = meta_item.args().name_value() else {
errored = true;
cx.adcx().expected_name_value(item.span(), None);
let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else {
continue;
};

let attrib_to_write = match meta_item.ident().map(|ident| ident.name) {
Some(sym::prefix_nops) => {
let attrib_to_write = match ident.name {
sym::prefix_nops => {
// Duplicate prefixes are not allowed
if prefix.is_some() {
errored = true;
cx.adcx().duplicate_key(meta_item.path().span(), sym::prefix_nops);
cx.adcx().duplicate_key(ident.span, sym::prefix_nops);
continue;
}
&mut prefix
}
Some(sym::entry_nops) => {
sym::entry_nops => {
// Duplicate entries are not allowed
if entry.is_some() {
errored = true;
cx.adcx().duplicate_key(meta_item.path().span(), sym::entry_nops);
cx.adcx().duplicate_key(ident.span, sym::entry_nops);
continue;
}
&mut entry
}
_ => {
errored = true;
cx.adcx().expected_specific_argument(
meta_item.path().span(),
ident.span,
&[sym::prefix_nops, sym::entry_nops],
);
continue;
}
};

let rustc_ast::LitKind::Int(val, _) = name_value_lit.value_as_lit().kind else {
let rustc_ast::LitKind::Int(val, _) = value.value_as_lit().kind else {
errored = true;
cx.adcx().expected_integer_literal(name_value_lit.value_span);
cx.adcx().expected_integer_literal(value.value_span);
continue;
};

let Ok(val) = val.get().try_into() else {
errored = true;
cx.adcx().expected_integer_literal_in_range(
name_value_lit.value_span,
value.value_span,
u8::MIN as isize,
u8::MAX as isize,
);
Expand Down
45 changes: 7 additions & 38 deletions compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(n) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let n = cx.expect_name_value(args, cx.attr_span, None)?;

let Some(name) = n.value_as_str() else {
cx.adcx().expected_string_literal(n.value_span, Some(n.value_as_lit()));
Expand All @@ -47,11 +43,7 @@ impl<S: Stage> CombineAttributeParser<S> for CrateTypeParser {
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let ArgParser::NameValue(n) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let n = cx.expect_name_value(args, cx.attr_span, None)?;

let Some(crate_type) = n.value_as_str() else {
cx.adcx().expected_string_literal(n.value_span, Some(n.value_as_lit()));
Expand Down Expand Up @@ -95,11 +87,7 @@ impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let nv = cx.expect_name_value(args, cx.attr_span, None)?;

Some(AttributeKind::RecursionLimit {
limit: cx.parse_limit_int(nv)?,
Expand All @@ -117,11 +105,7 @@ impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let nv = cx.expect_name_value(args, cx.attr_span, None)?;

Some(AttributeKind::MoveSizeLimit {
limit: cx.parse_limit_int(nv)?,
Expand All @@ -140,11 +124,7 @@ impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let nv = cx.expect_name_value(args, cx.attr_span, None)?;

Some(AttributeKind::TypeLengthLimit {
limit: cx.parse_limit_int(nv)?,
Expand All @@ -162,11 +142,7 @@ impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
let attr_span = cx.attr_span;
cx.adcx().expected_name_value(attr_span, None);
return None;
};
let nv = cx.expect_name_value(args, cx.attr_span, None)?;

Some(AttributeKind::PatternComplexityLimit {
limit: cx.parse_limit_int(nv)?,
Expand Down Expand Up @@ -219,14 +195,7 @@ impl<S: Stage> SingleAttributeParser<S> for WindowsSubsystemParser {
const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
let inner_span = cx.inner_span;
cx.adcx().expected_name_value(
args.span().unwrap_or(inner_span),
Some(sym::windows_subsystem),
);
return None;
};
let nv = cx.expect_name_value(args, cx.inner_span, Some(sym::windows_subsystem))?;

let kind = match nv.value_as_str() {
Some(sym::console) => WindowsSubsystemKind::Console,
Expand Down
25 changes: 8 additions & 17 deletions compiler/rustc_attr_parsing/src/attributes/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,24 @@ impl<S: Stage> CombineAttributeParser<S> for DebuggerViualizerParser {
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let single = cx.expect_single_element_list(args, cx.attr_span)?;
let Some(mi) = single.meta_item() else {
cx.adcx().expected_name_value(single.span(), None);
return None;
};
let path = mi.path().word_sym();
let visualizer_type = match path {
Some(sym::natvis_file) => DebuggerVisualizerType::Natvis,
Some(sym::gdb_script_file) => DebuggerVisualizerType::GdbPrettyPrinter,
let (ident, args) = cx.expect_name_value(single, single.span(), None)?;
let visualizer_type = match ident.name {
sym::natvis_file => DebuggerVisualizerType::Natvis,
sym::gdb_script_file => DebuggerVisualizerType::GdbPrettyPrinter,
_ => {
cx.adcx().expected_specific_argument(
mi.path().span(),
ident.span,
&[sym::natvis_file, sym::gdb_script_file],
);
return None;
}
};

let Some(path) = mi.args().name_value() else {
cx.adcx().expected_name_value(single.span(), path);
return None;
};

let Some(path) = path.value_as_str() else {
cx.adcx().expected_string_literal(path.value_span, Some(path.value_as_lit()));
let Some(path) = args.value_as_str() else {
cx.adcx().expected_string_literal(args.value_span, Some(args.value_as_lit()));
return None;
};

Some(DebugVisualizer { span: mi.span(), visualizer_type, path })
Some(DebugVisualizer { span: ident.span.to(args.value_span), visualizer_type, path })
}
}
Loading
Loading