-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
hygiene: Decouple transparencies from expansion IDs #51952
Conversation
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
r? @oli-obk |
Needs check-only crater run (stable derives are affected). |
@bors try |
hygiene: Decouple transparencies from expansion IDs Fixes #50504 in accordance with [this comment](#50504 (comment)).
@@ -284,22 +285,31 @@ impl SyntaxContext { | |||
}) | |||
} | |||
|
|||
/// Extend a syntax context with a given mark |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you lost a doc comment
#[proc_macro] | ||
pub fn check(_: TokenStream) -> TokenStream { | ||
" | ||
struct Outer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you check that we can still access things outside the expansion here?
" | ||
struct Outer; | ||
mod inner { | ||
type Inner = Outer; // `Outer` shouldn't be available from here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and that we cannot access anything from outside the expansion without an import
☀️ Test successful - status-travis |
cc @pietroalbini check-only crater run wanted (details are in the crater status spreadsheet already). |
Crater run started. It should finish in ~2 days. |
Hi @petrochenkov (crater requester), @oli-obk (PR reviewer)! Crater results are at: http://cargobomb-reports.s3.amazonaws.com/pr-51952/index.html. 'Blacklisted' crates (spurious failures etc) can be found here. If you see any spurious failures not on the list, please make a PR against that file. (interested observers: Crater is a tool for testing the impact of changes on the crates.io ecosystem. You can find out more at the repo if you're curious) |
52 crates regressed. Seems both actix and diesel are broken by this. Dependency treeThe tool used to build the tree is not perfect, the tree might be a bit off. It only includes registry crates.
|
The common pattern is #[derive(Something)]
struct MyStruct; being expanded into struct MyStruct;
mod __implementation_details {
// Note, that `MyStruct` is not in scope here.
impl Something for MyStruct {
let x: SomethingElseFromTheParentModule = ...;
}
} The "universal solution" is to do this: mod __implementation_details {
use super::*; // <---
// Now `MyStruct` and `SomethingElseFromTheParentModule ` are in scope.
impl Something for MyStruct {
let x: SomethingElseFromTheParentModule = ...;
}
} Perhaps we can send fixes, release minor versions and land this fix. |
Thanks for investigating @petrochenkov! Out of curiosity, is it possible to apply this fix for just In any case I think we should send fixes upstream and publish ASAP. Hopefully that'll buy us as many possibilities as we can to fix this! |
Alternative "universal solution": fn __implementation_details() {
impl Something for MyStruct {
let x: SomethingElseFromTheParentModule = ...;
}
} This may look silly, but this may be even better solution for encapsulating implementation details than introducing a module (which acts as a "name barrier") and thus losing names in scope, including those that can't be recovered with For example, fn outer() {
#[derive(Something)]
struct MyStruct;
} |
This should be possible to do with a targeted hack, if I'm not mistaken about the root cause of the bug. |
These are all consequences of rushed stabilization of macros 1.1 and low "bus factor" for hygiene system (not enough qualified reviewing was done). |
While I appreciate where you're coming from, stability should not mean "unless we decide we change our minds". I agree with you that this is something that should have been discussed before the feature became stable in the first place, but that does not mean that it should be OK for the rug to get pulled out from under the ecosystem on a stable feature. |
@sgrif did diesel or any other crates you know of stop compiling as a result of this change? This change was landed under the presumption that nothing was broken and crates continued to compile, if that's not the case we should fix that! If crates continued to compile, however, then I think it's a bit disingenous to say that the rug was pulled out from under you or that this is a major breaking change. This fixed bug exhibits behavior which is clearly a bug in procedural macros which has affected stable Rust for quite some time. We always try quite hard to keep crates compiling on stable. This does not mean that we will prevent ourselves from fixing bugs though as we're doing in this situation. We are tasked, however, with fixing the bug while keeping existing code compiling. |
@sgrif |
Yes, Diesel did. You also listed a ton of affected crates in #50504 (comment). Again, I think calling it a "fixed bug" is quite arguable. Personally I'd expect hygiene to mean that a given ident is resolved in the scope it was given from. My main point is that I don't think it's an obvious conclusion one way or the other, and I would have liked to see a discussion around it.
I agree. But there does become a point when folks start relying on behavior enough that there is a conversation to be had about whether fixing the "bug" does more harm than good (there are several cases like this in Rails for example). At a certain point something in the grey area ends up being a defacto feature. I think it's also important to define what "bug" means here. I couldn't find anything in the relevant RFCs which explicitly defines how this behavior should interact. At best this is a clarification of intent, but given that it's on a stable feature, I don't think that should be done without giving the community an opportunity to voice their opinion.
I agree. I do not think this is obviously a bug. It's also much more nuanced than you are making it out to be, see my above comments. |
@sgrif so to be clear, diesel compiled on stable, and then the exact same source code no longer compiles on nightly? I'm not talking about warnings, but literal compiler errors. The crater report you gisted is not even tied to this change, so I'd just want to be clear about what breaking is. If it's broken, can you also gist the error message you're getting? (steps to reproduce would also be great!) I agree there's possibility for a gray area, but I disagree that this is not obviously a bug. All of macros 1.1 is "call site" hygiene which is "as if the tokens are copy/pasted". That's clearly not the case when you're generating |
Most published versions of Diesel were shipped with
I linked to a discussion on the issue closed by this PR, not sure how it's unrelated. Pretty much every crate there is generating a module for the same reason -- to be able to have an isolated scope for
This is a fair point. Really there's a broader issue here is that proc macros (and derives in particular) have no way to isolate their scope, and want to do things that don't have obvious interactions with hygiene (such as |
I think this is what was specified in the RFC for 1.1 and announcement for 1.2, yes. |
@sgrif our stability policy does not consider new warnings or changes to warnings a breaking change due to The crater report you linked was a blanket denial of all procedural macros generating There is many many issues with procedural macros and how they do not have many hygiene controls, they're forced to just splat tokens into the user's program. These problems are well-known though and the solution is under development but is still not ready for stabilization. |
I understand that. This is not just a new default warn lint. This is a warning for what will end up being a breaking change. It also doesn't really matter in terms of the impact that this has on downstream crates. If someones build starts spamming warnings, we still get multiple reports a day (the most recent versions of Diesel do not
I looked through about half of them, and every single one I looked at is going to be affected by this change. As I said in my previous comment, there is very little reason to emit a module from a
Has there been an RFC for this? This is my main point. This is a stable feature, and it really feels like things about it are just being changed with no input from the community. |
Regardless of anything else, I hope you understand the frustration here. A lot of folks use Diesel with Rocket or other crates that require nightly, so we tend to feel pains from that pretty quick. Users on older versions that still had |
Sorry :( |
Even if we're able to allow it, that's at best a temporary fix. At the end of the day this is a compatibility warning for something that will be breaking eventually -- meaning that any version of Diesel (or any other affected crate) that doesn't handle it will stop working. Saying that this isn't a breaking change because it's a warning, or that there'll be a fix that lets us silence the warning is seriously sidestepping the issue here. From a library maintainer's point of view, being told "your code will stop working" is no different from it not working. My concern is both with the lack of a working migration path, but also with this happening at all. I understand that this is considered to be a bug by the relevant teams. However, I really don't think enough consideration has been given to existing code. @alexcrichton directly said:
Since the only code that's going to stop compiling is code using |
@sgrif yes I'm sorry that Diesel is going through these troubles, this particular migration could probably have gone more smoothly! The warnings here were intended to be like all other future incompatibility warnings the compiler issues: they don't break existing code (modulo lint denial) and they are supressable in the near term if necessary. The migration path here was thought to be simple enough but it wasn't exercised for Diesel's case specifically and you've discovered there's a bug or two which prevents a feasible migration path, but we'll work on that! The compiler has a well documented policy on how to fix a bug in the compiler. It appears we accidentally left out the tracking issue part of that, but otherwise that policy was followed. To reiterate some motivation of that policy, no future-incompatible compiler warning is turned into an error, ever, if enough of the ecosystem is still using it. We would never consider turning this into a hard error unless Diesel had successfully migrated to no longer have the warning issued. I disagree with your point of "is no different from it not working", this is the crucial distinction. |
Attach deprecation lint `proc_macro_derive_resolution_fallback` to a specific node id So it can be `allow`-ed from inside the derive. cc #51952
This resolves a warning introduced in rust-lang/rust#51952 that will eventually become a hard error, the latter of which is being tracked in rust-lang/rust#50504.
Stabilize a few secondary macro features - `tool_attributes` - closes rust-lang#44690 - `proc_macro_path_invoc` - this feature was created due to issues with tool attributes (rust-lang#51277), those issues are now fixed (rust-lang#52841) - partially `proc_macro_gen` - this feature was created due to issue rust-lang#50504, the issue is now fixed (rust-lang#51952), so proc macros can generate modules. They still can't generate `macro_rules` items though due to unclear hygiene interactions.
Stabilize a few secondary macro features - `tool_attributes` - closes #44690 - `proc_macro_path_invoc` - this feature was created due to issues with tool attributes (#51277), those issues are now fixed (#52841) - partially `proc_macro_gen` - this feature was created due to issue #50504, the issue is now fixed (#51952), so proc macros can generate modules. They still can't generate `macro_rules` items though due to unclear hygiene interactions.
And remove fallback to parent modules during resolution of names in scope.
This is a breaking change for users of unstable macros 2.0 (both procedural and declarative), code like this:
or equivalent
stops working due to module boundaries being properly enforced.
For proc macro derives this is still reported as a compatibility warning to give
actix_derive
,diesel_derives
andpalette_derive
time to fix their issues.Fixes #50504 in accordance with this comment.