Skip to content

Commit 5fa1347

Browse files
committed
Revert "Make PROC_MACRO_DERIVE_RESOLUTION_FALLBACK a hard error"
This reverts commit 7d82cad. I am doing this to buy us some time with respect to issue rust-lang#106337 w.r.t. the 1.67 release.
1 parent 5ce39f4 commit 5fa1347

File tree

6 files changed

+238
-49
lines changed

6 files changed

+238
-49
lines changed

Diff for: compiler/rustc_lint_defs/src/builtin.rs

+68
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,73 @@ declare_lint! {
20232023
};
20242024
}
20252025

2026+
declare_lint! {
2027+
/// The `proc_macro_derive_resolution_fallback` lint detects proc macro
2028+
/// derives using inaccessible names from parent modules.
2029+
///
2030+
/// ### Example
2031+
///
2032+
/// ```rust,ignore (proc-macro)
2033+
/// // foo.rs
2034+
/// #![crate_type = "proc-macro"]
2035+
///
2036+
/// extern crate proc_macro;
2037+
///
2038+
/// use proc_macro::*;
2039+
///
2040+
/// #[proc_macro_derive(Foo)]
2041+
/// pub fn foo1(a: TokenStream) -> TokenStream {
2042+
/// drop(a);
2043+
/// "mod __bar { static mut BAR: Option<Something> = None; }".parse().unwrap()
2044+
/// }
2045+
/// ```
2046+
///
2047+
/// ```rust,ignore (needs-dependency)
2048+
/// // bar.rs
2049+
/// #[macro_use]
2050+
/// extern crate foo;
2051+
///
2052+
/// struct Something;
2053+
///
2054+
/// #[derive(Foo)]
2055+
/// struct Another;
2056+
///
2057+
/// fn main() {}
2058+
/// ```
2059+
///
2060+
/// This will produce:
2061+
///
2062+
/// ```text
2063+
/// warning: cannot find type `Something` in this scope
2064+
/// --> src/main.rs:8:10
2065+
/// |
2066+
/// 8 | #[derive(Foo)]
2067+
/// | ^^^ names from parent modules are not accessible without an explicit import
2068+
/// |
2069+
/// = note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default
2070+
/// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
2071+
/// = note: for more information, see issue #50504 <https://github.com/rust-lang/rust/issues/50504>
2072+
/// ```
2073+
///
2074+
/// ### Explanation
2075+
///
2076+
/// If a proc-macro generates a module, the compiler unintentionally
2077+
/// allowed items in that module to refer to items in the crate root
2078+
/// without importing them. This is a [future-incompatible] lint to
2079+
/// transition this to a hard error in the future. See [issue #50504] for
2080+
/// more details.
2081+
///
2082+
/// [issue #50504]: https://github.com/rust-lang/rust/issues/50504
2083+
/// [future-incompatible]: ../index.md#future-incompatible-lints
2084+
pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
2085+
Deny,
2086+
"detects proc macro derives using inaccessible names from parent modules",
2087+
@future_incompatible = FutureIncompatibleInfo {
2088+
reference: "issue #83583 <https://github.com/rust-lang/rust/issues/83583>",
2089+
reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
2090+
};
2091+
}
2092+
20262093
declare_lint! {
20272094
/// The `macro_use_extern_crate` lint detects the use of the
20282095
/// [`macro_use` attribute].
@@ -3261,6 +3328,7 @@ declare_lint_pass! {
32613328
UNSTABLE_NAME_COLLISIONS,
32623329
IRREFUTABLE_LET_PATTERNS,
32633330
WHERE_CLAUSES_OBJECT_SAFETY,
3331+
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
32643332
MACRO_USE_EXTERN_CRATE,
32653333
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
32663334
ILL_FORMED_ATTRIBUTE_INPUT,

Diff for: compiler/rustc_resolve/src/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ impl<'a> Resolver<'a> {
10331033
let root_module = this.resolve_crate_root(root_ident);
10341034
this.add_module_candidates(root_module, &mut suggestions, filter_fn, None);
10351035
}
1036-
Scope::Module(module) => {
1036+
Scope::Module(module, _) => {
10371037
this.add_module_candidates(module, &mut suggestions, filter_fn, None);
10381038
}
10391039
Scope::MacroUsePrelude => {

Diff for: compiler/rustc_resolve/src/ident.rs

+65-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use rustc_ast as ast;
1+
use rustc_ast::{self as ast, NodeId};
22
use rustc_feature::is_builtin_attr_name;
33
use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
44
use rustc_hir::PrimTy;
55
use rustc_middle::bug;
66
use rustc_middle::ty;
7+
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
8+
use rustc_session::lint::BuiltinLintDiagnostics;
79
use rustc_span::def_id::LocalDefId;
810
use rustc_span::edition::Edition;
911
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
@@ -99,7 +101,7 @@ impl<'a> Resolver<'a> {
99101
};
100102
let mut scope = match ns {
101103
_ if is_absolute_path => Scope::CrateRoot,
102-
TypeNS | ValueNS => Scope::Module(module),
104+
TypeNS | ValueNS => Scope::Module(module, None),
103105
MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
104106
};
105107
let mut ctxt = ctxt.normalize_to_macros_2_0();
@@ -163,7 +165,7 @@ impl<'a> Resolver<'a> {
163165
MacroRulesScope::Invocation(invoc_id) => {
164166
Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules)
165167
}
166-
MacroRulesScope::Empty => Scope::Module(module),
168+
MacroRulesScope::Empty => Scope::Module(module, None),
167169
},
168170
Scope::CrateRoot => match ns {
169171
TypeNS => {
@@ -172,10 +174,16 @@ impl<'a> Resolver<'a> {
172174
}
173175
ValueNS | MacroNS => break,
174176
},
175-
Scope::Module(module) => {
177+
Scope::Module(module, prev_lint_id) => {
176178
use_prelude = !module.no_implicit_prelude;
177-
match self.hygienic_lexical_parent(module, &mut ctxt) {
178-
Some(parent_module) => Scope::Module(parent_module),
179+
let derive_fallback_lint_id = match scope_set {
180+
ScopeSet::Late(.., lint_id) => lint_id,
181+
_ => None,
182+
};
183+
match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) {
184+
Some((parent_module, lint_id)) => {
185+
Scope::Module(parent_module, lint_id.or(prev_lint_id))
186+
}
179187
None => {
180188
ctxt.adjust(ExpnId::root());
181189
match ns {
@@ -207,13 +215,45 @@ impl<'a> Resolver<'a> {
207215
&mut self,
208216
module: Module<'a>,
209217
ctxt: &mut SyntaxContext,
210-
) -> Option<Module<'a>> {
218+
derive_fallback_lint_id: Option<NodeId>,
219+
) -> Option<(Module<'a>, Option<NodeId>)> {
211220
if !module.expansion.outer_expn_is_descendant_of(*ctxt) {
212-
return Some(self.expn_def_scope(ctxt.remove_mark()));
221+
return Some((self.expn_def_scope(ctxt.remove_mark()), None));
213222
}
214223

215224
if let ModuleKind::Block = module.kind {
216-
return Some(module.parent.unwrap().nearest_item_scope());
225+
return Some((module.parent.unwrap().nearest_item_scope(), None));
226+
}
227+
228+
// We need to support the next case under a deprecation warning
229+
// ```
230+
// struct MyStruct;
231+
// ---- begin: this comes from a proc macro derive
232+
// mod implementation_details {
233+
// // Note that `MyStruct` is not in scope here.
234+
// impl SomeTrait for MyStruct { ... }
235+
// }
236+
// ---- end
237+
// ```
238+
// So we have to fall back to the module's parent during lexical resolution in this case.
239+
if derive_fallback_lint_id.is_some() {
240+
if let Some(parent) = module.parent {
241+
// Inner module is inside the macro, parent module is outside of the macro.
242+
if module.expansion != parent.expansion
243+
&& module.expansion.is_descendant_of(parent.expansion)
244+
{
245+
// The macro is a proc macro derive
246+
if let Some(def_id) = module.expansion.expn_data().macro_def_id {
247+
let ext = self.get_macro_by_def_id(def_id).ext;
248+
if ext.builtin_name.is_none()
249+
&& ext.macro_kind() == MacroKind::Derive
250+
&& parent.expansion.outer_expn_is_descendant_of(*ctxt)
251+
{
252+
return Some((parent, derive_fallback_lint_id));
253+
}
254+
}
255+
}
256+
}
217257
}
218258

219259
None
@@ -470,7 +510,7 @@ impl<'a> Resolver<'a> {
470510
Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
471511
}
472512
}
473-
Scope::Module(module) => {
513+
Scope::Module(module, derive_fallback_lint_id) => {
474514
let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
475515
let binding = this.resolve_ident_in_module_unadjusted_ext(
476516
ModuleOrUniformRoot::Module(module),
@@ -483,6 +523,21 @@ impl<'a> Resolver<'a> {
483523
);
484524
match binding {
485525
Ok(binding) => {
526+
if let Some(lint_id) = derive_fallback_lint_id {
527+
this.lint_buffer.buffer_lint_with_diagnostic(
528+
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
529+
lint_id,
530+
orig_ident.span,
531+
&format!(
532+
"cannot find {} `{}` in this scope",
533+
ns.descr(),
534+
ident
535+
),
536+
BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(
537+
orig_ident.span,
538+
),
539+
);
540+
}
486541
let misc_flags = if ptr::eq(module, this.graph_root) {
487542
Flags::MISC_SUGGEST_CRATE
488543
} else if module.is_normal() {

Diff for: compiler/rustc_resolve/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ enum Scope<'a> {
105105
DeriveHelpersCompat,
106106
MacroRules(MacroRulesScopeRef<'a>),
107107
CrateRoot,
108-
Module(Module<'a>),
108+
// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK`
109+
// lint if it should be reported.
110+
Module(Module<'a>, Option<NodeId>),
109111
MacroUsePrelude,
110112
BuiltinAttrs,
111113
ExternPrelude,
@@ -1591,7 +1593,7 @@ impl<'a> Resolver<'a> {
15911593

15921594
self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| {
15931595
match scope {
1594-
Scope::Module(module) => {
1596+
Scope::Module(module, _) => {
15951597
this.traits_in_module(module, assoc_item, &mut found_traits);
15961598
}
15971599
Scope::StdLibPrelude => {

Diff for: tests/ui/proc-macro/generate-mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@ struct S;
1515

1616
#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope
1717
//~| ERROR cannot find type `OuterDerive` in this scope
18+
//~| WARN this was previously accepted
19+
//~| WARN this was previously accepted
1820
struct Z;
1921

2022
fn inner_block() {
2123
#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope
2224
//~| ERROR cannot find type `OuterDerive` in this scope
25+
//~| WARN this was previously accepted
26+
//~| WARN this was previously accepted
2327
struct InnerZ;
2428
}
2529

26-
#[derive(generate_mod::CheckDeriveLint)] //~ ERROR cannot find type `OuterDeriveLint` in this scope
27-
//~| ERROR cannot find type `FromOutside` in this scope
30+
#[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
2831
struct W;
2932

3033
fn main() {}

0 commit comments

Comments
 (0)