Skip to content

Commit c4250ac

Browse files
committed
Supress unhelpful diagnostics for unresolved top level attributes
1 parent 090d5ea commit c4250ac

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

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
@@ -850,44 +850,6 @@ pub struct UnknownLangItem {
850850
pub name: Symbol,
851851
}
852852

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

compiler/rustc_resolve/src/errors.rs

+13
Original file line numberDiff line numberDiff line change
@@ -778,3 +778,16 @@ pub(crate) struct IsNotDirectlyImportable {
778778
pub(crate) span: Span,
779779
pub(crate) target: Ident,
780780
}
781+
782+
#[derive(Subdiagnostic)]
783+
#[suggestion(
784+
resolve_suggestion,
785+
code = "",
786+
applicability = "machine-applicable",
787+
style = "verbose"
788+
)]
789+
pub(crate) struct InvalidAttrSugg {
790+
#[primary_span]
791+
pub(crate) span: Span,
792+
pub(crate) name: Symbol,
793+
}

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

@@ -695,6 +697,32 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
695697
res.map(|res| (self.get_macro(res).map(|macro_data| macro_data.ext.clone()), res))
696698
}
697699

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

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)