about summary refs log tree commit diff
path: root/compiler/rustc_attr_parsing
diff options
context:
space:
mode:
authorJana Dönszelmann <jana@donsz.nl>2025-08-11 11:46:30 +0200
committerJana Dönszelmann <jana@donsz.nl>2025-08-24 09:14:49 +0200
commit3bf61444616fc0b9de1e09031f40be0943823fc5 (patch)
treec7fb122fb12ddd2a76e0bd1c350b48ee648eee07 /compiler/rustc_attr_parsing
parent4eedad312695d773b6e2e17a4f8082660470c101 (diff)
downloadrust-3bf61444616fc0b9de1e09031f40be0943823fc5.tar.gz
rust-3bf61444616fc0b9de1e09031f40be0943823fc5.zip
Allow errors to be emitted as fatal during attribute parsing
Diffstat (limited to 'compiler/rustc_attr_parsing')
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs40
-rw-r--r--compiler/rustc_attr_parsing/src/interface.rs2
-rw-r--r--compiler/rustc_attr_parsing/src/parser.rs23
3 files changed, 43 insertions, 22 deletions
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index bb701df6053..f30edbfaaa1 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -5,7 +5,7 @@ use std::sync::LazyLock;
 
 use private::Sealed;
 use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
-use rustc_errors::Diagnostic;
+use rustc_errors::{Diag, Diagnostic, Level};
 use rustc_feature::AttributeTemplate;
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
@@ -263,11 +263,7 @@ impl Stage for Early {
         sess: &'sess Session,
         diag: impl for<'x> Diagnostic<'x>,
     ) -> ErrorGuaranteed {
-        if self.emit_errors.should_emit() {
-            sess.dcx().emit_err(diag)
-        } else {
-            sess.dcx().create_err(diag).delay_as_bug()
-        }
+        self.should_emit().emit_err_or_delay(sess.dcx().create_err(diag))
     }
 
     fn should_emit(&self) -> ShouldEmit {
@@ -333,7 +329,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
     /// must be delayed until after HIR is built. This method will take care of the details of
     /// that.
     pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
-        if !self.stage.should_emit().should_emit() {
+        if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
             return;
         }
         let id = self.target_id;
@@ -651,8 +647,13 @@ pub enum OmitDoc {
     Skip,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum ShouldEmit {
+    /// The operations will emit errors, and lints, and errors are fatal.
+    ///
+    /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
+    /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
+    EarlyFatal,
     /// The operation will emit errors and lints.
     /// This is usually what you need.
     ErrorsAndLints,
@@ -662,10 +663,27 @@ pub enum ShouldEmit {
 }
 
 impl ShouldEmit {
-    pub fn should_emit(&self) -> bool {
+    pub(crate) fn emit_err_or_delay(&self, diag: Diag<'_>) -> ErrorGuaranteed {
+        match self {
+            ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(),
+            ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(),
+            ShouldEmit::ErrorsAndLints => diag.emit(),
+            ShouldEmit::Nothing => diag.delay_as_bug(),
+        }
+    }
+
+    pub(crate) fn maybe_emit_err(&self, diag: Diag<'_>) {
         match self {
-            ShouldEmit::ErrorsAndLints => true,
-            ShouldEmit::Nothing => false,
+            ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => {
+                diag.emit();
+            }
+            ShouldEmit::EarlyFatal => {
+                diag.upgrade_to_fatal().emit();
+            }
+            ShouldEmit::ErrorsAndLints => {
+                diag.emit();
+            }
+            ShouldEmit::Nothing => {}
         }
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs
index f652d39a708..b4222e41b71 100644
--- a/compiler/rustc_attr_parsing/src/interface.rs
+++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -252,7 +252,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
 
                             (accept.accept_fn)(&mut cx, args);
 
-                            if self.stage.should_emit().should_emit() {
+                            if !matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
                                 self.check_target(
                                     path.get_attribute_path(),
                                     attr.span,
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index 364f8819d13..3ba188938c6 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -328,15 +328,16 @@ fn expr_to_lit(
         match res {
             Ok(lit) => {
                 if token_lit.suffix.is_some() {
-                    psess
-                        .dcx()
-                        .create_err(SuffixedLiteralInAttribute { span: lit.span })
-                        .emit_unless_delay(!should_emit.should_emit());
+                    should_emit.emit_err_or_delay(
+                        psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+                    );
                     None
                 } else {
-                    if should_emit.should_emit() && !lit.kind.is_unsuffixed() {
+                    if !lit.kind.is_unsuffixed() {
                         // Emit error and continue, we can still parse the attribute as if the suffix isn't there
-                        psess.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
+                        should_emit.maybe_emit_err(
+                            psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+                        );
                     }
 
                     Some(lit)
@@ -366,7 +367,7 @@ fn expr_to_lit(
             err.downgrade_to_delayed_bug();
         }
 
-        err.emit_unless_delay(!should_emit.should_emit());
+        should_emit.emit_err_or_delay(err);
         None
     }
 }
@@ -397,9 +398,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
             }
         };
 
-        if self.should_emit.should_emit() && !lit.kind.is_unsuffixed() {
+        if !lit.kind.is_unsuffixed() {
             // Emit error and continue, we can still parse the attribute as if the suffix isn't there
-            self.parser.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
+            self.should_emit.maybe_emit_err(
+                self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+            );
         }
 
         Ok(lit)
@@ -539,7 +542,7 @@ impl<'a> MetaItemListParser<'a> {
         ) {
             Ok(s) => Some(s),
             Err(e) => {
-                e.emit_unless_delay(!should_emit.should_emit());
+                should_emit.emit_err_or_delay(e);
                 None
             }
         }