Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
5 changes: 3 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ pub(crate) fn parse_cfg_entry<S: Stage>(
}
},
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
let Some(name) = meta.path().word_sym() else {
let Some(name) = meta.path().word_sym().filter(|s| !s.is_path_segment_keyword())
else {
cx.expected_identifier(meta.path().span());
return None;
};
Expand Down Expand Up @@ -160,7 +161,7 @@ fn parse_cfg_entry_target<S: Stage>(
};

// Then, parse it as a name-value item
let Some(name) = sub_item.path().word_sym() else {
let Some(name) = sub_item.path().word_sym().filter(|s| !s.is_path_segment_keyword()) else {
cx.expected_identifier(sub_item.path().span());
return None;
};
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/cfg_old.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,10 @@ pub fn eval_condition(
}
}
}
MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
MetaItemKind::Word | MetaItemKind::NameValue(..)
if cfg.path.segments.len() != 1
|| cfg.path.segments[0].ident.is_path_segment_keyword() =>
{
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
true
}
Expand Down
22 changes: 10 additions & 12 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,30 +534,28 @@ impl Emitter for HumanEmitter {
}
}

/// An emitter that does nothing when emitting a non-fatal diagnostic.
/// Fatal diagnostics are forwarded to `fatal_emitter` to avoid silent
/// An emitter that does nothing when emitting a non-error diagnostic.
/// Error diagnostics are forwarded to `error_emitter` to avoid silent
/// failures of rustc, as witnessed e.g. in issue #89358.
pub struct FatalOnlyEmitter {
pub fatal_emitter: Box<dyn Emitter + DynSend>,
pub fatal_note: Option<String>,
pub struct ErrorOnlyEmitter {
pub error_emitter: Box<dyn Emitter + DynSend>,
pub error_note: String,
}

impl Emitter for FatalOnlyEmitter {
impl Emitter for ErrorOnlyEmitter {
fn source_map(&self) -> Option<&SourceMap> {
None
}

fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) {
if diag.level == Level::Fatal {
if let Some(fatal_note) = &self.fatal_note {
diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
}
self.fatal_emitter.emit_diagnostic(diag, registry);
if diag.is_error() {
diag.sub(Level::Note, self.error_note.clone(), MultiSpan::new());
self.error_emitter.emit_diagnostic(diag, registry);
}
}

fn translator(&self) -> &Translator {
self.fatal_emitter.translator()
self.error_emitter.translator()
}
}

Expand Down
69 changes: 47 additions & 22 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use rustc_middle::ty::CurrentGcx;
use rustc_middle::util::Providers;
use rustc_parse::lexer::StripTokens;
use rustc_parse::new_parser_from_source_str;
use rustc_parse::parser::Recovery;
use rustc_parse::parser::attr::AllowLeadingUnsafe;
use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack;
Expand Down Expand Up @@ -52,7 +53,7 @@ pub struct Compiler {
pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
cfgs.into_iter()
.map(|s| {
let psess = ParseSess::with_fatal_emitter(
let psess = ParseSess::with_error_emitter(
vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
format!("this error occurred on the command line: `--cfg={s}`"),
);
Expand All @@ -63,35 +64,47 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
dcx.fatal(format!(
concat!("invalid `--cfg` argument: `{}` (", $reason, ")"),
s
"invalid `--cfg` argument: `{}` ({})",
s, $reason,
));
};
}

match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
{
Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => {
if meta_item.path.segments.len() != 1 {
error!("argument key must be an identifier");
}
match &meta_item.kind {
MetaItemKind::List(..) => {}
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
error!("argument value must be a string");
Ok(mut parser) => {
parser = parser.recovery(Recovery::Forbidden);
match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => {
if meta_item.path.segments.len() != 1 {
error!("argument key must be an identifier");
}
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
let ident = meta_item.ident().expect("multi-segment cfg key");
return (ident.name, meta_item.value_str());
match &meta_item.kind {
MetaItemKind::List(..) => {}
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
error!("argument value must be a string");
}
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
let ident = meta_item.ident().expect("multi-segment cfg key");

if !ident.name.can_be_raw() {
error!(format!("argument key must be an identifier, but `{}` cannot be a raw identifier", ident.name));
}

return (ident.name, meta_item.value_str());
}
}
}
Ok(..) => {}
Err(err) => {
err.emit();
},
}
Ok(..) => {}
Err(err) => err.cancel(),
},
Err(errs) => errs.into_iter().for_each(|err| err.cancel()),
}
Err(errs) => errs.into_iter().for_each(|err| {
err.emit();
}),
};

// If the user tried to use a key="value" flag, but is missing the quotes, provide
// a hint about how to resolve this.
Expand All @@ -116,7 +129,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };

for s in specs {
let psess = ParseSess::with_fatal_emitter(
let psess = ParseSess::with_error_emitter(
vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
format!("this error occurred on the command line: `--check-cfg={s}`"),
);
Expand Down Expand Up @@ -173,16 +186,19 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
{
Ok(parser) => parser,
Err(errs) => {
errs.into_iter().for_each(|err| err.cancel());
errs.into_iter().for_each(|err| {
err.emit();
});
expected_error();
}
};
parser = parser.recovery(Recovery::Forbidden);

let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => meta_item,
Ok(..) => expected_error(),
Err(err) => {
err.cancel();
err.emit();
expected_error();
}
};
Expand All @@ -209,11 +225,20 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
if values_specified {
error!("`cfg()` names cannot be after values");
}

if !ident.name.can_be_raw() {
error!(format!(
"argument key must be an identifier, but `{}` cannot be a raw identifier",
ident.name
));
}

names.push(ident);
} else if let Some(boolean) = arg.boolean_literal() {
if values_specified {
error!("`cfg()` names cannot be after values");
}

names.push(rustc_span::Ident::new(
if boolean { rustc_span::kw::True } else { rustc_span::kw::False },
arg.span(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ impl<'a> Parser<'a> {

// Public for rustfmt usage.
pub fn parse_ident(&mut self) -> PResult<'a, Ident> {
self.parse_ident_common(true)
self.parse_ident_common(self.may_recover())
}

fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
Expand Down
13 changes: 5 additions & 8 deletions compiler/rustc_session/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sync::{AppendOnlyVec, Lock};
use rustc_errors::emitter::{FatalOnlyEmitter, HumanEmitter, stderr_destination};
use rustc_errors::emitter::{ErrorOnlyEmitter, HumanEmitter, stderr_destination};
use rustc_errors::translation::Translator;
use rustc_errors::{
BufferedEarlyLint, ColorConfig, DecorateDiagCompat, Diag, DiagCtxt, DiagCtxtHandle,
Expand Down Expand Up @@ -315,16 +315,13 @@ impl ParseSess {
}
}

pub fn with_fatal_emitter(locale_resources: Vec<&'static str>, fatal_note: String) -> Self {
pub fn with_error_emitter(locale_resources: Vec<&'static str>, error_note: String) -> Self {
let translator = Translator::with_fallback_bundle(locale_resources, false);
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
let fatal_emitter =
let emitter =
Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), translator));
let dcx = DiagCtxt::new(Box::new(FatalOnlyEmitter {
fatal_emitter,
fatal_note: Some(fatal_note),
}))
.disable_warnings();
let dcx = DiagCtxt::new(Box::new(ErrorOnlyEmitter { error_emitter: emitter, error_note }))
.disable_warnings();
ParseSess::with_dcx(dcx, sm)
}

Expand Down
8 changes: 4 additions & 4 deletions src/tools/clippy/tests/ui/cast_size.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@revisions: 32bit 64bit
//@[32bit]ignore-bitwidth: 64
//@[64bit]ignore-bitwidth: 32
//@revisions: r32bit r64bit
//@[r32bit]ignore-bitwidth: 64
//@[r64bit]ignore-bitwidth: 32
//@no-rustfix: only some diagnostics have suggestions

#![warn(
Expand Down Expand Up @@ -62,7 +62,7 @@ fn main() {
//~^ cast_precision_loss
9_999_999_999_999_999usize as f64;
//~^ cast_precision_loss
//~[32bit]^^ ERROR: literal out of range for `usize`
//~[r32bit]^^ ERROR: literal out of range for `usize`
// 999_999_999_999_999_999_999_999_999_999u128 as f128;
}

Expand Down
26 changes: 13 additions & 13 deletions src/tools/clippy/tests/ui/fn_to_numeric_cast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//@revisions: 32bit 64bit
//@[32bit]ignore-bitwidth: 64
//@[64bit]ignore-bitwidth: 32
//@revisions: r32bit r64bit
//@[r32bit]ignore-bitwidth: 64
//@[r64bit]ignore-bitwidth: 32
//@no-rustfix
#![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)]

Expand All @@ -14,8 +14,8 @@ fn test_function_to_numeric_cast() {
let _ = foo as i16;
//~^ fn_to_numeric_cast_with_truncation
let _ = foo as i32;
//~[64bit]^ fn_to_numeric_cast_with_truncation
//~[32bit]^^ fn_to_numeric_cast
//~[r64bit]^ fn_to_numeric_cast_with_truncation
//~[r32bit]^^ fn_to_numeric_cast
let _ = foo as i64;
//~^ fn_to_numeric_cast
let _ = foo as i128;
Expand All @@ -28,8 +28,8 @@ fn test_function_to_numeric_cast() {
let _ = foo as u16;
//~^ fn_to_numeric_cast_with_truncation
let _ = foo as u32;
//~[64bit]^ fn_to_numeric_cast_with_truncation
//~[32bit]^^ fn_to_numeric_cast
//~[r64bit]^ fn_to_numeric_cast_with_truncation
//~[r32bit]^^ fn_to_numeric_cast
let _ = foo as u64;
//~^ fn_to_numeric_cast
let _ = foo as u128;
Expand All @@ -51,8 +51,8 @@ fn test_function_var_to_numeric_cast() {
let _ = abc as i16;
//~^ fn_to_numeric_cast_with_truncation
let _ = abc as i32;
//~[64bit]^ fn_to_numeric_cast_with_truncation
//~[32bit]^^ fn_to_numeric_cast
//~[r64bit]^ fn_to_numeric_cast_with_truncation
//~[r32bit]^^ fn_to_numeric_cast
let _ = abc as i64;
//~^ fn_to_numeric_cast
let _ = abc as i128;
Expand All @@ -65,8 +65,8 @@ fn test_function_var_to_numeric_cast() {
let _ = abc as u16;
//~^ fn_to_numeric_cast_with_truncation
let _ = abc as u32;
//~[64bit]^ fn_to_numeric_cast_with_truncation
//~[32bit]^^ fn_to_numeric_cast
//~[r64bit]^ fn_to_numeric_cast_with_truncation
//~[r32bit]^^ fn_to_numeric_cast
let _ = abc as u64;
//~^ fn_to_numeric_cast
let _ = abc as u128;
Expand All @@ -78,8 +78,8 @@ fn test_function_var_to_numeric_cast() {

fn fn_with_fn_args(f: fn(i32) -> i32) -> i32 {
f as i32
//~[64bit]^ fn_to_numeric_cast_with_truncation
//~[32bit]^^ fn_to_numeric_cast
//~[r64bit]^ fn_to_numeric_cast_with_truncation
//~[r32bit]^^ fn_to_numeric_cast
}

fn main() {}
10 changes: 5 additions & 5 deletions src/tools/clippy/tests/ui/large_enum_variant.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//@revisions: 32bit 64bit
//@revisions: r32bit r64bit
//@aux-build:proc_macros.rs
//@no-rustfix
//@[32bit]ignore-bitwidth: 64
//@[64bit]ignore-bitwidth: 32
//@[r32bit]ignore-bitwidth: 64
//@[r64bit]ignore-bitwidth: 32
#![allow(dead_code)]
#![allow(unused_variables)]
#![warn(clippy::large_enum_variant)]
Expand Down Expand Up @@ -221,13 +221,13 @@ mod issue11915 {
}

enum NoWarnings {
//~[64bit]^ large_enum_variant
//~[r64bit]^ large_enum_variant
BigBoi(PublishWithBytes),
_SmallBoi(u8),
}

enum MakesClippyAngry {
//~[64bit]^ large_enum_variant
//~[r64bit]^ large_enum_variant
BigBoi(PublishWithVec),
_SmallBoi(u8),
}
Expand Down
10 changes: 5 additions & 5 deletions tests/codegen-llvm/cf-protection.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Test that the correct module flags are emitted with different control-flow protection flags.

//@ add-core-stubs
//@ revisions: undefined none branch return full
//@ revisions: undefined none branch return_ full
//@ needs-llvm-components: x86
// [undefined] no extra compile-flags
//@ [none] compile-flags: -Z cf-protection=none
//@ [branch] compile-flags: -Z cf-protection=branch
//@ [return] compile-flags: -Z cf-protection=return
//@ [return_] compile-flags: -Z cf-protection=return
//@ [full] compile-flags: -Z cf-protection=full
//@ compile-flags: --target x86_64-unknown-linux-gnu

Expand All @@ -30,9 +30,9 @@ pub fn test() {}
// branch: !"cf-protection-branch", i32 1
// branch-NOT: !"cf-protection-return"

// return-NOT: !"cf-protection-branch"
// return: !"cf-protection-return", i32 1
// return-NOT: !"cf-protection-branch"
// return_-NOT: !"cf-protection-branch"
// return_: !"cf-protection-return", i32 1
// return_-NOT: !"cf-protection-branch"

// full: !"cf-protection-branch", i32 1
// full: !"cf-protection-return", i32 1
6 changes: 6 additions & 0 deletions tests/run-make/multiline-args-value/cfg-frontmatter.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
error: expected identifier, found `-`
|
= note: this error occurred on the command line: `--cfg=---
---
key`

error: invalid `--cfg` argument: `---
---
key` (expected `key` or `key="value"`)
Expand Down
Loading
Loading