Skip to content

Commit 9e404df

Browse files
committed
On outer attr not found, avoid knock-down errors
When we encounter code like ```rust #![non_existent] #[derive(Clone)] struct S; fn main() { S.clone(); } ``` we avoid emitting errors about the `derive` (which isn't early resolved as normal, but *has* a later resolution) and stop the compiler from advancing to later stages, to avoid knock down errors from the `derive` not being evaluated. Recovering these would be possible, but would produce incorrect errors in the cases where had the outer attribute been present it would have modified the behavior/evaluation of the `derive` attributes. Fix #118455.
1 parent 25c75bc commit 9e404df

File tree

7 files changed

+49
-19
lines changed

7 files changed

+49
-19
lines changed

compiler/rustc_resolve/src/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
10391039
if let Ok((Some(ext), _)) = this.resolve_macro_path(
10401040
derive,
10411041
Some(MacroKind::Derive),
1042+
false,
10421043
parent_scope,
10431044
false,
10441045
false,

compiler/rustc_resolve/src/ident.rs

+1
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
443443
match this.resolve_macro_path(
444444
derive,
445445
Some(MacroKind::Derive),
446+
false,
446447
parent_scope,
447448
true,
448449
force,

compiler/rustc_resolve/src/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3869,7 +3869,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
38693869
let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
38703870
let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
38713871
if let Ok((_, res)) =
3872-
self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false)
3872+
self.r.resolve_macro_path(&path, None, false, &self.parent_scope, false, false)
38733873
{
38743874
return Ok(Some(PartialRes::new(res)));
38753875
}

compiler/rustc_resolve/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ pub struct Resolver<'a, 'tcx> {
10471047
proc_macro_stubs: FxHashSet<LocalDefId>,
10481048
/// Traces collected during macro resolution and validated when it's complete.
10491049
single_segment_macro_resolutions:
1050-
Vec<(Ident, MacroKind, ParentScope<'a>, Option<NameBinding<'a>>)>,
1050+
Vec<(Ident, MacroKind, bool, ParentScope<'a>, Option<NameBinding<'a>>)>,
10511051
multi_segment_macro_resolutions:
10521052
Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>, Option<Res>)>,
10531053
builtin_attrs: Vec<(Ident, ParentScope<'a>)>,

compiler/rustc_resolve/src/macros.rs

+40-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust;
1515
use rustc_attr::StabilityLevel;
1616
use rustc_data_structures::intern::Interned;
1717
use rustc_data_structures::sync::Lrc;
18-
use rustc_errors::{struct_span_err, Applicability};
18+
use rustc_errors::{struct_span_err, Applicability, FatalError};
1919
use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand};
2020
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
2121
use rustc_expand::compile_declarative_macro;
@@ -373,6 +373,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
373373
match self.resolve_macro_path(
374374
path,
375375
Some(MacroKind::Derive),
376+
false,
376377
&parent_scope,
377378
true,
378379
force,
@@ -504,8 +505,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
504505
force: bool,
505506
soft_custom_inner_attributes_gate: bool,
506507
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
507-
let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force)
508-
{
508+
let (ext, res) = match self.resolve_macro_path(
509+
path,
510+
Some(kind),
511+
inner_attr,
512+
parent_scope,
513+
true,
514+
force,
515+
) {
509516
Ok((Some(ext), res)) => (ext, res),
510517
Ok((None, res)) => (self.dummy_ext(kind), res),
511518
Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
@@ -627,6 +634,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
627634
&mut self,
628635
path: &ast::Path,
629636
kind: Option<MacroKind>,
637+
inner_attr: bool,
630638
parent_scope: &ParentScope<'a>,
631639
trace: bool,
632640
force: bool,
@@ -685,6 +693,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
685693
self.single_segment_macro_resolutions.push((
686694
path[0].ident,
687695
kind,
696+
inner_attr,
688697
*parent_scope,
689698
binding.ok(),
690699
));
@@ -794,7 +803,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
794803
}
795804

796805
let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions);
797-
for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
806+
let mut has_reported_inner_attr_error = false;
807+
let mut raise_fatal_error = false;
808+
for (ident, kind, inner_attr, parent_scope, initial_binding) in macro_resolutions {
798809
match self.early_resolve_ident_in_lexical_scope(
799810
ident,
800811
ScopeSet::Macro(kind),
@@ -810,7 +821,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
810821
});
811822
let res = binding.res();
812823
let seg = Segment::from_ident(ident);
813-
check_consistency(self, &[seg], ident.span, kind, initial_res, res);
824+
if has_reported_inner_attr_error
825+
&& let Res::Def(DefKind::Macro(MacroKind::Attr), _) = res
826+
&& let None = initial_res
827+
{
828+
// Do not emit an indeterminate resolution and later errors when an outer
829+
// attribute wasn't found, as this can be knock down effects. #118455
830+
raise_fatal_error = true;
831+
} else {
832+
let res = binding.res();
833+
check_consistency(self, &[seg], ident.span, kind, initial_res, res);
834+
};
814835
if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) {
815836
let node_id = self
816837
.invocation_parents
@@ -825,7 +846,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
825846
);
826847
}
827848
}
828-
Err(..) => {
849+
Err(_) => {
850+
if inner_attr {
851+
has_reported_inner_attr_error = true;
852+
}
829853
let expected = kind.descr_expected();
830854

831855
let mut err = self.tcx.sess.create_err(CannotFindIdentInThisScope {
@@ -851,6 +875,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
851875
None,
852876
);
853877
}
878+
879+
if raise_fatal_error {
880+
// When we encounter an inner attribute failure, and subsequent successful macro
881+
// resolutions following early resolution failures. This is so when an outer attribute
882+
// isn't found, and we encounter `derive` attributes, we won't raise errors caused by
883+
// any code that relies on those derives having been evaluated. We don't attempt to
884+
// recover because the behavior of those derives could have been modified by the outer
885+
// attribute, causing *other* errors, so it is safest to just stop early instead.
886+
FatalError.raise();
887+
}
854888
}
855889

856890
fn check_stability_and_deprecation(

tests/ui/proc-macro/derive-helper-legacy-spurious.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
#[macro_use]
66
extern crate test_macros;
77

8-
#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive`
8+
#[derive(Empty, Clone)] // no error emitted here
99
#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
1010
struct Foo {}
1111

12-
fn main() {}
12+
fn main() {
13+
let _ = Foo.clone(); // no error emitted here
14+
}

tests/ui/proc-macro/derive-helper-legacy-spurious.stderr

+1-9
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,11 @@ error: cannot find attribute `dummy` in this scope
44
LL | #![dummy]
55
| ^^^^^
66

7-
error: cannot determine resolution for the attribute macro `derive`
8-
--> $DIR/derive-helper-legacy-spurious.rs:8:3
9-
|
10-
LL | #[derive(Empty)]
11-
| ^^^^^^
12-
|
13-
= note: import resolution is stuck, try simplifying macro imports
14-
157
error: cannot find attribute `empty_helper` in this scope
168
--> $DIR/derive-helper-legacy-spurious.rs:9:3
179
|
1810
LL | #[empty_helper]
1911
| ^^^^^^^^^^^^
2012

21-
error: aborting due to 3 previous errors
13+
error: aborting due to 2 previous errors
2214

0 commit comments

Comments
 (0)