Skip to content

Commit 5c89b70

Browse files
committed
Supress unhelpful diagnostics for unresolved top level attributes
1 parent 04521fd commit 5c89b70

35 files changed

+189
-282
lines changed

compiler/rustc_attr/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ attr_incorrect_repr_format_generic =
3434
attr_incorrect_repr_format_packed_one_or_zero_arg =
3535
incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
3636
37+
attr_invalid_attr_at_crate_level =
38+
`{$name}` attribute cannot be used at crate level
39+
.suggestion = perhaps you meant to use an outer attribute
40+
41+
attr_invalid_attr_at_crate_level_item =
42+
the inner attribute doesn't annotate this {$kind}
3743
attr_invalid_issue_string =
3844
`issue` must be a non-zero numeric string or "none"
3945
.must_not_be_zero = `issue` must not be "0", use "none" instead

compiler/rustc_attr/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ pub use StabilityLevel::*;
2525
pub use rustc_ast::attr::*;
2626

2727
pub(crate) use rustc_session::HashStableContext;
28+
pub use session_diagnostics::{InvalidAttrAtCrateLevel, ItemFollowingInnerAttr};
2829

2930
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

compiler/rustc_attr/src/session_diagnostics.rs

+37
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,40 @@ pub(crate) struct UnknownVersionLiteral {
390390
#[primary_span]
391391
pub span: Span,
392392
}
393+
394+
pub struct InvalidAttrAtCrateLevel {
395+
pub span: Span,
396+
pub sugg_span: Option<Span>,
397+
pub name: Symbol,
398+
pub item: Option<ItemFollowingInnerAttr>,
399+
}
400+
401+
#[derive(Clone, Copy)]
402+
pub struct ItemFollowingInnerAttr {
403+
pub span: Span,
404+
pub kind: &'static str,
405+
}
406+
407+
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel {
408+
#[track_caller]
409+
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
410+
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_invalid_attr_at_crate_level);
411+
diag.set_span(self.span);
412+
diag.set_arg("name", self.name);
413+
// Only emit an error with a suggestion if we can create a string out
414+
// of the attribute span
415+
if let Some(span) = self.sugg_span {
416+
diag.span_suggestion_verbose(
417+
span,
418+
fluent::attr_suggestion,
419+
String::new(),
420+
Applicability::MachineApplicable,
421+
);
422+
}
423+
if let Some(item) = self.item {
424+
diag.set_arg("kind", item.kind);
425+
diag.span_label(item.span, fluent::attr_invalid_attr_at_crate_level_item);
426+
}
427+
diag
428+
}
429+
}

compiler/rustc_passes/messages.ftl

-7
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,6 @@ passes_inline_not_fn_or_closure =
389389
passes_inner_crate_level_attr =
390390
crate-level attribute should be in the root module
391391
392-
passes_invalid_attr_at_crate_level =
393-
`{$name}` attribute cannot be used at crate level
394-
.suggestion = perhaps you meant to use an outer attribute
395-
396-
passes_invalid_attr_at_crate_level_item =
397-
the inner attribute doesn't annotate this {$kind}
398-
399392
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
400393
401394
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments

compiler/rustc_passes/src/check_attr.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -2503,12 +2503,8 @@ fn is_c_like_enum(item: &Item<'_>) -> bool {
25032503
}
25042504
}
25052505

2506-
// FIXME: Fix "Cannot determine resolution" error and remove built-in macros
2507-
// from this check.
2506+
// Built-in macros will be checked in resolve.
25082507
fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
2509-
// Check for builtin attributes at the crate level
2510-
// which were unsuccessfully resolved due to cannot determine
2511-
// resolution for the attribute macro error.
25122508
const ATTRS_TO_CHECK: &[Symbol] = &[
25132509
sym::macro_export,
25142510
sym::repr,
@@ -2517,11 +2513,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
25172513
sym::start,
25182514
sym::rustc_main,
25192515
sym::unix_sigpipe,
2520-
sym::derive,
2521-
sym::test,
2522-
sym::test_case,
2523-
sym::global_allocator,
2524-
sym::bench,
25252516
];
25262517

25272518
for attr in attrs {
@@ -2535,11 +2526,11 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
25352526
.items()
25362527
.map(|id| tcx.hir().item(id))
25372528
.find(|item| !item.span.is_dummy()) // Skip prelude `use`s
2538-
.map(|item| errors::ItemFollowingInnerAttr {
2529+
.map(|item| rustc_attr::ItemFollowingInnerAttr {
25392530
span: item.ident.span,
25402531
kind: item.kind.descr(),
25412532
});
2542-
tcx.dcx().emit_err(errors::InvalidAttrAtCrateLevel {
2533+
tcx.dcx().emit_err(rustc_attr::InvalidAttrAtCrateLevel {
25432534
span: attr.span,
25442535
sugg_span: tcx
25452536
.sess

compiler/rustc_passes/src/errors.rs

-38
Original file line numberDiff line numberDiff line change
@@ -856,44 +856,6 @@ pub struct UnknownLangItem {
856856
pub name: Symbol,
857857
}
858858

859-
pub struct InvalidAttrAtCrateLevel {
860-
pub span: Span,
861-
pub sugg_span: Option<Span>,
862-
pub name: Symbol,
863-
pub item: Option<ItemFollowingInnerAttr>,
864-
}
865-
866-
#[derive(Clone, Copy)]
867-
pub struct ItemFollowingInnerAttr {
868-
pub span: Span,
869-
pub kind: &'static str,
870-
}
871-
872-
impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel {
873-
#[track_caller]
874-
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
875-
let mut diag =
876-
DiagnosticBuilder::new(dcx, level, fluent::passes_invalid_attr_at_crate_level);
877-
diag.span(self.span);
878-
diag.arg("name", self.name);
879-
// Only emit an error with a suggestion if we can create a string out
880-
// of the attribute span
881-
if let Some(span) = self.sugg_span {
882-
diag.span_suggestion_verbose(
883-
span,
884-
fluent::passes_suggestion,
885-
String::new(),
886-
Applicability::MachineApplicable,
887-
);
888-
}
889-
if let Some(item) = self.item {
890-
diag.arg("kind", item.kind);
891-
diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item);
892-
}
893-
diag
894-
}
895-
}
896-
897859
#[derive(Diagnostic)]
898860
#[diag(passes_duplicate_diagnostic_item_in_crate)]
899861
pub struct DuplicateDiagnosticItemInCrate {

compiler/rustc_resolve/src/errors.rs

+13
Original file line numberDiff line numberDiff line change
@@ -787,3 +787,16 @@ pub(crate) struct IsNotDirectlyImportable {
787787
pub(crate) span: Span,
788788
pub(crate) target: Ident,
789789
}
790+
791+
#[derive(Subdiagnostic)]
792+
#[suggestion(
793+
resolve_suggestion,
794+
code = "",
795+
applicability = "machine-applicable",
796+
style = "verbose"
797+
)]
798+
pub(crate) struct InvalidAttrSugg {
799+
#[primary_span]
800+
pub(crate) span: Span,
801+
pub(crate) name: Symbol,
802+
}

compiler/rustc_resolve/src/macros.rs

+50-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use crate::{BuiltinMacroState, Determinacy, MacroData};
1010
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
1111
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
1212
use rustc_ast::expand::StrippedCfgItem;
13-
use rustc_ast::{self as ast, attr, Crate, Inline, ItemKind, ModKind, NodeId};
13+
use rustc_ast::{
14+
self as ast, attr, AttrStyle, Attribute, Crate, Inline, ItemKind, ModKind, NodeId,
15+
};
1416
use rustc_ast_pretty::pprust;
1517
use rustc_attr::StabilityLevel;
1618
use rustc_data_structures::intern::Interned;
@@ -35,7 +37,7 @@ use rustc_span::edition::Edition;
3537
use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
3638
use rustc_span::hygiene::{AstPass, MacroKind};
3739
use rustc_span::symbol::{kw, sym, Ident, Symbol};
38-
use rustc_span::{Span, DUMMY_SP};
40+
use rustc_span::{BytePos, Span, DUMMY_SP};
3941
use std::cell::Cell;
4042
use std::mem;
4143

@@ -689,6 +691,32 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
689691
res.map(|res| (self.get_macro(res).map(|macro_data| macro_data.ext.clone()), res))
690692
}
691693

694+
fn report_invalid_crate_level_attr(&mut self, attrs: &[Attribute], name: Symbol) -> bool {
695+
for attr in attrs.iter().filter(|attr| attr.style == AttrStyle::Inner) {
696+
if attr.has_name(name) {
697+
let tcx = self.tcx;
698+
tcx.dcx().emit_err(rustc_attr::InvalidAttrAtCrateLevel {
699+
span: attr.span,
700+
sugg_span: tcx
701+
.sess
702+
.source_map()
703+
.span_to_snippet(attr.span)
704+
.ok()
705+
.filter(|src| src.starts_with("#!["))
706+
.map(|_| {
707+
attr.span
708+
.with_lo(attr.span.lo() + BytePos(1))
709+
.with_hi(attr.span.lo() + BytePos(2))
710+
}),
711+
name,
712+
item: None,
713+
});
714+
return true;
715+
}
716+
}
717+
false
718+
}
719+
692720
pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
693721
let check_consistency = |this: &mut Self,
694722
path: &[Segment],
@@ -708,15 +736,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
708736
// expanded into a dummy fragment for recovery during expansion.
709737
// Now, post-expansion, the resolution may succeed, but we can't change the
710738
// past and need to report an error.
711-
// However, non-speculative `resolve_path` can successfully return private items
739+
// Special cases:
740+
// 1. non-speculative `resolve_path` can successfully return private items
712741
// even if speculative `resolve_path` returned nothing previously, so we skip this
713742
// less informative error if the privacy error is reported elsewhere.
743+
// 2. issue #118455, unresolved top level attribute error didn't imported prelude and
744+
// already have emitted an error, report builtin macro and attributes error by the way,
745+
// so `check_invalid_crate_level_attr` in can ignore them.
746+
714747
if this.privacy_errors.is_empty() {
715-
this.dcx().emit_err(CannotDetermineMacroResolution {
716-
span,
717-
kind: kind.descr(),
718-
path: Segment::names_to_string(path),
719-
});
748+
if this.is_builtin_macro(res)
749+
|| this.builtin_attrs_bindings.values().any(|b| b.res() == res)
750+
{
751+
if !this.report_invalid_crate_level_attr(&krate.attrs, path[0].ident.name) {
752+
return;
753+
}
754+
if this.tcx.dcx().has_errors().is_none() {
755+
this.dcx().emit_err(CannotDetermineMacroResolution {
756+
span,
757+
kind: kind.descr(),
758+
path: Segment::names_to_string(path),
759+
});
760+
}
761+
}
720762
}
721763
}
722764
};

tests/ui/derives/issue-36617.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
#![derive(Copy)] //~ ERROR cannot determine resolution for the attribute macro `derive`
1+
#![derive(Copy)]
22
//~^ ERROR `derive` attribute cannot be used at crate level
33

4-
#![test]//~ ERROR cannot determine resolution for the attribute macro `test`
4+
#![test]
55
//~^ ERROR `test` attribute cannot be used at crate level
66

7-
#![test_case]//~ ERROR cannot determine resolution for the attribute macro `test_case`
7+
#![test_case]
88
//~^ ERROR `test_case` attribute cannot be used at crate level
99

10-
#![bench]//~ ERROR cannot determine resolution for the attribute macro `bench`
10+
#![bench]
1111
//~^ ERROR `bench` attribute cannot be used at crate level
1212

13-
#![global_allocator]//~ ERROR cannot determine resolution for the attribute macro `global_allocator`
13+
#![global_allocator]
1414
//~^ ERROR `global_allocator` attribute cannot be used at crate level
1515

1616
fn main() {}

tests/ui/derives/issue-36617.stderr

+1-56
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,8 @@
1-
error: cannot determine resolution for the attribute macro `derive`
2-
--> $DIR/issue-36617.rs:1:4
3-
|
4-
LL | #![derive(Copy)]
5-
| ^^^^^^
6-
|
7-
= note: import resolution is stuck, try simplifying macro imports
8-
9-
error: cannot determine resolution for the attribute macro `test`
10-
--> $DIR/issue-36617.rs:4:4
11-
|
12-
LL | #![test]
13-
| ^^^^
14-
|
15-
= note: import resolution is stuck, try simplifying macro imports
16-
17-
error: cannot determine resolution for the attribute macro `test_case`
18-
--> $DIR/issue-36617.rs:7:4
19-
|
20-
LL | #![test_case]
21-
| ^^^^^^^^^
22-
|
23-
= note: import resolution is stuck, try simplifying macro imports
24-
25-
error: cannot determine resolution for the attribute macro `bench`
26-
--> $DIR/issue-36617.rs:10:4
27-
|
28-
LL | #![bench]
29-
| ^^^^^
30-
|
31-
= note: import resolution is stuck, try simplifying macro imports
32-
33-
error: cannot determine resolution for the attribute macro `global_allocator`
34-
--> $DIR/issue-36617.rs:13:4
35-
|
36-
LL | #![global_allocator]
37-
| ^^^^^^^^^^^^^^^^
38-
|
39-
= note: import resolution is stuck, try simplifying macro imports
40-
411
error: `derive` attribute cannot be used at crate level
422
--> $DIR/issue-36617.rs:1:1
433
|
444
LL | #![derive(Copy)]
455
| ^^^^^^^^^^^^^^^^
46-
...
47-
LL | fn main() {}
48-
| ---- the inner attribute doesn't annotate this function
496
|
507
help: perhaps you meant to use an outer attribute
518
|
@@ -58,9 +15,6 @@ error: `test` attribute cannot be used at crate level
5815
|
5916
LL | #![test]
6017
| ^^^^^^^^
61-
...
62-
LL | fn main() {}
63-
| ---- the inner attribute doesn't annotate this function
6418
|
6519
help: perhaps you meant to use an outer attribute
6620
|
@@ -73,9 +27,6 @@ error: `test_case` attribute cannot be used at crate level
7327
|
7428
LL | #![test_case]
7529
| ^^^^^^^^^^^^^
76-
...
77-
LL | fn main() {}
78-
| ---- the inner attribute doesn't annotate this function
7930
|
8031
help: perhaps you meant to use an outer attribute
8132
|
@@ -88,9 +39,6 @@ error: `bench` attribute cannot be used at crate level
8839
|
8940
LL | #![bench]
9041
| ^^^^^^^^^
91-
...
92-
LL | fn main() {}
93-
| ---- the inner attribute doesn't annotate this function
9442
|
9543
help: perhaps you meant to use an outer attribute
9644
|
@@ -103,15 +51,12 @@ error: `global_allocator` attribute cannot be used at crate level
10351
|
10452
LL | #![global_allocator]
10553
| ^^^^^^^^^^^^^^^^^^^^
106-
...
107-
LL | fn main() {}
108-
| ---- the inner attribute doesn't annotate this function
10954
|
11055
help: perhaps you meant to use an outer attribute
11156
|
11257
LL - #![global_allocator]
11358
LL + #[global_allocator]
11459
|
11560

116-
error: aborting due to 10 previous errors
61+
error: aborting due to 5 previous errors
11762

tests/ui/extenv/issue-55897.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ mod unresolved_env {
44
use env; //~ ERROR unresolved import `env`
55

66
include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
7-
//~^ ERROR cannot determine resolution for the macro `env`
87
}
98

109
mod nonexistent_env {

0 commit comments

Comments
 (0)