diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 0374a86d3eb1..88556aa58c77 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -845,7 +845,7 @@ pub fn list_contains_name(items: &[MetaItemInner], name: Symbol) -> bool { } impl MetaItemLit { - pub fn value_str(&self) -> Option { + pub fn value_as_str(&self) -> Option { LitKind::from_token_lit(self.as_token_lit()).ok().and_then(|lit| lit.str()) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 4cc07ceaf231..f838f7383849 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -135,12 +135,12 @@ fn parse_cfg_entry_version( cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span }) ); }; - let Some(version_lit) = version.lit() else { + let Some(version_lit) = version.as_lit() else { return Err( cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() }) ); }; - let Some(version_str) = version_lit.value_str() else { + let Some(version_str) = version_lit.value_as_str() else { return Err( cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span }) ); diff --git a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs index 1a99e8ff1a6f..0f6b5ee8ad9d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs @@ -13,10 +13,7 @@ impl SingleAttributeParser for CfiEncodingParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { 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); - return None; - }; + let value_str = cx.expect_string_literal(name_value)?; if value_str.as_str().trim().is_empty() { cx.adcx().expected_non_empty_string_literal(name_value.value_span); diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 27501fb3cec1..5c2a41a7a970 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -119,10 +119,7 @@ impl SingleAttributeParser for ExportNameParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { 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; - }; + let name = cx.expect_string_literal(nv)?; if name.as_str().contains('\0') { // `#[export_name = ...]` will be converted to a null-terminated string, // so it may not contain any null characters. @@ -478,8 +475,7 @@ fn parse_tf_attribute( } // Use value - let Some(value_str) = value.value_as_str() else { - cx.adcx().expected_string_literal(value.value_span, Some(value.value_as_lit())); + let Some(value_str) = cx.expect_string_literal(value) else { return features; }; for feature in value_str.as_str().split(",") { diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 5877ac5819aa..311fc0d33c1f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -19,10 +19,7 @@ impl AttributeParser for ConfusablesParser { } for param in list.mixed() { - let span = param.span(); - - let Some(lit) = param.lit().and_then(|i| i.value_str()) else { - cx.adcx().expected_string_literal(span, param.lit()); + let Some(lit) = cx.expect_string_literal(param) else { continue; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 038246536a63..9d6887a33873 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -17,10 +17,7 @@ impl SingleAttributeParser for CrateNameParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { 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())); - return None; - }; + let name = cx.expect_string_literal(n)?; Some(AttributeKind::CrateName { name, name_span: n.value_span, attr_span: cx.attr_span }) } @@ -44,10 +41,7 @@ fn extend( ) -> impl IntoIterator { 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())); - return None; - }; + let crate_type = cx.expect_string_literal(n)?; let Ok(crate_type) = crate_type.try_into() else { // We don't error on invalid `#![crate_type]` when not applied to a crate diff --git a/compiler/rustc_attr_parsing/src/attributes/debugger.rs b/compiler/rustc_attr_parsing/src/attributes/debugger.rs index b77fdfadf824..0fc4166a178e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/debugger.rs +++ b/compiler/rustc_attr_parsing/src/attributes/debugger.rs @@ -34,10 +34,7 @@ fn extend( } }; - let Some(path) = args.value_as_str() else { - cx.adcx().expected_string_literal(args.value_span, Some(args.value_as_lit())); - return None; - }; + let path = cx.expect_string_literal(args)?; Some(DebugVisualizer { span: ident.span.to(args.value_span), visualizer_type, path }) } diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 10232a7c55a5..535f67f67a26 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -255,8 +255,7 @@ fn parse_alias( } ArgParser::List(list) => { for i in list.mixed() { - let Some(alias) = i.lit().and_then(|i| i.value_str()) else { - cx.adcx().expected_string_literal(i.span(), i.lit()); + let Some(alias) = cx.expect_string_literal(i) else { continue; }; @@ -264,8 +263,7 @@ fn parse_alias( } } ArgParser::NameValue(nv) => { - let Some(alias) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + let Some(alias) = cx.expect_string_literal(nv) else { return; }; self.add_alias(cx, alias, nv.value_span); diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index a02f0a89cc04..aee0537771fd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -77,21 +77,11 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let l = cx.expect_single(list)?; - let Some(reason) = l.lit().and_then(|i| i.kind.str()) else { - cx.adcx().expected_string_literal(l.span(), l.lit()); - return None; - }; - - Some(reason) - } - ArgParser::NameValue(v) => { - let Some(reason) = v.value_as_str() else { - cx.adcx().expected_string_literal(v.value_span, Some(v.value_as_lit())); - return None; - }; + let reason = cx.expect_string_literal(l)?; Some(reason) } + ArgParser::NameValue(v) => cx.expect_string_literal(v), }; Some(AttributeKind::Inline( diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index d9310906dfee..0685f989c383 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -37,10 +37,7 @@ impl SingleAttributeParser for LinkNameParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { 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; - }; + let name = cx.expect_string_literal(nv)?; Some(LinkName { name, span: cx.attr_span }) } @@ -260,8 +257,7 @@ fn parse_link_name( let Some(nv) = cx.expect_name_value(item.args(), item.span(), Some(sym::name)) else { return false; }; - let Some(link_name) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.args_span(), Some(nv.value_as_lit())); + let Some(link_name) = cx.expect_string_literal(nv) else { return false; }; @@ -286,8 +282,7 @@ fn parse_link_kind( let Some(nv) = cx.expect_name_value(item.args(), item.span(), Some(sym::kind)) else { return true; }; - let Some(link_kind) = nv.value_as_str() else { - cx.adcx().expected_string_literal(item.span(), Some(nv.value_as_lit())); + let Some(link_kind) = cx.expect_string_literal(nv) else { return true; }; @@ -365,8 +360,7 @@ fn parse_link_modifiers( let Some(nv) = cx.expect_name_value(item.args(), item.span(), Some(sym::modifiers)) else { return true; }; - let Some(link_modifiers) = nv.value_as_str() else { - cx.adcx().expected_string_literal(item.span(), Some(nv.value_as_lit())); + let Some(link_modifiers) = cx.expect_string_literal(nv) else { return true; }; *modifiers = Some((link_modifiers, nv.value_span)); @@ -408,8 +402,7 @@ fn parse_link_wasm_import_module( else { return true; }; - let Some(link_wasm_import_module) = nv.value_as_str() else { - cx.adcx().expected_string_literal(item.span(), Some(nv.value_as_lit())); + let Some(link_wasm_import_module) = cx.expect_string_literal(nv) else { return true; }; *wasm_import_module = Some((link_wasm_import_module, item.span())); @@ -429,8 +422,7 @@ fn parse_link_import_name_type( else { return true; }; - let Some(link_import_name_type) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + let Some(link_import_name_type) = cx.expect_string_literal(nv) else { return true; }; if cx.sess().target.arch != Arch::X86 { @@ -498,10 +490,7 @@ impl SingleAttributeParser for LinkSectionParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { 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; - }; + let name = cx.expect_string_literal(nv)?; if name.as_str().contains('\0') { // `#[link_section = ...]` will be converted to a null-terminated string, // so it may not contain any null characters. @@ -630,9 +619,7 @@ impl SingleAttributeParser for LinkageParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let name_value = cx.expect_name_value(args, cx.attr_span, Some(sym::linkage))?; - let Some(value) = name_value.value_as_str() else { - cx.adcx() - .expected_string_literal(name_value.value_span, Some(name_value.value_as_lit())); + let Some(value) = cx.expect_string_literal(name_value) else { return None; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs index de7ea837b3a7..f8e5cb37328a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs @@ -14,13 +14,7 @@ impl SingleAttributeParser for MustNotSuspendParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let reason = match args { - ArgParser::NameValue(reason) => match reason.value_as_str() { - Some(val) => Some(val), - None => { - cx.adcx().expected_nv_or_no_args(reason.value_span); - return None; - } - }, + ArgParser::NameValue(reason) => cx.expect_string_literal(reason), ArgParser::NoArgs => None, ArgParser::List(list) => { cx.adcx().expected_nv_or_no_args(list.span); diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs index 6cdf8c74c0c5..646ac69b6452 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -30,16 +30,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option None, - ArgParser::NameValue(name_value) => { - 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()), - ); - return None; - }; - Some(value_str) - } + ArgParser::NameValue(name_value) => cx.expect_string_literal(name_value), ArgParser::List(list) => { cx.adcx().expected_nv_or_no_args(list.span); return None; diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs index 0ff87866d624..8b6f20478df7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/path.rs +++ b/compiler/rustc_attr_parsing/src/attributes/path.rs @@ -14,10 +14,7 @@ impl SingleAttributeParser for PathParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let nv = cx.expect_name_value(args, cx.attr_span, None)?; - let Some(path) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); - return None; - }; + let path = cx.expect_string_literal(nv)?; Some(AttributeKind::Path(path)) } diff --git a/compiler/rustc_attr_parsing/src/attributes/prototype.rs b/compiler/rustc_attr_parsing/src/attributes/prototype.rs index fbc27a8d0fd1..8b8eccab029d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prototype.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prototype.rs @@ -74,8 +74,7 @@ fn extract_value( return; } - let Some(value_sym) = val.value_as_str() else { - cx.adcx().expected_string_literal(val.value_span, Some(val.value_as_lit())); + let Some(value_sym) = cx.expect_string_literal(val) else { *failed = true; return; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 496510f67c3f..0ba32c6ca8fa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -43,7 +43,7 @@ fn extend( } for param in list.mixed() { - if let Some(_) = param.lit() { + if let Some(_) = param.as_lit() { cx.emit_err(session_diagnostics::ReprIdent { span: cx.attr_span }); continue; } @@ -212,7 +212,7 @@ fn parse_repr_align( return None; }; - let Some(lit) = align.lit() else { + let Some(lit) = align.as_lit() else { match align_kind { Packed => { cx.emit_err(session_diagnostics::IncorrectReprFormatPackedExpectInteger { @@ -293,7 +293,7 @@ fn parse(&mut self, cx: &mut AcceptContext<'_, '_>, args: &ArgParser) { return; }; - let Some(lit) = align.lit() else { + let Some(lit) = align.as_lit() else { cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger { span: align.span(), }); diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs index 3706fec5e770..b21677b4f79e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs @@ -27,10 +27,7 @@ impl SingleAttributeParser for RustcAllocatorZeroedVariantParser { const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function"); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { 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; - }; + let name = cx.expect_string_literal(nv)?; Some(AttributeKind::RustcAllocatorZeroedVariant { name }) } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 859293bf33a1..8a648550ae8c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -152,14 +152,9 @@ impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let arg = cx.expect_single_element_list(args, cx.attr_span)?; + let lint_message = cx.expect_string_literal(arg)?; - let MetaItemOrLitParser::Lit(MetaItemLit { kind: LitKind::Str(lint_message, _), .. }) = arg - else { - cx.adcx().expected_string_literal(arg.span(), arg.lit()); - return None; - }; - - Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message: *lint_message }) + Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message }) } } @@ -204,10 +199,7 @@ fn parse_cgu_fields( } }; - let Some(str) = arg.value_as_str() else { - cx.adcx().expected_string_literal(arg.value_span, Some(arg.value_as_lit())); - continue; - }; + let str = cx.expect_string_literal(arg)?; if res.is_some() { cx.adcx().duplicate_key(ident.span.to(arg.args_span()), ident.name); @@ -324,10 +316,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option, args: &ArgParser) -> Option, args: &ArgParser) -> Option { 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; - }; + let name = cx.expect_string_literal(nv)?; let Some(lang_item) = LangItem::from_name(name) else { cx.emit_err(UnknownLangItem { span: cx.attr_span, name }); return None; @@ -649,10 +632,7 @@ fn extend( mi.span(), Some(sym::borrowck_graphviz_postflow), )?; - let Some(path) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, None); - return None; - }; + let path = cx.expect_string_literal(nv)?; let path = PathBuf::from(path.to_string()); if path.file_name().is_some() { Some(RustcMirKind::BorrowckGraphvizPostflow { path }) @@ -757,8 +737,7 @@ fn extend( continue; }; let value_span = value.value_span; - let Some(value) = value.value_as_str() else { - cx.adcx().expected_string_literal(value_span, None); + let Some(value) = cx.expect_string_literal(value) else { continue; }; match ident.name { @@ -983,10 +962,7 @@ impl SingleAttributeParser for RustcDiagnosticItemParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let nv = cx.expect_name_value(args, cx.attr_span, None)?; - let Some(value) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); - return None; - }; + let value = cx.expect_string_literal(nv)?; Some(AttributeKind::RustcDiagnosticItem(value)) } } @@ -1038,11 +1014,7 @@ impl SingleAttributeParser for RustcReservationImplParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let nv = cx.expect_name_value(args, cx.attr_span, None)?; - - let Some(value_str) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); - return None; - }; + let value_str = cx.expect_string_literal(nv)?; Some(AttributeKind::RustcReservationImpl(value_str)) } @@ -1065,11 +1037,7 @@ impl SingleAttributeParser for RustcDocPrimitiveParser { fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { let nv = cx.expect_name_value(args, cx.attr_span, None)?; - - let Some(value_str) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); - return None; - }; + let value_str = cx.expect_string_literal(nv)?; Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str)) } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index d70c66dc18cf..4d8943aa3668 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -105,8 +105,7 @@ impl AttributeParser for StabilityParser { let Some(nv) = cx.expect_name_value(args, cx.attr_span, None) else { return; }; - let Some(value_str) = nv.value_as_str() else { - cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + let Some(value_str) = cx.expect_string_literal(nv) else { return; }; this.allowed_through_unstable_modules = Some(value_str); @@ -292,11 +291,7 @@ fn insert_value_into_option_or_error( } let (_ident, arg) = cx.expect_name_value(param, param.span(), Some(name.name))?; - - let Some(s) = arg.value_as_str() else { - cx.adcx().expected_string_literal(arg.value_span, Some(arg.value_as_lit())); - return None; - }; + let s = cx.expect_string_literal(arg)?; *item = Some(s); diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 1ae8dd0e37c2..7ffeb3d2194a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -60,16 +60,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option None, - ArgParser::NameValue(name_value) => { - let Some(str_value) = name_value.value_as_str() else { - cx.adcx().expected_string_literal( - name_value.value_span, - Some(name_value.value_as_lit()), - ); - return None; - }; - Some(str_value) - } + ArgParser::NameValue(name_value) => cx.expect_string_literal(name_value), ArgParser::List(list) => { let single = cx.expect_single(list)?; let (ident, arg) = @@ -78,11 +69,7 @@ fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option, args: &ArgParser) -> Option, args: &ArgParser) -> Option { let name_value = cx.expect_name_value(args, cx.attr_span, Some(sym::rustc_test_marker))?; - - let Some(value_str) = name_value.value_as_str() else { - cx.adcx().expected_string_literal(name_value.value_span, None); - return None; - }; + let value_str = cx.expect_string_literal(name_value)?; if value_str.as_str().trim().is_empty() { cx.adcx().expected_non_empty_string_literal(name_value.value_span); diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs index 438c6ba43505..82f515aff399 100644 --- a/compiler/rustc_attr_parsing/src/attributes/util.rs +++ b/compiler/rustc_attr_parsing/src/attributes/util.rs @@ -41,7 +41,7 @@ pub(crate) fn parse_single_integer( args: &ArgParser, ) -> Option { let single = cx.expect_single_element_list(args, cx.attr_span)?; - let Some(lit) = single.lit() else { + let Some(lit) = single.as_lit() else { cx.adcx().expected_integer_literal(single.span()); return None; }; @@ -54,10 +54,7 @@ pub(crate) fn parse_single_integer( impl AcceptContext<'_, '_> { pub(crate) fn parse_limit_int(&mut self, nv: &NameValueParser) -> Option { - let Some(limit) = nv.value_as_str() else { - self.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit())); - return None; - }; + let limit = self.expect_string_literal(nv)?; let error_str = match limit.as_str().parse() { Ok(i) => return Some(Limit::new(i)), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index bf4989b83200..81cd32faea12 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -562,6 +562,13 @@ pub(crate) fn expect_name_value<'arg, Arg>( } /// Assert that an [`ArgParser`] has no args, or emits an error and return `None`. + /// + /// This is a higher-level (and harder to misuse) wrapper over multiple + /// [`ArgParser::as_no_args`]. You may still want to use the lower-level methods for the + /// following reasons: + /// + /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). + /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. pub(crate) fn expect_no_args<'arg>(&mut self, arg: &'arg ArgParser) -> Option<()> { if let Err(span) = arg.as_no_args() { self.adcx().expected_no_args(span); @@ -570,6 +577,26 @@ pub(crate) fn expect_no_args<'arg>(&mut self, arg: &'arg ArgParser) -> Option<() Some(()) } + + /// Asserts that a node is a string literal, or emits an error and return `None` + /// + /// `arg` must be a reference to any node that may contain a name-value pair, that is: + /// + /// - [`NameValueParser`], + /// - [`MetaItemOrLitParser`], + /// + /// This is a higher-level (and harder to misuse) wrapper over multiple `as_` methods in the + /// [`parser`][crate::parser] module. You may still want to use the lower-level methods for the + /// following reasons: + /// + /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). + /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + pub(crate) fn expect_string_literal<'arg, Arg>(&mut self, arg: &'arg Arg) -> Option + where + Arg: ExpectStringLiteral, + { + arg.expect_string_literal(self) + } } pub(crate) trait ExpectNameValue { @@ -649,6 +676,44 @@ fn expect_name_value<'a, 'f, 'sess>( } } +pub(crate) trait ExpectStringLiteral { + fn expect_string_literal<'f, 'sess>(&self, cx: &mut AcceptContext<'f, 'sess>) + -> Option; +} + +impl ExpectStringLiteral for NameValueParser { + fn expect_string_literal<'f, 'sess>( + &self, + cx: &mut AcceptContext<'f, 'sess>, + ) -> Option { + let value = self.value_as_str(); + if value.is_none() { + cx.adcx().expected_string_literal(self.value_span, Some(self.value_as_lit())); + } + value + } +} + +impl ExpectStringLiteral for MetaItemOrLitParser { + fn expect_string_literal<'f, 'sess>( + &self, + cx: &mut AcceptContext<'f, 'sess>, + ) -> Option { + let Some(lit) = self.as_lit() else { + cx.adcx().expected_string_literal(self.span(), None); + return None; + }; + + let str = lit.value_as_str(); + + if str.is_none() { + cx.adcx().expected_string_literal(self.span(), Some(lit)); + } + + str + } +} + impl<'f, 'sess> Deref for AcceptContext<'f, 'sess> { type Target = SharedContext<'f, 'sess>; diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 845f1394cc3d..48790f273adf 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -240,7 +240,7 @@ pub fn span(&self) -> Span { } } - pub fn lit(&self) -> Option<&MetaItemLit> { + pub fn as_lit(&self) -> Option<&MetaItemLit> { match self { MetaItemOrLitParser::Lit(meta_item_lit) => Some(meta_item_lit), MetaItemOrLitParser::MetaItemParser(_) => None, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7747d9920a32..34785b040118 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1340,7 +1340,7 @@ fn meta_item_list(&self) -> Option> { #[inline] fn value_str(&self) -> Option { - self.value_lit().and_then(|x| x.value_str()) + self.value_lit().and_then(|x| x.value_as_str()) } #[inline]