Skip to content

Commit

Permalink
Supress unhelpful diagnostics for unresolved top level attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Dec 2, 2023
1 parent df0295f commit 6a9456f
Show file tree
Hide file tree
Showing 29 changed files with 139 additions and 233 deletions.
11 changes: 1 addition & 10 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2495,12 +2495,8 @@ fn is_c_like_enum(item: &Item<'_>) -> bool {
}
}

// FIXME: Fix "Cannot determine resolution" error and remove built-in macros
// from this check.
// builtin macros will be checked in resolve
fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
// Check for builtin attributes at the crate level
// which were unsuccessfully resolved due to cannot determine
// resolution for the attribute macro error.
const ATTRS_TO_CHECK: &[Symbol] = &[
sym::macro_export,
sym::repr,
Expand All @@ -2509,11 +2505,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
sym::start,
sym::rustc_main,
sym::unix_sigpipe,
sym::derive,
sym::test,
sym::test_case,
sym::global_allocator,
sym::bench,
];

for attr in attrs {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ resolve_invalid_asm_sym =
.label = is a local variable
.help = `sym` operands must refer to either a function or a static
resolve_invalid_attr_at_crate_level =
`{$name}` attribute cannot be used at crate level
.suggestion = perhaps you meant to use an outer attribute
resolve_is_not_directly_importable =
`{$target}` is not directly importable
.label = cannot be imported directly
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,3 +771,26 @@ pub(crate) struct IsNotDirectlyImportable {
pub(crate) span: Span,
pub(crate) target: Ident,
}

#[derive(Diagnostic)]
#[diag(resolve_invalid_attr_at_crate_level)]
pub struct InvalidAttrAtCrateLevel {
#[primary_span]
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
pub(crate) sugg: InvalidAttrSugg,
}

#[derive(Subdiagnostic)]
#[suggestion(
resolve_suggestion,
code = "",
applicability = "machine-applicable",
style = "verbose"
)]
pub(crate) struct InvalidAttrSugg {
#[primary_span]
pub(crate) span: Span,
pub(crate) name: Symbol,
}
7 changes: 7 additions & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name.is_some())
}

fn is_builtin(&mut self, res: Res) -> bool {
if self.is_builtin_macro(res) {
return true;
}
self.builtin_attrs_bindings.values().any(|b| b.res() == res)
}

fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
loop {
match ctxt.outer_expn_data().macro_def_id {
Expand Down
57 changes: 51 additions & 6 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! A bunch of methods and structures more or less related to resolving macros and
//! interface provided by `Resolver` to macro expander.

use crate::ast::AttrStyle;
use crate::ast::Attribute;
use crate::errors::{
self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
MacroExpectedFound, RemoveSurroundingDerive,
Expand Down Expand Up @@ -35,6 +37,7 @@ use rustc_span::edition::Edition;
use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::hygiene::{AstPass, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::BytePos;
use rustc_span::{Span, DUMMY_SP};
use std::cell::Cell;
use std::mem;
Expand Down Expand Up @@ -698,6 +701,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
res.map(|res| (self.get_macro(res).map(|macro_data| macro_data.ext.clone()), res))
}

fn report_invalid_crate_level_attr(&mut self, attrs: &[Attribute], name: Symbol) -> bool {
for attr in attrs.iter().filter(|attr| attr.style == AttrStyle::Inner) {
if attr.has_name(name) {
let tcx = self.tcx;
tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel {
name,
span: attr.span,
sugg: errors::InvalidAttrSugg {
span: tcx
.sess
.source_map()
.span_to_snippet(attr.span)
.ok()
.filter(|src| src.starts_with("#!["))
.map(|_| {
attr.span
.with_lo(attr.span.lo() + BytePos(1))
.with_hi(attr.span.lo() + BytePos(2))
})
.unwrap(),
name,
},
});
return true;
}
}
false
}

pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
let check_consistency = |this: &mut Self,
path: &[Segment],
Expand All @@ -717,15 +749,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// expanded into a dummy fragment for recovery during expansion.
// Now, post-expansion, the resolution may succeed, but we can't change the
// past and need to report an error.
// However, non-speculative `resolve_path` can successfully return private items
// Special cases:
// 1. non-speculative `resolve_path` can successfully return private items
// even if speculative `resolve_path` returned nothing previously, so we skip this
// less informative error if the privacy error is reported elsewhere.
// 2. issue #118455, unresolved top level attribute error didn't imported prelude and
// already have emitted an error, report builtin macro and attributes error by the way,
// so `check_invalid_crate_level_attr` in can ignore them.

let is_builtin = res.opt_def_id().map_or(false, |_| this.is_builtin(res));
if this.privacy_errors.is_empty() {
this.tcx.sess.emit_err(CannotDetermineMacroResolution {
span,
kind: kind.descr(),
path: Segment::names_to_string(path),
});
let mut fallback = !is_builtin;
if is_builtin && krate.id == ast::CRATE_NODE_ID {
fallback =
!this.report_invalid_crate_level_attr(&krate.attrs, path[0].ident.name);
}
if fallback && this.tcx.sess.has_errors().is_none() {
this.tcx.sess.emit_err(CannotDetermineMacroResolution {
span,
kind: kind.descr(),
path: Segment::names_to_string(path),
});
}
}
}
};
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/derives/issue-36617.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
#![derive(Copy)] //~ ERROR cannot determine resolution for the attribute macro `derive`
#![derive(Copy)]
//~^ ERROR `derive` attribute cannot be used at crate level

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

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

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

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

fn main() {}
57 changes: 1 addition & 56 deletions tests/ui/derives/issue-36617.stderr
Original file line number Diff line number Diff line change
@@ -1,51 +1,8 @@
error: cannot determine resolution for the attribute macro `derive`
--> $DIR/issue-36617.rs:1:4
|
LL | #![derive(Copy)]
| ^^^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the attribute macro `test`
--> $DIR/issue-36617.rs:4:4
|
LL | #![test]
| ^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the attribute macro `test_case`
--> $DIR/issue-36617.rs:7:4
|
LL | #![test_case]
| ^^^^^^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the attribute macro `bench`
--> $DIR/issue-36617.rs:10:4
|
LL | #![bench]
| ^^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: cannot determine resolution for the attribute macro `global_allocator`
--> $DIR/issue-36617.rs:13:4
|
LL | #![global_allocator]
| ^^^^^^^^^^^^^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: `derive` attribute cannot be used at crate level
--> $DIR/issue-36617.rs:1:1
|
LL | #![derive(Copy)]
| ^^^^^^^^^^^^^^^^
...
LL | fn main() {}
| ---- the inner attribute doesn't annotate this function
|
help: perhaps you meant to use an outer attribute
|
Expand All @@ -58,9 +15,6 @@ error: `test` attribute cannot be used at crate level
|
LL | #![test]
| ^^^^^^^^
...
LL | fn main() {}
| ---- the inner attribute doesn't annotate this function
|
help: perhaps you meant to use an outer attribute
|
Expand All @@ -73,9 +27,6 @@ error: `test_case` attribute cannot be used at crate level
|
LL | #![test_case]
| ^^^^^^^^^^^^^
...
LL | fn main() {}
| ---- the inner attribute doesn't annotate this function
|
help: perhaps you meant to use an outer attribute
|
Expand All @@ -88,9 +39,6 @@ error: `bench` attribute cannot be used at crate level
|
LL | #![bench]
| ^^^^^^^^^
...
LL | fn main() {}
| ---- the inner attribute doesn't annotate this function
|
help: perhaps you meant to use an outer attribute
|
Expand All @@ -103,15 +51,12 @@ error: `global_allocator` attribute cannot be used at crate level
|
LL | #![global_allocator]
| ^^^^^^^^^^^^^^^^^^^^
...
LL | fn main() {}
| ---- the inner attribute doesn't annotate this function
|
help: perhaps you meant to use an outer attribute
|
LL - #![global_allocator]
LL + #[global_allocator]
|

error: aborting due to 10 previous errors
error: aborting due to 5 previous errors

1 change: 0 additions & 1 deletion tests/ui/extenv/issue-55897.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ mod unresolved_env {
use env; //~ ERROR unresolved import `env`

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

mod nonexistent_env {
Expand Down
14 changes: 3 additions & 11 deletions tests/ui/extenv/issue-55897.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: environment variable `NON_EXISTENT` not defined at compile time
--> $DIR/issue-55897.rs:11:22
--> $DIR/issue-55897.rs:10:22
|
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
| ^^^^^^^^^^^^^^^^^^^^
Expand All @@ -8,7 +8,7 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)

error: suffixes on string literals are invalid
--> $DIR/issue-55897.rs:16:22
--> $DIR/issue-55897.rs:15:22
|
LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs"));
| ^^^^^^^^^^^^^^^^^^^^ invalid suffix `suffix`
Expand All @@ -33,14 +33,6 @@ help: consider importing this module instead
LL | use std::env;
| ~~~~~~~~

error: cannot determine resolution for the macro `env`
--> $DIR/issue-55897.rs:6:22
|
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
| ^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0432`.
6 changes: 2 additions & 4 deletions tests/ui/feature-gates/issue-43106-gating-of-bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
// handled in "weird places" when `--test` is passed.

#![feature(custom_inner_attributes)]

#![bench = "4100"]
//~^ ERROR cannot determine resolution for the attribute macro `bench`
//~^^ ERROR `bench` attribute cannot be used at crate level
#![bench = "4100"]
//~^ ERROR `bench` attribute cannot be used at crate level
fn main() {}
23 changes: 6 additions & 17 deletions tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
error: cannot determine resolution for the attribute macro `bench`
--> $DIR/issue-43106-gating-of-bench.rs:7:4
|
LL | #![bench = "4100"]
| ^^^^^
|
= note: import resolution is stuck, try simplifying macro imports

error: `bench` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-bench.rs:7:1
--> $DIR/issue-43106-gating-of-bench.rs:6:1
|
LL | #![bench = "4100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | fn main() {}
| ---- the inner attribute doesn't annotate this function
LL | #![bench = "4100"]
| ^^^^^^^^^^^^^^^^^^
|
help: perhaps you meant to use an outer attribute
|
LL - #![bench = "4100"]
LL + #[bench = "4100"]
LL - #![bench = "4100"]
LL + #[bench = "4100"]
|

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

5 changes: 2 additions & 3 deletions tests/ui/feature-gates/issue-43106-gating-of-test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs.

#![allow(soft_unstable)]
#![test = "4200"]
//~^ ERROR cannot determine resolution for the attribute macro `test`
//~^^ ERROR `test` attribute cannot be used at crate level
#![test = "4200"]
//~^ ERROR `test` attribute cannot be used at crate level
fn main() {}
Loading

0 comments on commit 6a9456f

Please sign in to comment.