diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6c387a385e640..fcbe757e22329 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1039,6 +1039,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Ok((Some(ext), _)) = this.resolve_macro_path( derive, Some(MacroKind::Derive), + false, parent_scope, false, false, diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index a069c6f8e0436..902dd82ccdcbd 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -443,6 +443,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match this.resolve_macro_path( derive, Some(MacroKind::Derive), + false, parent_scope, true, force, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 75a0541b89be4..54e74d7a36fbc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3869,7 +3869,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident); let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None }; if let Ok((_, res)) = - self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false) + self.r.resolve_macro_path(&path, None, false, &self.parent_scope, false, false) { return Ok(Some(PartialRes::new(res))); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 208391cc0199f..268df6ea0ac83 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1047,7 +1047,7 @@ pub struct Resolver<'a, 'tcx> { proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: - Vec<(Ident, MacroKind, ParentScope<'a>, Option>)>, + Vec<(Ident, MacroKind, bool, ParentScope<'a>, Option>)>, multi_segment_macro_resolutions: Vec<(Vec, Span, MacroKind, ParentScope<'a>, Option)>, builtin_attrs: Vec<(Ident, ParentScope<'a>)>, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 5f21741223bc0..ff0c9cdc4cc7b 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_err, Applicability, FatalError}; use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; @@ -373,6 +373,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { match self.resolve_macro_path( path, Some(MacroKind::Derive), + false, &parent_scope, true, force, @@ -504,8 +505,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { force: bool, soft_custom_inner_attributes_gate: bool, ) -> Result<(Lrc, Res), Indeterminate> { - let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force) - { + let (ext, res) = match self.resolve_macro_path( + path, + Some(kind), + inner_attr, + parent_scope, + true, + force, + ) { Ok((Some(ext), res)) => (ext, res), Ok((None, res)) => (self.dummy_ext(kind), res), Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err), @@ -627,6 +634,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &ast::Path, kind: Option, + inner_attr: bool, parent_scope: &ParentScope<'a>, trace: bool, force: bool, @@ -685,6 +693,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.single_segment_macro_resolutions.push(( path[0].ident, kind, + inner_attr, *parent_scope, binding.ok(), )); @@ -794,7 +803,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions); - for (ident, kind, parent_scope, initial_binding) in macro_resolutions { + let mut has_reported_inner_attr_error = false; + let mut raise_fatal_error = false; + for (ident, kind, inner_attr, parent_scope, initial_binding) in macro_resolutions { match self.early_resolve_ident_in_lexical_scope( ident, ScopeSet::Macro(kind), @@ -810,7 +821,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); let res = binding.res(); let seg = Segment::from_ident(ident); - check_consistency(self, &[seg], ident.span, kind, initial_res, res); + if has_reported_inner_attr_error + && let Res::Def(DefKind::Macro(MacroKind::Attr), _) = res + && let None = initial_res + { + // Do not emit an indeterminate resolution and later errors when an outer + // attribute wasn't found, as this can be knock down effects. #118455 + raise_fatal_error = true; + } else { + let res = binding.res(); + check_consistency(self, &[seg], ident.span, kind, initial_res, res); + }; if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) { let node_id = self .invocation_parents @@ -825,7 +846,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); } } - Err(..) => { + Err(_) => { + if inner_attr { + has_reported_inner_attr_error = true; + } let expected = kind.descr_expected(); let mut err = self.tcx.sess.create_err(CannotFindIdentInThisScope { @@ -851,6 +875,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None, ); } + + if raise_fatal_error { + // When we encounter an inner attribute failure, and subsequent successful macro + // resolutions following early resolution failures. This is so when an outer attribute + // isn't found, and we encounter `derive` attributes, we won't raise errors caused by + // any code that relies on those derives having been evaluated. We don't attempt to + // recover because the behavior of those derives could have been modified by the outer + // attribute, causing *other* errors, so it is safest to just stop early instead. + FatalError.raise(); + } } fn check_stability_and_deprecation( diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs index 4a7e48eed46c3..c772050d57f45 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs @@ -5,8 +5,10 @@ #[macro_use] extern crate test_macros; -#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive` +#[derive(Empty, Clone)] // no error emitted here #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope struct Foo {} -fn main() {} +fn main() { + let _ = Foo.clone(); // no error emitted here +} diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr index fd1ed8a3d0ff3..b34713b8ca68e 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr @@ -4,19 +4,11 @@ error: cannot find attribute `dummy` in this scope LL | #![dummy] | ^^^^^ -error: cannot determine resolution for the attribute macro `derive` - --> $DIR/derive-helper-legacy-spurious.rs:8:3 - | -LL | #[derive(Empty)] - | ^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: cannot find attribute `empty_helper` in this scope --> $DIR/derive-helper-legacy-spurious.rs:9:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors