Make PROC_MACRO_DERIVE_RESOLUTION_FALLBACK a hard error

This commit is contained in:
Aaron Hill 2022-10-04 19:02:13 -05:00
parent 1481fd964b
commit 7d82cadd97
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
6 changed files with 54 additions and 243 deletions

View File

@ -1982,73 +1982,6 @@ declare_lint! {
}; };
} }
declare_lint! {
/// The `proc_macro_derive_resolution_fallback` lint detects proc macro
/// derives using inaccessible names from parent modules.
///
/// ### Example
///
/// ```rust,ignore (proc-macro)
/// // foo.rs
/// #![crate_type = "proc-macro"]
///
/// extern crate proc_macro;
///
/// use proc_macro::*;
///
/// #[proc_macro_derive(Foo)]
/// pub fn foo1(a: TokenStream) -> TokenStream {
/// drop(a);
/// "mod __bar { static mut BAR: Option<Something> = None; }".parse().unwrap()
/// }
/// ```
///
/// ```rust,ignore (needs-dependency)
/// // bar.rs
/// #[macro_use]
/// extern crate foo;
///
/// struct Something;
///
/// #[derive(Foo)]
/// struct Another;
///
/// fn main() {}
/// ```
///
/// This will produce:
///
/// ```text
/// warning: cannot find type `Something` in this scope
/// --> src/main.rs:8:10
/// |
/// 8 | #[derive(Foo)]
/// | ^^^ names from parent modules are not accessible without an explicit import
/// |
/// = note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default
/// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
/// = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
/// ```
///
/// ### Explanation
///
/// If a proc-macro generates a module, the compiler unintentionally
/// allowed items in that module to refer to items in the crate root
/// without importing them. This is a [future-incompatible] lint to
/// transition this to a hard error in the future. See [issue #50504] for
/// more details.
///
/// [issue #50504]: https://github.com/rust-lang/rust/issues/50504
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
Deny,
"detects proc macro derives using inaccessible names from parent modules",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #83583 <https://github.com/rust-lang/rust/issues/83583>",
reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
};
}
declare_lint! { declare_lint! {
/// The `macro_use_extern_crate` lint detects the use of the /// The `macro_use_extern_crate` lint detects the use of the
/// [`macro_use` attribute]. /// [`macro_use` attribute].
@ -3287,7 +3220,6 @@ declare_lint_pass! {
UNSTABLE_NAME_COLLISIONS, UNSTABLE_NAME_COLLISIONS,
IRREFUTABLE_LET_PATTERNS, IRREFUTABLE_LET_PATTERNS,
WHERE_CLAUSES_OBJECT_SAFETY, WHERE_CLAUSES_OBJECT_SAFETY,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
MACRO_USE_EXTERN_CRATE, MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
ILL_FORMED_ATTRIBUTE_INPUT, ILL_FORMED_ATTRIBUTE_INPUT,

View File

@ -1186,7 +1186,7 @@ impl<'a> Resolver<'a> {
let root_module = this.resolve_crate_root(root_ident); let root_module = this.resolve_crate_root(root_ident);
this.add_module_candidates(root_module, &mut suggestions, filter_fn, None); this.add_module_candidates(root_module, &mut suggestions, filter_fn, None);
} }
Scope::Module(module, _) => { Scope::Module(module) => {
this.add_module_candidates(module, &mut suggestions, filter_fn, None); this.add_module_candidates(module, &mut suggestions, filter_fn, None);
} }
Scope::MacroUsePrelude => { Scope::MacroUsePrelude => {

View File

@ -1,11 +1,9 @@
use rustc_ast::{self as ast, NodeId}; use rustc_ast as ast;
use rustc_feature::is_builtin_attr_name; use rustc_feature::is_builtin_attr_name;
use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
use rustc_hir::PrimTy; use rustc_hir::PrimTy;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext}; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
@ -101,7 +99,7 @@ impl<'a> Resolver<'a> {
}; };
let mut scope = match ns { let mut scope = match ns {
_ if is_absolute_path => Scope::CrateRoot, _ if is_absolute_path => Scope::CrateRoot,
TypeNS | ValueNS => Scope::Module(module, None), TypeNS | ValueNS => Scope::Module(module),
MacroNS => Scope::DeriveHelpers(parent_scope.expansion), MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
}; };
let mut ctxt = ctxt.normalize_to_macros_2_0(); let mut ctxt = ctxt.normalize_to_macros_2_0();
@ -165,7 +163,7 @@ impl<'a> Resolver<'a> {
MacroRulesScope::Invocation(invoc_id) => { MacroRulesScope::Invocation(invoc_id) => {
Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules) Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules)
} }
MacroRulesScope::Empty => Scope::Module(module, None), MacroRulesScope::Empty => Scope::Module(module),
}, },
Scope::CrateRoot => match ns { Scope::CrateRoot => match ns {
TypeNS => { TypeNS => {
@ -174,16 +172,10 @@ impl<'a> Resolver<'a> {
} }
ValueNS | MacroNS => break, ValueNS | MacroNS => break,
}, },
Scope::Module(module, prev_lint_id) => { Scope::Module(module) => {
use_prelude = !module.no_implicit_prelude; use_prelude = !module.no_implicit_prelude;
let derive_fallback_lint_id = match scope_set { match self.hygienic_lexical_parent(module, &mut ctxt) {
ScopeSet::Late(.., lint_id) => lint_id, Some(parent_module) => Scope::Module(parent_module),
_ => None,
};
match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) {
Some((parent_module, lint_id)) => {
Scope::Module(parent_module, lint_id.or(prev_lint_id))
}
None => { None => {
ctxt.adjust(ExpnId::root()); ctxt.adjust(ExpnId::root());
match ns { match ns {
@ -215,45 +207,13 @@ impl<'a> Resolver<'a> {
&mut self, &mut self,
module: Module<'a>, module: Module<'a>,
ctxt: &mut SyntaxContext, ctxt: &mut SyntaxContext,
derive_fallback_lint_id: Option<NodeId>, ) -> Option<Module<'a>> {
) -> Option<(Module<'a>, Option<NodeId>)> {
if !module.expansion.outer_expn_is_descendant_of(*ctxt) { if !module.expansion.outer_expn_is_descendant_of(*ctxt) {
return Some((self.expn_def_scope(ctxt.remove_mark()), None)); return Some(self.expn_def_scope(ctxt.remove_mark()));
} }
if let ModuleKind::Block = module.kind { if let ModuleKind::Block = module.kind {
return Some((module.parent.unwrap().nearest_item_scope(), None)); return Some(module.parent.unwrap().nearest_item_scope());
}
// We need to support the next case under a deprecation warning
// ```
// struct MyStruct;
// ---- begin: this comes from a proc macro derive
// mod implementation_details {
// // Note that `MyStruct` is not in scope here.
// impl SomeTrait for MyStruct { ... }
// }
// ---- end
// ```
// So we have to fall back to the module's parent during lexical resolution in this case.
if derive_fallback_lint_id.is_some() {
if let Some(parent) = module.parent {
// Inner module is inside the macro, parent module is outside of the macro.
if module.expansion != parent.expansion
&& module.expansion.is_descendant_of(parent.expansion)
{
// The macro is a proc macro derive
if let Some(def_id) = module.expansion.expn_data().macro_def_id {
let ext = self.get_macro_by_def_id(def_id).ext;
if ext.builtin_name.is_none()
&& ext.macro_kind() == MacroKind::Derive
&& parent.expansion.outer_expn_is_descendant_of(*ctxt)
{
return Some((parent, derive_fallback_lint_id));
}
}
}
}
} }
None None
@ -510,7 +470,7 @@ impl<'a> Resolver<'a> {
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
} }
} }
Scope::Module(module, derive_fallback_lint_id) => { Scope::Module(module) => {
let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
let binding = this.resolve_ident_in_module_unadjusted_ext( let binding = this.resolve_ident_in_module_unadjusted_ext(
ModuleOrUniformRoot::Module(module), ModuleOrUniformRoot::Module(module),
@ -523,21 +483,6 @@ impl<'a> Resolver<'a> {
); );
match binding { match binding {
Ok(binding) => { Ok(binding) => {
if let Some(lint_id) = derive_fallback_lint_id {
this.lint_buffer.buffer_lint_with_diagnostic(
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
lint_id,
orig_ident.span,
&format!(
"cannot find {} `{}` in this scope",
ns.descr(),
ident
),
BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(
orig_ident.span,
),
);
}
let misc_flags = if ptr::eq(module, this.graph_root) { let misc_flags = if ptr::eq(module, this.graph_root) {
Flags::MISC_SUGGEST_CRATE Flags::MISC_SUGGEST_CRATE
} else if module.is_normal() { } else if module.is_normal() {

View File

@ -102,9 +102,7 @@ enum Scope<'a> {
DeriveHelpersCompat, DeriveHelpersCompat,
MacroRules(MacroRulesScopeRef<'a>), MacroRules(MacroRulesScopeRef<'a>),
CrateRoot, CrateRoot,
// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` Module(Module<'a>),
// lint if it should be reported.
Module(Module<'a>, Option<NodeId>),
MacroUsePrelude, MacroUsePrelude,
BuiltinAttrs, BuiltinAttrs,
ExternPrelude, ExternPrelude,
@ -1551,7 +1549,7 @@ impl<'a> Resolver<'a> {
self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| { self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| {
match scope { match scope {
Scope::Module(module, _) => { Scope::Module(module) => {
this.traits_in_module(module, assoc_item, &mut found_traits); this.traits_in_module(module, assoc_item, &mut found_traits);
} }
Scope::StdLibPrelude => { Scope::StdLibPrelude => {

View File

@ -15,19 +15,16 @@ struct S;
#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope #[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope
//~| ERROR cannot find type `OuterDerive` in this scope //~| ERROR cannot find type `OuterDerive` in this scope
//~| WARN this was previously accepted
//~| WARN this was previously accepted
struct Z; struct Z;
fn inner_block() { fn inner_block() {
#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope #[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope
//~| ERROR cannot find type `OuterDerive` in this scope //~| ERROR cannot find type `OuterDerive` in this scope
//~| WARN this was previously accepted
//~| WARN this was previously accepted
struct InnerZ; struct InnerZ;
} }
#[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed #[derive(generate_mod::CheckDeriveLint)] //~ ERROR cannot find type `OuterDeriveLint` in this scope
//~| ERROR cannot find type `FromOutside` in this scope
struct W; struct W;
fn main() {} fn main() {}

View File

@ -38,127 +38,66 @@ LL | #[generate_mod::check_attr]
OuterAttr OuterAttr
= note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find type `FromOutside` in this scope error[E0412]: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:16:10 --> $DIR/generate-mod.rs:16:10
| |
LL | #[derive(generate_mod::CheckDerive)] LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | ^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: consider importing this struct:
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> FromOutside
= note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find type `OuterDerive` in this scope error[E0412]: cannot find type `OuterDerive` in this scope
--> $DIR/generate-mod.rs:16:10 --> $DIR/generate-mod.rs:16:10
| |
LL | #[derive(generate_mod::CheckDerive)] LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | ^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: consider importing this struct:
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> OuterDerive
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find type `FromOutside` in this scope error[E0412]: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:23:14 --> $DIR/generate-mod.rs:21:14
| |
LL | #[derive(generate_mod::CheckDerive)] LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | ^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: consider importing this struct:
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> FromOutside
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find type `OuterDerive` in this scope error[E0412]: cannot find type `OuterDerive` in this scope
--> $DIR/generate-mod.rs:23:14 --> $DIR/generate-mod.rs:21:14
| |
LL | #[derive(generate_mod::CheckDerive)] LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import | ^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
| |
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: consider importing this struct:
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583> OuterDerive
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 8 previous errors error[E0412]: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:26:10
|
LL | #[derive(generate_mod::CheckDeriveLint)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
= note: consider importing this struct:
FromOutside
= note: this error originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0412]: cannot find type `OuterDeriveLint` in this scope
--> $DIR/generate-mod.rs:26:10
|
LL | #[derive(generate_mod::CheckDeriveLint)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
|
= note: consider importing this struct:
OuterDeriveLint
= note: this error originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0412`. For more information about this error, try `rustc --explain E0412`.
Future incompatibility report: Future breakage diagnostic:
error: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:16:10
|
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
error: cannot find type `OuterDerive` in this scope
--> $DIR/generate-mod.rs:16:10
|
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
error: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:23:14
|
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
error: cannot find type `OuterDerive` in this scope
--> $DIR/generate-mod.rs:23:14
|
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
warning: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:30:10
|
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
note: the lint level is defined here
--> $DIR/generate-mod.rs:30:10
|
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
warning: cannot find type `OuterDeriveLint` in this scope
--> $DIR/generate-mod.rs:30:10
|
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
note: the lint level is defined here
--> $DIR/generate-mod.rs:30:10
|
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)