Since we're leaving as open the question of whether to say `impl
use<..> Trait` or `use<..> impl Trait`, we had earlier weakened some
language that was previously decisive. We missed one spot, though, so
let's make this sentence less decisive as well.
We had a sentence that would be correct if we had not already
stabilized RPIT in trait impls. Since we have, let's more precisely
describe where lifetime parameters are not implicitly captured.
We had in this RFC chosen `impl use<..> Trait`. But there's been
meaningful discussion about whether this should instead be `use<..>
impl Trait`, so let's mark this question as unresolved.
The FCP for RFC 3484 completed on 2024-05-04 with a disposition to
merge. The lang team further confirmed its happiness with the RFC in
a meeting on 2024-05-08. Let's merge the RFC.
Without this adjustment, it would not be possible to use this macro with
types such as the `ARef` type that was discussed on the RFC thread [1],
since we need `AlwaysRefcounted` to be specified for both T and U.
Link: https://www.github.com/rust-lang/rfcs/pull/3621#issuecomment-2094094231 [1]
The 2023-10-11 consensus from lang on how to move forward included
that the `safe` and `unsafe` keywords would be optional within an
`unsafe extern` block.
The reference-level section correctly followed this consensus, but the
guide-level section did not, and suggested that annotating items with
these keywords was required. Let's fix that.
This RFC had used as one motivation that undefined behavior can
currently result simply from having an incorrect `extern` block even
if the items within are not used from Rust code.
This motivation was not cited in the lang team's 2023-10-11 consensus
for how and why to proceed with this RFC, and it's possible that we
may be able to resolve this issue in other ways, so let's remove that
motivation from this RFC.
(Thanks to RalfJ for raising this point and suggesting this.)
When people migrate to the new edition, if they have turned up the
severity of the `unsafe_code` lint and they have `extern` blocks that
need to be marked `unsafe`, they will see this lint as intended.
Let's make a note of that.
(Thanks to kennytm for raising this point.)
Even if the C standard allows for what LLVM is doing, we could still
conceivably fix LLVM. In the text, let's draw this out a bit more
finely.
(Thanks to RalfJ for raising this point.)
One possibility we should mention is that of changing the behavior of
LLVM and then not adding `unsafe extern`, so let's mention that.
(Thanks to RalfJ for raising this point.)
As this RFC was reviewed in the GitHub thread, many alternatives were
proposed and questions raised. As those of us who were a bit too
close to it were cursed with knowledge, the rationale for rejecting
these alternatives were not fully articulated and not all of these
questions were clearly answered.
Let's better document these alternatives, the rationale for rejecting
each, and the answers to various known questions.
(Thanks to GoldsteinE, madsmtm, kennytm, samih, and tmccombs for
raising these alternatives and questions.)
This RFC means to specify that we will *eventually* issue a lint in
all editions when `extern` is not prefixed with `unsafe`. Let's
specify this more clearly.
(Thanks to Waffle and joshtriplett for raising this point.)
There's a long history of discussion on how incorrect declarations in
`extern` blocks might cause UB in programs compiled using LLVM. Let's
link to one of the issues in that history.
(Thanks to madsmtm for raising this question, and to RalfJ for
providing this citation.)
An incorrect declaration in an `extern` block may cause undefined
behavior in the resulting program. Let's clarify that in the text.
(Thanks to Waffle for raising this point.)
During the FCP, people noticed that the wording of the drawback
probably fit better with an earlier draft of this RFC. Let's
incorporate that feedback before merging.
(Thanks to Waffle for raising this point.)
The FCP for RFC 3593 has completed, so let's prepare it to be merged.
In this case, that means changing the file name to use dashes rather
than underscores as separators and updating the tracking issue.
The FCP has completed on RFC 3606, so let's prepare it to be merged.
First, we'll shorten the name of the feature flag a bit; this should
still be unambiguous.
Second, we're going to remove the graphic from the summary. While it
may be illustrative, the text and the other examples seem clear enough
without it, and its benefits have to be weighed against the fact that
we want the content in this repository to be easily editable and
freestanding. Pulling in an SVG file from an outside host pulls
against that. If we come to think the graphic is critical, we could
always add it back in a separate PR that would add an editable version
of this SVG file into the repository itself.
Third, let's make the H1 title of the document a bit more clear.
The FCP for RFC 3519 ("Arbitrary self types v2") is complete. Let's
reuse the existing `arbitrary_self_types` feature flag for this work,
and similarly, let's reuse the existing tracking issue.
During the FCP, some questions came up related to how refinement and
reparameterization in the impl are handled. This handling is implied
by other text in the RFC and by the existing behavior of Rust, so
let's go ahead and add clarifications to address these questions.
The hardest of these questions relate to how things would behave if we
were to allow `use<..>` in trait definitions to not capture the
generic input parameters to the trait (including `Self`). It's
unlikely this will be possible for the foreseeable future, and while
we will not leave these as open questions, certainly much might be
learned between now and the point at which that might become possible,
so we'll make note of that.
We'll also add a clarification to address a question that came up in
the 2024-04-24 design meeting about what it means to capture a const
generic parameter.
(Thanks to aliemjay for raising many of these great questions.)
We had added an RPITIT desugaring that was rather complicated. This
complication was due to trying to explain what it would mean to not
capture generic parameters that are part of the trait header.
However, it's likely that there's no good way to express that semantic
in the surface syntax. Let's instead simplify the desugaring and make
a note of its limitations.
We had included a reference desugaring of `use<..>` in RPIT using
ATPIT. Let's add a similar desugaring for `use<..>` in RPITIT.
In doing this, we'll make some changes to the RPIT desugaring so that
it better parallels the RPITIT one. In particular, we want to
turbofish all generic parameters for clarity, and we want to eliminate
all function arguments for conciseness. Doing this means that all of
the lifetimes become early bound. This seems fine, since it's rather
orthogonal to the semantics we're trying to demonstrate here.
We also want to demonstrate using const generics in the hidden type.
We could do this using arrays, e.g. `[(); N]`, but it seems more clear
to just define a type constructor that uses all of the generics, so
we'll sacrifice a bit of conciseness to do it that way.
We have an example showing how to avoid capturing a higher ranked
lifetime in a nested opaque type so that the code can be migrated to
Rust 2024. However, because we didn't parameterize the trait in the
example with a lifetime, the code could be migrated by just removing
the `for<..>` binder. This makes the example weaker than it could be,
so let's strengthen it by parameterizing the trait.
(Thanks to aliemjay for raising this point.)
We had earlier written up a section on `use<..> impl Trait` syntax
that mostly focused on why we had not adopted it. We didn't spend
much text on why it's appealing, probably because we are in fact
sympathetic to it and consider the reasons that it's appealing
obvious.
Still, we should write all those reasons down. Let's extend the
section on this syntax with the best possible argument in favor.
We also see more clearly now the fundamental intuitive tension behind
this syntax and `impl use<..> Trait`, so let's write that down too.
Finally, let's describe the historical and other factors that led to
picking one syntax over the other.
(Thanks to tmandry for suggesting the `use<..> impl Trait` syntax and
many of the arguments in favor of it.)
As with other lists of generic arguments in Rust, the grammar for
`use<..>` specifiers supports an optional trailing comma. This is
already specified in the formal grammar, but let's also note this in
the guide-level section.
(Thanks to Josh Triplett for raising this point.)
In the T-lang design meeting on 2024-04-24, a new syntax option was
raised: `use<..> impl Trait`.
While some people liked this, others did not, and no clear consensus
formed to change the main proposal in this RFC. Nevertheless, let's
discuss this as an alternative.
For the formal syntax, we had used the existing `GenericParams`
production. However, that production isn't exactly appropriate for
this case. What's needed here is essentially a generic argument list
that only accepts generic parameters as elements.
Since none of the other existing productions provide this, we'll
define our own.
(Thanks to @kennytm for pointing this out.)
We had included one `use<T>` in a pre-migration example when it should
have only appeared in a post-migration example. Let's fix this error.
(Thanks to @kennytm for pointing this out.)
One way to think about `use<..>` is that, in Rust `use` brings things
into scope, and here we are bringing certain generic parameters into
scope for the hidden type. Let's point this out.
To fully stabilize, in Rust 2024, the Lifetime Capture Rules 2024 that
we accepted in RFC 3498, we need to stabilize some means of precise
capturing. This RFC provides that means.
We discussed this feature, the need for it, and the syntax for it in
the T-lang planning meeting on 2024-04-03. The document here follows
from that discussion.
A few mentions of implementing `Receiver` for raw pointers snuck through from
earlier drafts. That's not in scope for this RFC, for the reasons explained in
the "Enable for raw pointers" alternatives section.
There's been much discussion at recent Rust lang team meetings about this
feature, followed by further discussion on Zulip and face-to-face at
RustNation.
The main conclusions have been:
* yes we want to do this; Rust for Linux has equally important use-cases
* the previously proposed deshadowing algorithm is believed to be sound but is
also complex and counterintuitive, so we may want to more broadly rethink
method resolution.
* so, for now, let's do the most conservative possible version - NOT supporting
raw pointers, Weak or NonNull - but instead erroring on any case where there
is a possible method conflict between an outer smart pointer type and its
contained type. This will give us maximal flexibility to relax restrictions
in future.
This PR updates the RFC correspondingly.
Prototype code can be found at:
https://github.com/rust-lang/rust/compare/master...adetaylor:rust:receiver_trait_with_target_simplified_per_rustnation
The motivating example we had given for `gen` blocks admitted too easy
an implementation with existing stable iterator combinators. Let's
make the example more *motivating* by showing a simple algorithm,
run-length encoding, that's more difficult to implement in other ways.
(Thanks to Ralf Jung for pointing out the need for a better example.)
Under this RFC, it's possible to yield one last value concisely with
`return yield EXPR`. Let's make a note of that.
(Thanks to Nemo157 for pointing this out and to pnkfelix for
suggesting that this be noted in the RFC.)
The Koka language provides an interesting alternative data point for
how generators and other powerful control flow constructs could work
in a typed language such as Rust. Let's include an example in the
prior art section.
(Thanks to zesterer for asking for this.)
We had been meaning to do some final copyediting prior to this RFC
being merged, so let's do that. In addition to making the text a bit
more regular and precise, fixing some minor errors, removing outdated
information, and adding references between sections, we've tried to
"tighten it up" a bit where possible. We've been careful to not
change anything of semantic significance or otherwise of significance
to the consensus.
In RFC 3101 we reserved in Rust 2021 prefixed identifiers such as
`prefix#ident`. For this reason, we can make `gen` blocks available
in Rust 2021 using `k#gen` as was anticipated in the (currently
pending) RFC 3098.
It's less clear what to do about Rust 2015 and Rust 2018, however, so
let's mark this as an open question.
(Thanks to tmandry for raising this point.)
There was a statement in the draft about, as a downside, something
needing to be pinned for the entire iteration rather than just for
each call to `next`. But, of course, under the pinning guarantees,
these are equivalent. Once something is pinned, unless it is `Unpin`,
it must be treated as pinned until it is destructed. Let's remove
this statement.
The main body of the RFC discusses how we might implement
`FusedIterator` for the iterators produced by `gen` blocks, but this
was not listed as a future possibility. Let's do that.
In addition to giving the file the correct number, let's call this
`gen-blocks` rather than `gen-fn` since we removed `gen fn` from the
main body of this RFC.
In RFC 3498 "Lifetime Capture Rules 2024" we specify that lifetime
parameters from `for<..>` binders are captured under the rules.
Currently opaque types in Rust do not support capturing these. In
early drafts of the document, we had called the missing feature
"higher ranked lifetime bounds on nested opaque types". However, we
had then noticed that the relevant error message in `rustc` called
these "higher kinded" instead:
> error: higher kinded lifetime bounds on nested opaque types are not
> supported yet
We changed later drafts to follow that language. But that language
was wrong. These are definitely "higher ranked" lifetime bounds, not
"higher kinded" ones, whatever that might mean. We've now fixed the
error message emitted by `rustc` in:
- https://github.com/rust-lang/rust/pull/122100
Correspondingly, let's now fix this error in the RFC.
We meant to change `r#gen` to `k#gen` on one line to fix an apparent
earlier search/replace error, and we erroneously changed it on a
different line. Let's fix the correct line and fix the mistaken fix.
The language about how to refer to the `gen` keyword in older editions
was changed in a recent commit from `k#gen` to `r#gen`. This was
probably a search/replace error. Let's fix that.
To give us better options for supporting self-referential generators
we may not want the type returned by `gen` blocks to implement
`Iterator` directly. Let's call this out as an open question and
weaken claims throughout the document related to this.
For many years, we had a trait in nightly Rust called `Generator`.
We've now renamed this to `Coroutine`, but this RFC still referred to
it as `Generator`. Let's use the new name and make a note of the old
one.
We had listed self-referential `gen` blocks as a future possibility,
but in discussion with T-lang, it's become clear that this should
instead be listed as an open question, so let's do that.