-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[WIP] Skip single use lifetime lint for generated opaque types #78004
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
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @matthewjasper (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
I'm working on adding more tests for different cases |
@sapessi since this is WIP, do you want to mark it as a draft PR? |
Yes please. I thought it was final but then as I was working I realized that this opened a larger question (see my last comment in the issue). There are cases where the lifetime only appears once in the async method signature but the linter does not throw the error because the lifetime is reused in the desugared generator - the behavior could be counter-intuitive for developers who do not see the desugared hir. We could treat the desugared opaque type for async methods as a completely different scope as far as lifetime linting is concerned and prevent a single-use lifetime from halting compilation since this code is outside of developers' control |
Oops, sorry about that! Apparently I can. |
Old error output: = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap this expression in parentheses | 4 | break '_l $f(;) | ^ ^ New error output: = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap this expression in parentheses | 4 | break '_l ($f); | ^ ^
Forbid inline const block referencing params from being used in patterns Fix #82518
Old error output: 3 | let _: usize = $f; | ----- ^ expected `usize`, found struct `Baz` | | | expected due to this New error output: 3 | let _: usize = $f; | ----- ^^ expected `usize`, found struct `Baz` | | | expected due to this
Make `-Z gcc-ld=lld` work for Apple targets `-Z gcc-ld=lld` was introduced in #85961. It does not work on Macos because lld needs be either named `ld64` or passed `-flavor darwin` as the first two arguments in order to select the Mach-O flavor. Rust invokes cc (=clang) on Macos for linking which calls `ld` as linker binary and not `ld64`, so just creating an `ld64` binary and modifying the search path with `-B` does not work. In order to solve this patch does: * Set the `lld_flavor` for all Apple-derived targets to `LldFlavor::Ld64`. As far as I can see this actually works towards fixing `-Xlinker=rust-lld` as all those targets use the Mach-O object format. * Copy/hardlink rust-lld to the gcc-ld subdirectory as ld64 next to ld. * If `-Z gcc-ld=lld` is used and the target lld flavor is Ld64 add `-fuse-ld=/path/to/ld64` to the linker invocation. Fixes #86945.
Update the stdarch submodule This notably brings in a number of codegen updates to ensure that wasm simd intrinsics generate the expected instruction with LLVM 13
When calling a method requiring a mutable self borrow on an inmutable to a mutable borrow of the type, suggest making the binding mutable. Fix #83241.
Treat types in unnormalized function signatures as well-formed Fixes #87748 r? `@nikomatsakis`
ast_lowering: Introduce `lower_span` for catching all spans entering HIR This PR cherry-picks the `fn lower_span` change from #84373. I also introduced `fn lower_ident` for lowering spans in identifiers, and audited places where HIR structures with spans or identifiers are constructed and added a few missing `lower_span`s/`lower_ident`s. Having a hook for spans entering HIR can be useful for things other than #84373, e.g. #35148. I also want to check whether this change causes perf regressions due to some accidental inlining issues. r? `@cjgillot`
Refactor unsized suggestions `@rustbot` label +A-diagnostics +A-traits +A-typesystem +C-cleanup +T-compiler
Add an example for deriving PartialOrd on enums For some reason, I always forget which variants are smaller and which are larger when you derive PartialOrd on an enum. And the wording in the current docs is not entirely clear to me. So, I often end up making a small enum, deriving PartialOrd on it, and then writing a `#[test]` with an assert that the top one is smaller than the bottom one (or the other way around) to figure out which way the deriving goes. So then I figured, it would be great if the standard library docs just had that example, so if I keep forgetting, at least I can figure it out quickly by looking at std's docs.
…=petrochenkov Fix LLVM libunwind build for non-musl targets Broken in #85600. AFAICT, [only musl, mingw, and wasm](https://github.com/rust-lang/rust/blob/673d0db5e393e9c64897005b470bfeb6d5aec61b/compiler/rustc_target/src/spec/crt_objects.rs#L128-L132) should use the “self-contained” logic in rustbuild.
small const generics cleanup
remove redundant / misplaced sentence from docs Removes sentence that seems to have drifted down into the examples section. Luckily, someone already added an explanation of what happens with packed structs back into the initial section of the doc entry and this wayward sentence can likely just be deleted.
Update outdated docs of array::IntoIter::new.
Update primitive docs for rust 2021. Fixes #87701
Rollup of 7 pull requests Successful merges: - #88202 (Add an example for deriving PartialOrd on enums) - #88483 (Fix LLVM libunwind build for non-musl targets) - #88507 (Add test case for using `slice::fill` with MaybeUninit) - #88557 (small const generics cleanup) - #88579 (remove redundant / misplaced sentence from docs) - #88610 (Update outdated docs of array::IntoIter::new.) - #88613 (Update primitive docs for rust 2021.) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Move global analyses from lowering to resolution Split off #87234 r? `@petrochenkov`
sunos systems add sanitizer supported.
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.
The changes look reasonable to me! Do you still want to tackle this?
Left some nitpicks to reduce righwards drift of the code.
// opaque types generated when desugaring an async function can have a single | ||
// use lifetime even if it is explicitly denied (Issue #77175) | ||
if let hir::Node::Item(item) = self.tcx.hir().get(parent_hir_id) { | ||
if let hir::ItemKind::OpaqueTy(ref opaque) = item.kind { | ||
if opaque.origin == hir::OpaqueTyOrigin::AsyncFn { | ||
// We want to do this only if the liftime identifier is already defined | ||
// in the async function that generated this. Otherwise it could be | ||
// an opaque type defined by the developer and we still want this | ||
// lint to fail compilation | ||
for p in opaque.generics.params { | ||
if defined_by.contains_key(&p.name) { | ||
continue 'lifetimes; | ||
} | ||
} | ||
} | ||
} | ||
} |
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.
// opaque types generated when desugaring an async function can have a single | |
// use lifetime even if it is explicitly denied (Issue #77175) | |
if let hir::Node::Item(item) = self.tcx.hir().get(parent_hir_id) { | |
if let hir::ItemKind::OpaqueTy(ref opaque) = item.kind { | |
if opaque.origin == hir::OpaqueTyOrigin::AsyncFn { | |
// We want to do this only if the liftime identifier is already defined | |
// in the async function that generated this. Otherwise it could be | |
// an opaque type defined by the developer and we still want this | |
// lint to fail compilation | |
for p in opaque.generics.params { | |
if defined_by.contains_key(&p.name) { | |
continue 'lifetimes; | |
} | |
} | |
} | |
} | |
} | |
// opaque types generated when desugaring an async function can have a single | |
// use lifetime even if it is explicitly denied (Issue #77175) | |
if let hir::Node::Item(hir::Item { | |
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { | |
origin: hir::OpaqueTyOrigin::AsyncFn, | |
.. | |
}), | |
.. | |
}) = self.tcx.hir().get(parent_hir_id) { | |
// We want to do this only if the liftime identifier is already defined | |
// in the async function that generated this. Otherwise it could be | |
// an opaque type defined by the developer and we still want this | |
// lint to fail compilation | |
for p in opaque.generics.params { | |
if defined_by.contains_key(&p.name) { | |
continue 'lifetimes; | |
} | |
} | |
} |
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.
Taken your suggestion with some minor changes because I need the opaque type while trying to prevent rightwards drift
src/test/ui/lifetimes/issue-77175.rs
Outdated
// edition:2018 | ||
// check-pass | ||
|
||
// error: lifetime parameter `'a` only used once |
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.
Change this to make it clear that this was the previously emitted error that shouldn't happen.
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.
Added more comprehensive comment
// in the async function that generated this. Otherwise it could be | ||
// an opaque type defined by the developer and we still want this | ||
// lint to fail compilation | ||
for p in opaque.generics.params { |
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.
I wonder if it makes sense to build an FxHashSet
from these to make the amortized cost linear, but that's likely gold-plating.
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 mean storing the parameters for the Generic
type in an FxHashSet
instead of an array?
Apologies for the radio silence - life and work have been pretty crazy. I would love to pick this up again. I'll be back online in a couple of weeks and I'll address your feedback, @estebank. Thank you! |
Fix drop handling for `if let` expressions MIR lowering for `if let` expressions is now more complicated now that `if let` exists in HIR. This PR adds a scope for the variables bound in an `if let` expression and then uses an approach similar to how we handle loops to ensure that we reliably drop the correct variables. Closes #88307 cc `@flip1995` `@richkadel` `@c410-f3r`
Add regression test for a spurious import This PR adds a test that verifies that the bug described in the linked issue does not creep back into the code. In essence it checks that compiling some specific code (that uses 128 bit multiplication) with a specific set of compiler options does not lead to a spurious import of a panic function. I noticed that other wasm tests use `# only-wasm32-bare` in their `Makefile`. This will skip the test for me. I did not find out how to run this test locally. Maybe someone can help. closes #78744 r? `@jyn514`
As reported in issue #77175, the opaque type generated by the desugaring process of an async function uses the lifetimes defined by the originating function. The definition ID for the lifetimes in the opaque method is different from the one in the originating async function and it could therefore be considered a single use of the lifetimne, this causes the single_use_lifetimes lint to fail compilation if explicitly denied. This fix skips the lint for lifetimes used only once in generated opaque types for an async function that are declared in the parent async function definition
To add historical context on the issue
to prevent rightwards drift of the code
@sapessi rust-lang/rust follows a "No-Merge Policy", so please rebase over master instead of merging it in. Thanks! |
Also, it seems like Git got confused and thinks this PR has 10,000 commits. I think rebasing may fix that. |
Yup, just realized this happened, must have forgotten the |
You could also |
Attempted to rebase from upstream. It's gotten really confused. I cannot figure out where it thinks those 1K commits came from. Easier to start from scratch. I'll reference the new PR from here |
New PR is #88650. Closing this one and apologies for the git mess |
Fix: #77175
The opaque type generated by the desugaring process of an async function uses the lifetimes defined by the originating function. The
DefId
for the lifetimes in the opaque type are different from the ones in the originating async function - as they should be, as far as I understand, and could therefore be considered a single use lifetimes, this causes thesingle_use_lifetimes
lint to fail compilation if explicitly denied. This fix skips the lint for lifetimes used only once in generated opaque types for an async function that are declared in the parent async function definition.More info in the comments on the original issue: 1 and 2