about summary refs log tree commit diff
path: root/compiler
AgeCommit message (Collapse)AuthorLines
2024-12-14Auto merge of #134296 - matthiaskrgr:rollup-o0sxozj, r=matthiaskrgrbors-165/+128
Rollup of 6 pull requests Successful merges: - #132150 (Fix powerpc64 big-endian FreeBSD ABI) - #133942 (Clarify how to use `black_box()`) - #134081 (Try to evaluate constants in legacy mangling) - #134192 (Remove `Lexer`'s dependency on `Parser`.) - #134208 (coverage: Tidy up creation of covmap and covfun records) - #134211 (On Neutrino QNX, reduce the need to set archiver via environment variables) r? `@ghost` `@rustbot` modify labels: rollup
2024-12-14Auto merge of #134185 - compiler-errors:impl-trait-in-bindings, r=oli-obkbors-49/+233
(Re-)Implement `impl_trait_in_bindings` This reimplements the `impl_trait_in_bindings` feature for local bindings. "`impl Trait` in bindings" serve as a form of *trait* ascription, where the type basically functions as an infer var but additionally registering the `impl Trait`'s trait bounds for the infer type. These trait bounds can be used to enforce that predicates hold, and can guide inference (e.g. for closure signature inference): ```rust let _: impl Fn(&u8) -> &u8 = |x| x; ``` They are implemented as an additional set of bounds that are registered when the type is lowered during typeck, and then these bounds are tied to a given `CanonicalUserTypeAscription` for borrowck. We enforce these `CanonicalUserTypeAscription` bounds during borrowck to make sure that the `impl Trait` types are sensitive to lifetimes: ```rust trait Static: 'static {} impl<T> Static for T where T: 'static {} let local = 1; let x: impl Static = &local; //~^ ERROR `local` does not live long enough ``` r? oli-obk cc #63065 --- Why can't we just use TAIT inference or something? Well, TAITs in bodies have the problem that they cannot reference lifetimes local to a body. For example: ```rust type TAIT = impl Display; let local = 0; let x: TAIT = &local; //~^ ERROR `local` does not live long enough ``` That's because TAITs requires us to do *opaque type inference* which is pretty strict, since we need to remap all of the lifetimes of the hidden type to universal regions. This is simply not possible here. --- I consider this part of the "impl trait everywhere" experiment. I'm not certain if this needs yet another lang team experiment.
2024-12-14Auto merge of #134294 - matthiaskrgr:rollup-anh6io8, r=matthiaskrgrbors-17/+51
Rollup of 8 pull requests Successful merges: - #134252 (Fix `Path::is_absolute` on Hermit) - #134254 (Fix building `std` for Hermit after `c_char` change) - #134255 (Update includes in `/library/core/src/error.rs`.) - #134261 (Document the symbol Visibility enum) - #134262 (Arbitrary self types v2: adjust diagnostic.) - #134265 (Rename `ty_def_id` so people will stop using it by accident) - #134271 (Arbitrary self types v2: better feature gate test) - #134274 (Add check-pass test for `&raw`) r? `@ghost` `@rustbot` modify labels: rollup
2024-12-14Rollup merge of #134208 - Zalathar:covmap-covfun, r=compiler-errorsMatthias Krüger-65/+61
coverage: Tidy up creation of covmap and covfun records This is a small follow-up to #134163 that mostly just inlines and renames some variables, and adds a few comments. It also slightly defers the creation of the LLVM value that holds the filename table, to just before the value is needed. --- try-job: x86_64-mingw-2 try-job: dist-x86_64-linux
2024-12-14Rollup merge of #134192 - nnethercote:rm-Lexer-Parser-dep, r=compiler-errorsMatthias Krüger-97/+37
Remove `Lexer`'s dependency on `Parser`. Lexing precedes parsing, as you'd expect: `Lexer` creates a `TokenStream` and `Parser` then parses that `TokenStream`. But, in a horrendous violation of layering abstractions and common sense, `Lexer` depends on `Parser`! The `Lexer::unclosed_delim_err` method does some error recovery that relies on creating a `Parser` to do some post-processing of the `TokenStream` that the `Lexer` just created. This commit just removes `unclosed_delim_err`. This change removes `Lexer`'s dependency on `Parser`, and also means that `lex_token_tree`'s return value can have a more typical form. The cost is slightly worse error messages in two obscure cases, as shown in these tests: - tests/ui/parser/brace-in-let-chain.rs: there is slightly less explanation in this case involving an extra `{`. - tests/ui/parser/diff-markers/unclosed-delims{,-in-macro}.rs: the diff marker detection is no longer supported (because that detection is implemented in the parser). In my opinion this cost is outweighed by the magnitude of the code cleanup. r? ```````@chenyukang```````
2024-12-14Rollup merge of #134081 - oli-obk:push-prpsqxxynxnq, r=BoxyUwUMatthias Krüger-1/+28
Try to evaluate constants in legacy mangling Best reviewed commit by commit. It seems kind of odd to treat literals differently from unevaluated free constants. So let's evaluate those constants and only fall back to `_` rendering if that fails to result in an integral constant
2024-12-14Rollup merge of #132150 - taiki-e:ppc64-freebsd-abi, r=pnkfelixMatthias Krüger-2/+2
Fix powerpc64 big-endian FreeBSD ABI Note that FreeBSD version bump may be reverted due to https://github.com/rust-lang/rust/pull/120869#issuecomment-2438685835. We may want to wait to merge this until that discussion is complete. Fixes https://github.com/rust-lang/rust/pull/120869#discussion_r1813233054 > > PPC64 FreeBSD (ELFv1 and ELFv2, version 13.2) > > It seems odd that ELFv1 and 13.N coexist. > > https://www.freebsd.org/releases/13.0R/relnotes/ > > > powerpc64 switched to ELFv2 ABI at the same time it switched to LLVM. This brings us to a parity with modern Linux distributions. This also makes the binaries from previous FreeBSD versions incompatible with 13.0-RELEASE. Kernel still supports ELFv1, so jails and chroots using older FreeBSD versions are still compatible. [e4399d169acc](https://cgit.freebsd.org/src/commit/?id=e4399d169acc) > > Well, it is also odd that this target claims ELFv2 support since our ABI code does not use ELFv2 on this target. > > https://github.com/rust-lang/rust/blob/be01dabfefd2daa4574b974f571c7852085d60cb/compiler/rustc_target/src/callconv/powerpc64.rs#L102-L111 ````````@rustbot```````` label +O-PowerPC +O-freebsd
2024-12-14(Re-)Implement impl_trait_in_bindingsMichael Goulet-22/+182
2024-12-14Split UserTypeAnnotation to have a kindMichael Goulet-36/+60
2024-12-14Rollup merge of #134265 - compiler-errors:ty_def_id, r=oli-obkMatthias Krüger-16/+16
Rename `ty_def_id` so people will stop using it by accident This function is just for cycle detection, but people keep using it because they think it's the right way of getting the def id from a `Ty` (and I can't blame them necessarily).
2024-12-14Rollup merge of #134262 - adetaylor:revert-diagnostics, r=compiler-errorsMatthias Krüger-1/+23
Arbitrary self types v2: adjust diagnostic. The recently landed PR #132961 to adjust arbitrary self types was a bit overenthusiastic, advising folks to use the new Receiver trait even before it's been stabilized. Revert to the older wording of the lint in such cases. Tracking issue #44874 r? ``@wesleywiser``
2024-12-14Rollup merge of #134261 - bjorn3:document_symbol_visibility, r=lqdMatthias Krüger-0/+12
Document the symbol Visibility enum
2024-12-14Rollup merge of #134256 - krtab:suggestion_overlapping, r=petrochenkovMatthias Krüger-3/+4
Use a more precise span in placeholder_type_error_diag Closes: https://github.com/rust-lang/rust/issues/123861
2024-12-14Rollup merge of #134251 - bjorn3:various_cleanups2, r=oli-obkMatthias Krüger-66/+38
A bunch of cleanups (part 2) Just like https://github.com/rust-lang/rust/pull/133567 these were all found while looking at the respective code, but are not blocking any other changes I want to make in the short term.
2024-12-14Rollup merge of #134244 - Enselic:no-mut-hint-for-raw-ref, r=jieyouxuMatthias Krüger-16/+53
rustc_borrowck: Stop suggesting the invalid syntax `&mut raw const` A legitimate suggestion would be to change from &raw const val to &raw mut val But until we have figured out how to make that happen we should at least stop suggesting invalid syntax. I recommend review commit-by-commit. Part of #127562
2024-12-14Rollup merge of #134181 - estebank:trim-render, r=oli-obkMatthias Krüger-3/+12
Tweak multispan rendering to reduce output length Consider comments and bare delimiters the same as an "empty line" for purposes of hiding rendered code output of long multispans. This results in more aggressive shortening of rendered output without losing too much context, specially in `*.stderr` tests that have "hidden" comments. We do that check not only on the first 4 lines of the multispan, but now also on the previous to last line as well.
2024-12-13Auto merge of #134269 - matthiaskrgr:rollup-fkshwux, r=matthiaskrgrbors-535/+861
Rollup of 7 pull requests Successful merges: - #133900 (Advent of `tests/ui` (misc cleanups and improvements) [1/N]) - #133937 (Keep track of parse errors in `mod`s and don't emit resolve errors for paths involving them) - #133938 (`rustc_mir_dataflow` cleanups, including some renamings) - #134058 (interpret: reduce usage of TypingEnv::fully_monomorphized) - #134130 (Stop using driver queries in the public API) - #134140 (Add AST support for unsafe binders) - #134229 (Fix typos in docs on provenance) r? `@ghost` `@rustbot` modify labels: rollup
2024-12-13Auto merge of #133099 - RalfJung:forbidden-hardfloat-features, r=workingjubileebors-403/+530
forbid toggling x87 and fpregs on hard-float targets Part of https://github.com/rust-lang/rust/issues/116344, follow-up to https://github.com/rust-lang/rust/pull/129884: The `x87` target feature on x86 and the `fpregs` target feature on ARM must not be disabled on a hardfloat target, as that would change the float ABI. However, *enabling* `fpregs` on ARM is [explicitly requested](https://github.com/rust-lang/rust/issues/130988) as it seems to be useful. Therefore, we need to refine the distinction of "forbidden" target features and "allowed" target features: all (un)stable target features can determine on a per-target basis whether they should be allowed to be toggled or not. `fpregs` then checks whether the current target has the `soft-float` feature, and if yes, `fpregs` is permitted -- otherwise, it is not. (Same for `x87` on x86). Also fixes https://github.com/rust-lang/rust/issues/132351. Since `fpregs` and `x87` can be enabled on some builds and disabled on others, it would make sense that one can query it via `cfg`. Therefore, I made them behave in `cfg` like any other unstable target feature. The first commit prepares the infrastructure, but does not change behavior. The second commit then wires up `fpregs` and `x87` with that new infrastructure. r? `@workingjubilee`
2024-12-13Document the symbol Visibility enumbjorn3-0/+12
2024-12-13Account for `///` when rendering multiline spansEsteban Küber-8/+9
Don't consider `///` and `//!` docstrings to be empty for the purposes of multiline span rendering.
2024-12-13Rename ty_def_id so people will stop using it by accidentMichael Goulet-16/+16
2024-12-13Rollup merge of #134140 - compiler-errors:unsafe-binders-ast, r=oli-obkMatthias Krüger-13/+338
Add AST support for unsafe binders I'm splitting up #130514 into pieces. It's impossible for me to keep up with a huge PR like that. I'll land type system support for this next, probably w/o MIR lowering, which will come later. r? `@oli-obk` cc `@BoxyUwU` and `@lcnr` who also may want to look at this, though this PR doesn't do too much yet
2024-12-13Rollup merge of #134130 - bjorn3:prepare_driver_query_removal, r=oli-obkMatthias Krüger-34/+32
Stop using driver queries in the public API Follow up to https://github.com/rust-lang/rust/pull/132410 and https://github.com/rust-lang/rust/pull/133567 The next PR will completely get rid of driver queries. That PR will also contains some non-trivial refactorings enabled by no longer needing to support entering TyCtxt multiple times after it is constructed. The changes in the current PR have been split out to make it easier to review the api changes and to reduce the size of the next PR to review. ## Custom driver breaking change The `after_crate_root_parsing` and `after_expansion` callbacks now accept `ast::Crate` and `TyCtxt` respectively rather than `Queries`. The only safe query in `Queries` to call inside these callbacks are `parse()` and `global_ctxt()` respectively which allows you to access the `ast::Crate` and `TyCtxt` either way. To fix your custom driver, replace the `queries: &'tcx Queries<'tcx>` argument with `crate_: ast::Crate` and `tcx: TyCtxt<'tcx>` respectively and for `after_expansion` remove your `queries.global_ctxt().unwrap().enter(|tcx| { ... })` call and only keep the contents of the closure.
2024-12-13Rollup merge of #134058 - RalfJung:interpret-typing-env, r=lcnrMatthias Krüger-8/+9
interpret: reduce usage of TypingEnv::fully_monomorphized r? `@lcnr`
2024-12-13Rollup merge of #133938 - nnethercote:rustc_mir_dataflow-renamings, r=oli-obkMatthias Krüger-422/+360
`rustc_mir_dataflow` cleanups, including some renamings Some opinionated commits in this collection, let's see how we go. r? `@cjgillot`
2024-12-13Rollup merge of #133937 - ↵Matthias Krüger-58/+122
estebank:silence-resolve-errors-from-mod-with-parse-errors, r=davidtwco Keep track of parse errors in `mod`s and don't emit resolve errors for paths involving them When we expand a `mod foo;` and parse `foo.rs`, we now track whether that file had an unrecovered parse error that reached the end of the file. If so, we keep that information around in the HIR and mark its `DefId` in the `Resolver`. When resolving a path like `foo::bar`, we do not emit any errors for "`bar` not found in `foo`", as we know that the parse error might have caused `bar` to not be parsed and accounted for. When this happens in an existing project, every path referencing `foo` would be an irrelevant compile error. Instead, we now skip emitting anything until `foo.rs` is fixed. Tellingly enough, we didn't have any test for errors caused by expansion of `mod`s with parse errors. Fix https://github.com/rust-lang/rust/issues/97734.
2024-12-13Auto merge of #134122 - oli-obk:push-zqnyznxtpnll, r=petrochenkovbors-43/+57
Move impl constness into impl trait header This PR is kind of the opposite of the rejected https://github.com/rust-lang/rust/pull/134114 Instead of moving more things into the `constness` query, we want to keep them where their corresponding hir nodes are lowered. So I gave this a spin for impls, which have an obvious place to be (the impl trait header). And surprisingly it's also a perf improvement (likely just slightly better query & cache usage). The issue was that removing anything from the `constness` query makes it just return `NotConst`, which is wrong. So I had to change it to `bug!` out if used wrongly, and only then remove the impl blocks from the `constness` query. I think this change is good in general, because it makes using `constness` more robust (as can be seen by how few sites that had to be changed, so it was almost solely used specifically for the purpose of asking for functions' constness). The main thing where this change was not great was in clippy, which was using the `constness` query as a general DefId -> constness map. I added a `DefKind` filter in front of that. If it becomes a more common pattern we can always move that helper into rustc.
2024-12-13Arbitrary self types v2: adjust diagnostic.Adrian Taylor-1/+23
The recently landed PR to adjust arbitrary self types was a bit overenthusiastic, advising folks to use the new Receiver trait even before it's been stabilized. Revert to the older wording of the lint in such cases.
2024-12-13rustc_borrowck: Convert suggest_ampmut() 4-tuple to struct for readabilityMartin Nordholts-13/+46
2024-12-13rustc_borrowck: Stop suggesting the invalid syntax `&mut raw const`Martin Nordholts-0/+5
A legitimate suggestion would be to change from &raw const val to &raw mut val But until we have figured out how to make that happen we should at least stop suggesting invalid syntax.
2024-12-13rustc_borrowck: Make suggest_ampmut() return type match its useMartin Nordholts-9/+8
So that it becomes easy for a later commit to return `None`.
2024-12-13Use a more precise span in placeholder_type_error_diagArthur Carcano-3/+4
Closes: https://github.com/rust-lang/rust/issues/123861
2024-12-13Make dependency_formats an FxIndexMap rather than a list of tuplesbjorn3-34/+19
It is treated as a map already. This is using FxIndexMap rather than UnordMap because the latter doesn't provide an api to pick a single value iff all values are equal, which each_linked_rlib depends on.
2024-12-13Explain why an untranslatable_diagnostic occursbjorn3-2/+5
2024-12-13Remove registered_lints field from Sessionbjorn3-8/+5
It only exists to pass some information from one part of the driver to another part. We can directly pass this information to the function that needs it to reduce the amount of mutation of the Session.
2024-12-13Remove jobserver from Sessionbjorn3-22/+9
It is effectively a global resource and the jobserver::Client in Session was a clone of GLOBAL_CLIENT anyway.
2024-12-13Auto merge of #133899 - scottmcm:strip-mir-debuginfo, r=oli-obkbors-4/+63
We don't need `NonNull::as_ptr` debuginfo In order to stop pessimizing the use of local variables in core, skip debug info for MIR temporaries in tiny (single-BB) functions. For functions as simple as this -- `Pin::new`, etc -- nobody every actually wants debuginfo for them in the first place. They're more like intrinsics than real functions, and stepping over them is good.
2024-12-13Auto merge of #132706 - compiler-errors:async-closures, r=oli-obkbors-23/+3
Stabilize async closures (RFC 3668) # Async Closures Stabilization Report This report proposes the stabilization of `#![feature(async_closure)]` ([RFC 3668](https://rust-lang.github.io/rfcs/3668-async-closures.html)). This is a long-awaited feature that increases the expressiveness of the Rust language and fills a pressing gap in the async ecosystem. ## Stabilization summary * You can write async closures like `async || {}` which return futures that can borrow from their captures and can be higher-ranked in their argument lifetimes. * You can express trait bounds for these async closures using the `AsyncFn` family of traits, analogous to the `Fn` family. ```rust async fn takes_an_async_fn(f: impl AsyncFn(&str)) { futures::join(f("hello"), f("world")).await; } takes_an_async_fn(async |s| { other_fn(s).await }).await; ``` ## Motivation Without this feature, users hit two major obstacles when writing async code that uses closures and `Fn` trait bounds: - The inability to express higher-ranked async function signatures. - That closures cannot return futures that borrow from the closure captures. That is, for the first, we cannot write: ```rust // We cannot express higher-ranked async function signatures. async fn f<Fut>(_: impl for<'a> Fn(&'a u8) -> Fut) where Fut: Future<Output = ()>, { todo!() } async fn main() { async fn g(_: &u8) { todo!() } f(g).await; //~^ ERROR mismatched types //~| ERROR one type is more general than the other } ``` And for the second, we cannot write: ```rust // Closures cannot return futures that borrow closure captures. async fn f<Fut: Future<Output = ()>>(_: impl FnMut() -> Fut) { todo!() } async fn main() { let mut xs = vec![]; f(|| async { async fn g() -> u8 { todo!() } xs.push(g().await); }); //~^ ERROR captured variable cannot escape `FnMut` closure body } ``` Async closures provide a first-class solution to these problems. For further background, please refer to the [motivation section](https://rust-lang.github.io/rfcs/3668-async-closures.html#motivation) of the RFC. ## Major design decisions since RFC The RFC had left open the question of whether we would spell the bounds syntax for async closures... ```rust // ...as this... fn f() -> impl AsyncFn() -> u8 { todo!() } // ...or as this: fn f() -> impl async Fn() -> u8 { todo!() } ``` We've decided to spell this as `AsyncFn{,Mut,Once}`. The `Fn` family of traits is special in many ways. We had originally argued that, due to this specialness, that perhaps the `async Fn` syntax could be adopted without having to decide whether a general `async Trait` mechanism would ever be adopted. However, concerns have been raised that we may not want to use `async Fn` syntax unless we would pursue more general trait modifiers. Since there remain substantial open questions on those -- and we don't want to rush any design work there -- it makes sense to ship this needed feature using the `AsyncFn`-style bounds syntax. Since we would, in no case, be shipping a generalized trait modifier system anytime soon, we'll be continuing to see `AsyncFoo` traits appear across the ecosystem regardless. If we were to ever later ship some general mechanism, we could at that time manage the migration from `AsyncFn` to `async Fn`, just as we'd be enabling and managing the migration of many other traits. Note that, as specified in RFC 3668, the details of the `AsyncFn*` traits are not exposed and they can only be named via the "parentheses sugar". That is, we can write `T: AsyncFn() -> u8` but not `T: AsyncFn<Output = u8>`. Unlike the `Fn` traits, we cannot project to the `Output` associated type of the `AsyncFn` traits. That is, while we can write... ```rust fn f<F: Fn() -> u8>(_: F::Output) {} ``` ...we cannot write: ```rust fn f<F: AsyncFn() -> u8>(_: F::Output) {} //~^ ERROR ``` The choice of `AsyncFn{,Mut,Once}` bounds syntax obviates, for our purposes here, another question decided after that RFC, which was how to order bound modifiers such as `for<'a> async Fn()`. Other than answering the open question in the RFC on syntax, nothing has changed about the design of this feature between RFC 3668 and this stabilization. ## What is stabilized For those interested in the technical details, please see [the dev guide section](https://rustc-dev-guide.rust-lang.org/coroutine-closures.html) I authored. #### Async closures Other than in how they solve the problems described above, async closures act similarly to closures that return async blocks, and can have parts of their signatures specified: ```rust // They can have arguments annotated with types: let _ = async |_: u8| { todo!() }; // They can have their return types annotated: let _ = async || -> u8 { todo!() }; // They can be higher-ranked: let _ = async |_: &str| { todo!() }; // They can capture values by move: let x = String::from("hello, world"); let _ = async move || do_something(&x).await }; ``` When called, they return an anonymous future type corresponding to the (not-yet-executed) body of the closure. These can be awaited like any other future. What distinguishes async closures is that, unlike closures that return async blocks, the futures returned from the async closure can capture state from the async closure. For example: ```rust let vec: Vec<String> = vec![]; let closure = async || { vec.push(ready(String::from("")).await); }; ``` The async closure captures `vec` with some `&'closure mut Vec<String>` which lives until the closure is dropped. Every call to `closure()` returns a future which reborrows that mutable reference `&'call mut Vec<String>` which lives until the future is dropped (e.g. it is `await`ed). As another example: ```rust let string: String = "Hello, world".into(); let closure = async move || { ready(&string).await; }; ``` The closure is marked with `move`, which means it takes ownership of the string by *value*. The future that is returned by calling `closure()` returns a future which borrows a reference `&'call String` which lives until the future is dropped (e.g. it is `await`ed). #### Async fn trait family To support the lending capability of async closures, and to provide a first-class way to express higher-ranked async closures, we introduce the `AsyncFn*` family of traits. See the [corresponding section](https://rust-lang.github.io/rfcs/3668-async-closures.html#asyncfn) of the RFC. We stabilize naming `AsyncFn*` via the "parenthesized sugar" syntax that normal `Fn*` traits can be named. The `AsyncFn*` trait can be used anywhere a `Fn*` trait bound is allowed, such as: ```rust /// In return-position impl trait: fn closure() -> impl AsyncFn() { async || {} } /// In trait bounds: trait Foo<F>: Sized where F: AsyncFn() { fn new(f: F) -> Self; } /// in GATs: trait Gat { type AsyncHasher<T>: AsyncFn(T) -> i32; } ``` Other than using them in trait bounds, the definitions of these traits are not directly observable, but certain aspects of their behavior can be indirectly observed such as the fact that: * `AsyncFn::async_call` and `AsyncFnMut::async_call_mut` return a future which is *lending*, and therefore borrows the `&self` lifetime of the callee. ```rust fn by_ref_call(c: impl AsyncFn()) { let fut = c(); drop(c); // ^ Cannot drop `c` since it is borrowed by `fut`. } ``` * `AsyncFnOnce::async_call_once` returns a future that takes ownership of the callee. ```rust fn by_ref_call(c: impl AsyncFnOnce()) { let fut = c(); let _ = c(); // ^ Cannot call `c` since calling it takes ownership the callee. } ``` * All currently-stable callable types (i.e., closures, function items, function pointers, and `dyn Fn*` trait objects) automatically implement `AsyncFn*() -> T` if they implement `Fn*() -> Fut` for some output type `Fut`, and `Fut` implements `Future<Output = T>`. * This is to make sure that `AsyncFn*()` trait bounds have maximum compatibility with existing callable types which return futures, such as async function items and closures which return boxed futures. * For now, this only works currently for *concrete* callable types -- for example, a argument-position impl trait like `impl Fn() -> impl Future<Output = ()>` does not implement `AsyncFn()`, due to the fact that a `AsyncFn`-if-`Fn` blanket impl does not exist in reality. This may be relaxed in the future. Users can work around this by wrapping their type in an async closure and calling it. I expect this to not matter much in practice, as users are encouraged to write `AsyncFn` bounds directly. ```rust fn is_async_fn(_: impl AsyncFn(&str)) {} async fn async_fn_item(s: &str) { todo!() } is_async_fn(s); // ^^^ This works. fn generic(f: impl Fn() -> impl Future<Output = ()>) { is_async_fn(f); // ^^^ This does not work (yet). } ``` #### The by-move future When async closures are called with `AsyncFn`/`AsyncFnMut`, they return a coroutine that borrows from the closure. However, when they are called via `AsyncFnOnce`, we consume that closure, and cannot return a coroutine that borrows from data that is now dropped. To work around around this limitation, we synthesize a separate future type for calling the async closure via `AsyncFnOnce`. This future executes identically to the by-ref future returned from calling the async closure, except for the fact that it has a different set of captures, since we must *move* the captures from the parent async into the child future. #### Interactions between async closures and the `Fn*` family of traits Async closures always implement `FnOnce`, since they always can be called once. They may also implement `Fn` or `FnMut` if their body is compatible with the calling mode (i.e. if they do not mutate their captures, or they do not capture their captures, respectively) and if the future returned by the async closure is not *lending*. ```rust let id = String::new(); let mapped: Vec</* impl Future */> = [/* elements */] .into_iter() // `Iterator::map` takes an `impl FnMut` .map(async |element| { do_something(&id, element).await; }) .collect(); ``` See [the dev guide](https://rustc-dev-guide.rust-lang.org/coroutine-closures.html#follow-up-when-do-async-closures-implement-the-regular-fn-traits) for a detailed explanation for the situations where this may not be possible due to the lending nature of async closures. #### Other notable features of async closures shared with synchronous closures * Async closures are `Copy` and/or `Clone` if their captures are `Copy`/`Clone`. * Async closures do closure signature inference: If an async closure is passed to a function with a `AsyncFn` or `Fn` trait bound, we can eagerly infer the argument types of the closure. More details are provided in [the dev guide](https://rustc-dev-guide.rust-lang.org/coroutine-closures.html#closure-signature-inference). #### Lints This PR also stabilizes the `CLOSURE_RETURNING_ASYNC_BLOCK` lint as an `allow` lint. This lints on "old-style" async closures: ```rust #![warn(closure_returning_async_block)] let c = |x: &str| async {}; ``` We should encourage users to use `async || {}` where possible. This lint remains `allow` and may be refined in the future because it has a few false positives (namely, see: "Where do we expect rewriting `|| async {}` into `async || {}` to fail?") An alternative that could be made at the time of stabilization is to put this lint behind another gate, so we can decide to stabilize it later. ## What isn't stabilized (aka, potential future work) #### `async Fn*()` bound syntax We decided to stabilize async closures without the `async Fn*()` bound modifier syntax. The general direction of this syntax and how it fits is still being considered by T-lang (e.g. in [RFC 3710](https://github.com/rust-lang/rfcs/pull/3710)). #### Naming the futures returned by async closures This stabilization PR does not provide a way of naming the futures returned by calling `AsyncFn*`. Exposing a stable way to refer to these futures is important for building async-closure-aware combinators, and will be an important future step. #### Return type notation-style bounds for async closures The RFC described an RTN-like syntax for putting bounds on the future returned by an async closure: ```rust async fn foo(x: F) -> Result<()> where F: AsyncFn(&str) -> Result<()>, // The future from calling `F` is `Send` and `'static`. F(..): Send + 'static, {} ``` This stabilization PR does not stabilize that syntax yet, which remains unimplemented (though will be soon). #### `dyn AsyncFn*()` `AsyncFn*` are not dyn-compatible yet. This will likely be implemented in the future along with the dyn-compatibility of async fn in trait, since the same issue (dealing with the future returned by a call) applies there. ## Tests Tests exist for this feature in [`tests/ui/async-await/async-closures`](https://github.com/rust-lang/rust/tree/5b542866400ad4a294f468cfa7e059d95c27a079/tests/ui/async-await/async-closures). <details> <summary>A selected set of tests:</summary> * Lending behavior of async closures * `tests/ui/async-await/async-closures/mutate.rs` * `tests/ui/async-await/async-closures/captures.rs` * `tests/ui/async-await/async-closures/precise-captures.rs` * `tests/ui/async-await/async-closures/no-borrow-from-env.rs` * Async closures may be higher-ranked * `tests/ui/async-await/async-closures/higher-ranked.rs` * `tests/ui/async-await/async-closures/higher-ranked-return.rs` * Async closures may implement `Fn*` traits * `tests/ui/async-await/async-closures/is-fn.rs` * `tests/ui/async-await/async-closures/implements-fnmut.rs` * Async closures may be cloned * `tests/ui/async-await/async-closures/clone-closure.rs` * Ownership of the upvars when `AsyncFnOnce` is called * `tests/ui/async-await/async-closures/drop.rs` * `tests/ui/async-await/async-closures/move-is-async-fn.rs` * `tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs` * `tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs` * Closure signature inference * `tests/ui/async-await/async-closures/signature-deduction.rs` * `tests/ui/async-await/async-closures/sig-from-bare-fn.rs` * `tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs` </details> ## Remaining bugs and open issues * https://github.com/rust-lang/rust/issues/120694 tracks moving onto more general `LendingFn*` traits. No action needed, since it's not observable. * https://github.com/rust-lang/rust/issues/124020 - Polymorphization ICE. Polymorphization needs to be heavily reworked. No action needed. * https://github.com/rust-lang/rust/issues/127227 - Tracking reworking the way that rustdoc re-sugars bounds. * The part relevant to to `AsyncFn` is fixed by https://github.com/rust-lang/rust/pull/132697. ## Where do we expect rewriting `|| async {}` into `async || {}` to fail? * Fn pointer coercions * Currently, it is not possible to coerce an async closure to an fn pointer like regular closures can be. This functionality may be implemented in the future. ```rust let x: fn() -> _ = async || {}; ``` * Argument capture * Like async functions, async closures always capture their input arguments. This is in contrast to something like `|t: T| async {}`, which doesn't capture `t` unless it is used in the async block. This may affect the `Send`-ness of the future or affect its outlives. ```rust fn needs_send_future(_: impl Fn(NotSendArg) -> Fut) where Fut: Future<Output = ()>, {} needs_send_future(async |_| {}); ``` ## History #### Important feature history - https://github.com/rust-lang/rust/pull/51580 - https://github.com/rust-lang/rust/pull/62292 - https://github.com/rust-lang/rust/pull/120361 - https://github.com/rust-lang/rust/pull/120712 - https://github.com/rust-lang/rust/pull/121857 - https://github.com/rust-lang/rust/pull/123660 - https://github.com/rust-lang/rust/pull/125259 - https://github.com/rust-lang/rust/pull/128506 - https://github.com/rust-lang/rust/pull/127482 ## Acknowledgements Thanks to `@oli-obk` for reviewing the bulk of the work for this feature. Thanks to `@nikomatsakis` for his design blog posts which generated interest for this feature, `@traviscross` for feedback and additions to this stabilization report. All errors are my own. r? `@ghost`
2024-12-13Stabilize async closuresMichael Goulet-23/+3
2024-12-12Filter empty lines, comments and delimiters from previous to last multiline ↵Esteban Küber-1/+5
span rendering
2024-12-12Tweak multispan renderingEsteban Küber-2/+6
Consider comments and bare delimiters the same as an "empty line" for purposes of hiding rendered code output of long multispans. This results in more aggressive shortening of rendered output without losing too much context, specially in `*.stderr` tests that have "hidden" comments.
2024-12-12Auto merge of #132961 - adetaylor:arbitrary-self-types-the-big-bit, ↵bors-148/+500
r=compiler-errors,wesleywiser Arbitrary self types v2: main compiler changes This is the main PR in a series of PRs related to Arbitrary Self Types v2, tracked in #44874. Specifically this is step 7 of the plan [described here](https://github.com/rust-lang/rust/issues/44874#issuecomment-2122179688), for [RFC 3519](https://github.com/rust-lang/rfcs/pull/3519). Overall this PR: * Switches from the `Deref` trait to the new `Receiver` trait when the unstable `arbitrary_self_types` feature is enabled (the simple bit) * Introduces new algorithms to spot "shadowing"; that is, the case where a newly-added method in an outer smart pointer might end up overriding a pre-existing method in the pointee (the complex bit). Most of this bit was explored in [this earlier perf-testing PR](https://github.com/rust-lang/rust/pull/127812#issuecomment-2236911900). * Lots of tests This should not break compatibility for: * Stable users, where it should have no effect * Users of the existing `arbitrary_self_types` feature (because we implement `Receiver` for `T: Deref`) _unless_ those folks have added methods which may shadow methods in inner types, which we no longer want to allow Subsequent PRs will add better diagnostics. It's probably easiest to review this commit-by-commit. r? `@wesleywiser`
2024-12-13Remove `Lexer`'s dependency on `Parser`.Nicholas Nethercote-97/+37
Lexing precedes parsing, as you'd expect: `Lexer` creates a `TokenStream` and `Parser` then parses that `TokenStream`. But, in a horrendous violation of layering abstractions and common sense, `Lexer` depends on `Parser`! The `Lexer::unclosed_delim_err` method does some error recovery that relies on creating a `Parser` to do some post-processing of the `TokenStream` that the `Lexer` just created. This commit just removes `unclosed_delim_err`. This change removes `Lexer`'s dependency on `Parser`, and also means that `lex_token_tree`'s return value can have a more typical form. The cost is slightly worse error messages in two obscure cases, as shown in these tests: - tests/ui/parser/brace-in-let-chain.rs: there is slightly less explanation in this case involving an extra `{`. - tests/ui/parser/diff-markers/unclosed-delims{,-in-macro}.rs: the diff marker detection is no longer supported (because that detection is implemented in the parser). In my opinion this cost is outweighed by the magnitude of the code cleanup.
2024-12-12Move impl constness into impl trait headerOli Scherer-33/+35
2024-12-12Rollup merge of #134204 - Zalathar:llvm-bool, r=SparrowLiiMatthias Krüger-1/+3
Fix our `llvm::Bool` typedef to be signed, to match `LLVMBool` In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`, but our Rust-side typedef was using `c_uint` instead. Signed and unsigned integers have the same ABI on most platforms, but that isn't universally true, so we should prefer to be consistent with LLVM. https://github.com/rust-lang/llvm-project/blob/1268e87/llvm/include/llvm-c/Types.h#L28
2024-12-12Rollup merge of #133249 - heiher:loong-abi-check, r=workingjubileeMatthias Krüger-1/+3
ABI checks: add support for loongarch LoongArch psABI[^1] specifies that LSX vector types are passed via general-purpose registers, while LASX vector types are passed indirectly through the stack. This patch addresses the following warnings: ``` warning: this function call uses a SIMD vector type that is not currently supported with the chosen ABI --> .../library/core/src/../../stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs:3695:5 | 3695 | __lsx_vreplgr2vr_b(a) | ^^^^^^^^^^^^^^^^^^^^^ function called here | = 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 #116558 <https://github.com/rust-lang/rust/issues/116558> = note: `#[warn(abi_unsupported_vector_types)]` on by default ``` [^1]: https://github.com/loongson/la-abi-specs/blob/release/lapcs.adoc r? `@workingjubilee`
2024-12-12Rollup merge of #133122 - compiler-errors:afidt, r=oli-obkMatthias Krüger-33/+386
Add unpolished, experimental support for AFIDT (async fn in dyn trait) This allows us to begin messing around `async fn` in `dyn Trait`. Calling an async fn from a trait object always returns a `dyn* Future<Output = ...>`. To make it work, Implementations are currently required to return something that can be coerced to a `dyn* Future` (see the example in `tests/ui/async-await/dyn/works.rs`). If it's not the right size, then it'll raise an error at the coercion site (see the example in `tests/ui/async-await/dyn/wrong-size.rs`). Currently the only practical way of doing this is wrapping the body in `Box::pin(async move { .. })`. This PR does not implement a helper type like a "`Boxing`"[^boxing] adapter, and I'll probably follow-up with another PR to improve the error message for the `PointerLike` trait (something that explains in just normal prose what is happening here, rather than a trait error). [^boxing]: https://rust-lang.github.io/async-fundamentals-initiative/explainer/user_guide_future.html#the-boxing-adapter This PR also does not implement new trait solver support for AFIDT; I'll need to think how best to integrate it into candidate assembly, and that's a bit of a matter of taste, but I don't think it will be difficult to do. This could also be generalized: * To work on functions that are `-> impl Future` (soon). * To work on functions that are `-> impl Iterator` and other "dyn rpitit safe" traits. We still need to nail down exactly what is needed for this to be okay (not soon). Tracking: * https://github.com/rust-lang/rust/issues/133119
2024-12-13Fix powerpc64 big-endian FreeBSD ABITaiki Endo-2/+2
2024-12-12Fix toolsMichael Goulet-1/+1
2024-12-12Add testsMichael Goulet-1/+3