-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking issue for future-incompatibility lint proc_macro_derive_resolution_fallback
#83583
Comments
Following warnings will be ceased: warning: cannot find type `Result` in this scope --> src/members.rs:8:10 | 8 | #[derive(GraphQLQuery)] | ^^^^^^^^^^^^ 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 #83583 <rust-lang/rust#83583> = note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
I'm a bit confused by these; is their presence a rustc bug? It doesn't look like the relevant pattern actually occurs.
I believe this lint has unveiled an unfortunate case in Rust's name resolution behavior for proc macro authors. Enforcing this makes certain proc macros no longer function if used inside of a I originally thought this was a false positive in this lint, but after some digging, it seems like a bug or quirk that I think should be taken into consideration for enforcement of this stabilization lint. Here's a repro case I created under the impression that this was a false positive: https://github.com/LPGhatguy/rustc-issue-83583-false-positive A proc macro that generates a // this is fine!
#[derive(Foo)]
struct Blah; ...but fails if the input struct is defined inside a function: // this trips this deprecation lint
fn item() {
#[derive(Foo)]
struct Blah;
} This appears to be due to a difference in the meaning of For proc macro authors, the solution seems to be to never generate a This commit backlinks to this issue and is an example of the confusion that users may encounter due to this deprecation lint. |
This works around rust-lang/rust#83583 by avoiding generating a mod block. This code previously worked everywhere, but tripped this deprecation lint if Crevice's derives were used on a struct inside a function. In order to have consistent name resolution, we instead blast all the generated functions into the main scope. This is... not great, but there is no other way to let code inside a mod inside a fn refer to other items inside the fn.
Diesel had this issue (as discussed in #51952) and migrated to generating some other code pattern, not using
Users are right to be confused, because the blame is on the authors of |
Thank you for linking the thread. It appears that the Diesel authors found a solution but were not generally happy with this change. It would be nice if proc macro authors had better tools for scope isolation. I only found out about this issue after using a proc macro that had existed for almost two years from within a function. I had no idea that name resolution from modules inside functions worked this way until this warning showed up in my terminal. While there are solutions, and I have now implemented them, they come with trade-offs. For example, one of the solutions from the thread: fn __implementation_details() {
impl Something for MyStruct {
let x: SomethingElseFromTheParentModule = ...;
}
} ...lacks the ability for other code generated from the proc macro to be able to refer to items from within the implementation details scope. This is the perfect use case for a mod, but it's hampered by resolution rules. I'd love to have a way to refer to an ident that comes from a user regardless of being in a sub-mod, like how proc macros work today, but without this warning. Otherwise, Is there a better place to discuss this issue? I figure that going deeper into a conversation about solutions may be out of scope for this issue. |
Yes, it would be good to have something better than the current tools, but it's out of scope for this specific issue. |
The SNAFU procedural macro optionally generates a module that starts with use snafu::prelude::*;
#[derive(Debug, Snafu)]
#[snafu(module)]
struct Foo;
/// ```rust
/// use snafu::prelude::*;
///
/// #[derive(Debug, Snafu)]
/// #[snafu(module)]
/// struct Foo;
/// ```
pub fn dummy() {}
|
Ah, that's because the doctest is added inside of a |
I'm a bit confused by these; is their presence a rustc bug? It doesn't look like the relevant pattern actually occurs.
In case anyone encounters the same problem as @shepmaster (I just did), remember that you can write /// ```rust
/// use snafu::prelude::*;
///
/// #[derive(Debug, Snafu)]
/// #[snafu(module)]
/// struct Foo;
/// # fn main() {}
/// ```
pub fn dummy() {} |
@rustbot label: I-lang-nominated I would like the lang team to discuss the problems that people have encountered from the lint described here, and the language issues that have led them to encounter those problems. In particular, it seems like macro authors would very much like to be able to write code like this (playpen): mod outer {
struct O;
pub fn foo() {
// This type is local to this fn implementation. Furthermore,
// it might have been injected *into* the body of the fn implementation
// by a macro exapnsion. (For example, that is part of what happens
// with doc tests that include struct definitions.) So, we cannot
// try to force the struct definition to live outside of here.
//
// and remember, there may be a derive on this thing too.
#[derive()]
struct FooS;
// This code is macro-generated, e.g. from a derive on FooS.
mod inner {
use super::*; // this use enables us to see `O`, but not `FooS` (!)
fn om(x: O) -> O { x }
// so how can one reference the type `FooS` from here?
#[cfg(this_is_the_code_that_breaks_with_a_resolve_error)]
fn g(f: FooS) -> FooS { f }
}
}
} |
see also #64079, which I think precisely describes the issue I summarized in my playpen example in the previous comment, and which @petrochenkov closed as not-a-bug. (I'm currently trying to figure out when/if T-lang has previously discussed this matter.) |
Okay, @joshtriplett has pointed out to me that one can work around the problem I described in my playpen example by introducing an intermedate module around the struct with the derive on it. I.e. something like this playpen |
See also #84022 which made the deprecation lint here a hard error. (Which, I admit, I signed off on in that issue. I think I did not appreciate the details that were raised on this issue about the problems with code that has been expanded directly within an |
I filed rust-lang/lang-team#193 for the lang team to formally follow up on this. I think that allows us to remove it from the lang-nominated issues @rustbot label: -I-lang-nominated |
I'm a bit confused by these; is their presence a rustc bug? It doesn't look like the relevant pattern actually occurs.
I'm a bit confused by these; is their presence a rustc bug? It doesn't look like the relevant pattern actually occurs.
This works around rust-lang/rust#83583 by avoiding generating a mod block. This code previously worked everywhere, but tripped this deprecation lint if Crevice's derives were used on a struct inside a function. In order to have consistent name resolution, we instead blast all the generated functions into the main scope. This is... not great, but there is no other way to let code inside a mod inside a fn refer to other items inside the fn.
proc_macro_derive_resolution_fallback
proc_macro_derive_resolution_fallback
This is a lint for code like
when it comes from a derive macro.
The code should obviously not compile because
S
is not in scope at its point of use, but before #51952 it compiled if the code was produced by a derive macro, and some popular crates likeactix_derive
,diesel_derives
andpalette_derive
exploited this in the wild.This deprecation lint was added in #51952 as warn-by-default.
The text was updated successfully, but these errors were encountered: