Edit the schedule here: https://github.com/orgs/rust-lang/projects/31/views/7.
(Meeting attendees, feel free to add items here!)
(Pulling this item forward from last week for visibility due to low attendance last week.)
TC: Two weeks ago, as I mentioned at the start of the meeting, I pushed the triage meeting along a bit faster than usual. The results were as follows:
In terms of output, that's quite a lot more than usual. But I want to be sure we were happy with it. Striking the right balance is challenging (we need those dials they use for focus groups to indicate "faster" or "slower").
TC: Here's an idea: if I'm moving it along and you need a moment, please just raise your hand in the conference and we'll stop until you're ready to move on.
TC: Last week, tmandry expressed that the meeting felt good. Josh expressed that he was happy with how much we got done, but that it felt a bit rushed in terms of the gap between items and would be happy to see it refined over time.
TC: Other feedback?
NM: I'd probably err on the side of a bit faster personally.
(Pulling this item forward from last week for visibility due to low attendance last week.)
TC: We've talked about making these 90 minutes. The recent meeting on temporary lifetimes went as well as possible (we finished reading at about 25 minutes and discussion moved along briskly) and there still just wasn't enough time. It seems likely that today's topic (arbitrary self types) will also be at risk of that.
TC: Do we want to make these meetings 90 minutes? If so, do we want to start half an hour earlier or go half an hour later?
TC: For half an hour earlier, TC, JT, tmandry, and pnkfelix indicated availability.
NM: In favor of either of those. I think we definitely need 90 minutes.
tmandry: I'm in favor of this.
TC: Proposal then, let's do these for 90 minutes and start half an hour earlier.
JT: Proposal for today, let's have optional attendance half an hour earlier today.
Consensus: We'll make these 90 minutes going forward and start half an hour earlier.
TC: We had a call on 2024-02-16 in which we resolved the semantics concerns regarding RTN:
https://hackmd.io/Yne6UYvkRTiEv5OZspCfxw
The consensus was as follows:
Consensus on semantic concerns: We'll try to ship trait aliases (but not necessarily implementable trait aliases) concurrently with RTN (but we'll reevaluate if those are taking too long), and we'll ship RTN with a warn-by-default lint against the direct use of RTN in the bounds of a reachable crate-level public interface (e.g. function, method, type (or type alias), trait, etc.) except for a trait alias.
Outcome on syntax concerns: We did not discuss the syntax concerns. Those are still blocking, and we'll try to resolve those asynchronously. We'll check in at the next triage meeting how that is going.
On the syntax question, we opened a thread to discuss that asynchronously:
https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/RTN.20syntax
TC: Anything we want to add here? Do we want to schedule a call?
NM: This feels like a classic example of where we're going to have to make a call. We should write up the options and then do a round-robin to see where people might stand on this.
JT: It could help here to have some examples written in each of the styles. I'd propose than the RTN proposers prepare a sample in their preferred style. Anyone with an alternate style to propose can then supply the same snippet written in their own proposed style.
NM: I'll take an action-item to do that today. I'll write up a doc. We could look at this in next week's planning meeting.
JT: I'm cognizant of the experience we had with await
syntax discussions. It's more important to find a consensus and ship this than to block on this. We need to find a consensus, but we should not let that expand to an excessive amount of time.
NM: Maybe Monday afternoon 1p EST or later.
tmandry: Can do 10a PST.
JT: Great, works.
Consensus: We'll meet about the RTN syntax on Monday 10a PST / 1p EST.
JT: I raised an issue on the calendaring repo about where this is creating friction. This came up in response:
I designed this around the compiler team's needs, where we have a very static calendar and don't use invites, it works well for that, but I can appreciate that other teams have different needs. I'd encourage other teams and project members to use these calendars for events where it makes sense for them and to continue to use their previous solutions when it doesn't, until the project has a better solution for them.
NM: I have a half-developed idea here. Let's discuss this asynchronously.
Project board: https://github.com/orgs/rust-lang/projects/43/views/5
None.
Link: https://github.com/rust-lang/rust/issues/117587
TC: We accepted the RFC but it has a dependency on some means of expressing precise capturing. That probably means stabilizing TAIT. We're starting with stabilizing ATPIT, and we've now posted the stabilization report and PR for that which is now in proposed FCP. This is also nominated, so let's discuss it further there.
Link: https://github.com/rust-lang/rfcs/pull/3513
TC: Oli is back, and we're all working on this. The minimum we need to do for 2024 is to reserve the keyword.
TC: Both gen
and async gen
blocks work today in nightly Rust. It might be worth giving these a try, along with concurrent work on async closures, if you haven't yet. E.g.:
TC: Josh started a proposed FCP on this last week.
TC: This prompted Oli to see about moving forward async gen
blocks also, and Oli and I put together some documents on this and had a call and further discussion yesterday with Yosh to try to try to identify and resolve concerns on the design of AsyncIterator
.
bstrie: Is there anything beyond the gen keyword relevant to the edition itself?
CE: No.
tmandry: Josh, you raised a concern to narrow the RFC to just gen
functions. Could you elaborate?
JT: I don't want to delay the approval on this to any questions about gen fn
. There are discussions to be had there.
tmandry: I almost think we should see if we can make progress on those discussions and then narrow the scope if necessary.
JT: We can always do another FCP and raise concerns there.
NM: If we were going to stabilize generators, would we need another RFC?
JT: I would not expect so. We could subsequently FCP gen block stabilization.
pnkfelix: As Josh mentioned, we should reserve the keyword. We shouldn't block on the wider questions.
NM: There's an RFC that proposes generators. On the basis of that we can reserve the keyword. As I understand, Josh has questions about how gen fn
should work or whether it should exist in that form, so we should set that aside.
JT: There's a question of fact of what the RFC says. The RFC does not just reserve the keyword but also add gen { .. }
and gen fn
.
tmandry: Do we need to also reserve the yields
keyword?
scottmcm: It's probably contextual.
CE: +1.
tmandry: Would that also be true in a gen
block case?
scottmcm: Generally when things are in expression position, it needs to be a real keyword.
CE: So yes, we'd need it if it were used for gen
closures.
JT: We'll likely want gen
closures.
CE: Agreed.
scottmcm: Technically, we can always k#
this if necessary. Not that we necessarily should. But we could.
NM: None of these questions arise for gen
blocks, right?
scottmcm: Agreed.
NM: I'm comfortable separating it this way.
bstrie: We can always split out yields
.
JT: We have brought up k#
many times. But we've never implemented it, and maybe we never completed the RFC?
TC: We did not accept that RFC.
scottmcm: We instead accepted an RFC reserving a wide space.
TC: tmandry has raised a concern about the open question on self-referential (non-async) generators. I can answer this one. Here's the thinking of the authors. We are in favor of self-referential generators. Because Iterator
is already stable, however, this will mean e.g. adding a new Generator
trait with a blanket impl that makes all pinned generators into iterators (or into IntoIterator
s, or makes all iterators into generators or IntoGenerator
s, etc.). The for
desugaring would be changed to handle automatically pinning the Generator
.
TC: The feeling of the authors is that the problem of not being able to hold references across yield points in gen { .. }
blocks is indeed a serious usability limitation and will be surprising to users (as tmandry suggested). If a consensus in favor of retrofitting Iterator
is possible today, the authors have no concerns about this. We just did not want to block gen
blocks if this consensus is not possible since this could be added later (and that people experiencing these limitations might help build momentum for doing that).
tmandry: It should be marked as an open question in the RFC. I'm fine with that. We don't have to work that out to accept the RFC.
NM: +1. We could then have a design meeting on that open question.
TC: I'll make sure that is added as an option question.
!
to a type (RFC 1216) #35121Link: https://github.com/rust-lang/rust/issues/35121
TC: The never type is still living up to its name. There's been a long discussion on Zulip. This is what we had been hoping to lint against:
TC: My read of the situation is that this would be a good topic for a design document and a design meeting.
TC: Waffle, Nadri, and Mark Simulacrum seem to be the key people here.
TC: Last week, tmandry mentioned that a design meeting could be a good forcing function here.
NM: I'm in favor of a design meeting here.
CE: Everyone has a partial understanding. We should bring this together.
Link: https://github.com/rust-lang/rust/pull/120700
TC: This is now a dual FCP with T-types. This makes it more important to have all boxes checked from the T-lang side.
TC: This is also blocked behind an FCP on:
https://github.com/rust-lang/rust/pull/116935
TC: As I was preparing the minutes, enough boxes became checked that this would move forward modulo the concerns. Let's discuss that on the next item…
Link: https://github.com/rust-lang/rust/pull/116935
TC: tmandry had raised a concern:
However, I am hesitant about moving to a hard error immediately, especially given that it might result in a nontrivial refactor for someone not in crater. I'd like to make this deny-by-default and transition to a hard error some time later (maybe in the following release).
@rfcbot concern can there be a soft transition
In any case if that is hard for some reason, I wouldn't block merging this on it. I also propose that we should use this FCP for making it a hard error eventually (whether in this PR or in a follow-up).
TC: Oli has now replied to this:
@tmandry I don't think it is hard, just undesirable to go with a future incompat lint if we find it unlikely to break user code anywhere. It requires some very interesting recursive RPIT code in order to hit any issue here at all, and while people do use RPIT with recursion, so far we have not seen anyone trying to be tricky with swapping lifetimes across the invocations and using that to constrain a hidden type via the returned value.
TC: What do we think?
tmandry: I mainly just wanted to pose the question. I can probably resolve the blocking concern.
TC: Here's an example:
TC: aliemjay has also raised a separate concern about higher-ranked lifetimes here:
https://github.com/rust-lang/rust/pull/116935#issuecomment-1835699182
TC: Niko, you might find this worth a look.
E0492: borrow of an interior mutable value may end up in the final value
during const eval when no inner mutability is involved" rust#121250Link: https://github.com/rust-lang/rust/issues/121250
TC: Oli describes the situation:
We accidentally fixed a bug (by cleaning up const checking code in a way that inherently forbade the bug). This bug has been found to have a single regression. The issue is already being worked around.
The bug fix is that we now correctly forbid using associated constants that have generic parameters (either themselves whenever we get GACs, or from their trait), if those constants are used behind references. This was a hole in our checks for preventing interior mutability behind references in constants. These are not stable yet, and if the constant is generic, we cannot know whether it has interior mutability and need to reject it.
TC: Reading the issue and comments from RalfJ, it seems like a bug fix to me. Do we agree?
tmandry: It looks like we did do a crater run here. There's just one regression.
TC: …which is the one reported in the issue.
tmandry: I'd be comfortable sticking with this. Anyone think we should revert the bug fix?
pnkfelix: We're talking about accepting the current nightly behavior as the correct thing.
JT: No objection to go ahead with the behavior of current nightly.
JT: I propose we FCP this.
tmandry: I actually thought we had FCPed this, but can't find it.
Consensus: Let's do this via FCP.
Freeze
trait again (unstably) and forbid implementing it manually" rust#121501Link: https://github.com/rust-lang/rust/pull/121501
Link: https://github.com/rust-lang/rust/issues/60715
TC: Apropos of the above issue, RalfJ brought up Freeze
:
In #121250 another case came up where a
Freeze
bound would be very useful.I am more and more in agreement that we should allow
Freeze
bounds on stable. We should not allow anyFreeze
impls though (Freeze
should be implementable with a nightly feature but not without).In the previous RFC for stabilizing Freeze, t-lang said this
However, our most significant concern was around backwards compatibility. This RFC proposes to expose a new auto trait which makes it backwards-incompatible to add a field with interior mutability to an existing type which previously had no interior mutability. This proposal would require library authors who may want to add interior mutability in the future to mark their types with
PhantomData<UnsafeCell<()>>
. The RFC further addresses this restriction in two places:However, this is already a breaking change. Various aspects of working with data in
const
, and static promotion, depend on whether a type isFreeze
or not. Not exposing the bound doesn't really avoid that issue. We should figure out if they are willing to re-evaluate their position given what seems like new information.They also suggested experimenting with this as a library crate, but that doesn't work for issues like #121250.
TC: Oli now has a PR for this:
This trait is useful for generic constants (associated consts of generic traits). See the test (
tests/ui/associated-consts/freeze.rs
) added in this PR for a usage example. The builtinFreeze
trait is the only way to do it, users cannot work around this issue.It's also a useful trait for building some very specific abstrations, as shown by the usage by the
zerocopy
crate: google/zerocopy#941Open questions
- naming: Could also have a name that contains
Cell
, as the trait signals the absence ofUnsafeCell
.
TC: Regarding naming, Josh pointed out:
…while I do think
Freeze
isn't an ideal name (since it isn't self-explanatory), for the lang discussion let's try to focus exclusively on "do we want to expose this" (and if we get to it, "do we want to stabilize this in the future"). We can bikeshed naming after we settle those questions. :)
TC: What do we think?
scottmcm: I have no objections to doing this on nightly.
scottmcm: On a meta point, we've been hitting a lot of issues recently about where someone might need to make a SemVer promise about something. It seems we need a way to handle this in general.
tmandry: +1 on that observation.
Consensus: We're OK exposing this on nightly via meeting consensus.
#[deny]
inside #[forbid]
as a no-op with a warning" rust#121560Link: https://github.com/rust-lang/rust/pull/121560
TC: Nils nominates this for us and describes the problem:
Forbid cannot be overriden. When someome tries to do this anyways, it results in a hard error. That makes sense.
Except it doesn't, because macros. Macros may reasonably use
#[deny]
(or#[warn]
for an allow-by-default lint) in their expansion to assert that their expanded code follows the lint. This is doesn't work when the output gets expanded into aforbid()
context. This is pretty silly, since both the macros and the code agree on the lint!By making it a warning instead, we remove the problem with the macro, which is now nothing as warnings are suppressed in macro expanded code, while still telling users that something is up.
TC: What do we think?
NM: It seems clear to me that this is useful. What's unclear to me is whether we'd ever want to let you override a forbid. I'm thinking about macros here. I could imagine wanting to have an hiegenic opt-out from forbid.
scottmcm: If you don't want this to a hard error, why not change forbid
to deny
?
pnkfelix: There can be an unexpected interaction here between parties due to macros.
tmandry: I don't understand why we'd need a warning.
(The meeting ended here.)
Link: https://github.com/rust-lang/rust/issues/121608
TC: In #119057:
https://github.com/rust-lang/rust/issues/119057
…we decided to disallow let-else
expressions from ending in a closing curly brace as that aligned with what was specified in the RFC. We did this on the basis of an extensive analysis by dtolnay and a check across crates.io
that found no breakage. We FCPed this in:
https://github.com/rust-lang/rust/pull/119062
TC: One day after the analysis by dtolnay, an author in the ecosystem committed a change that now breaks due to our change here. This is the one and only know breakage.
TC: The nominated question is whether we want to reconsider our decision now that this has moved from zero known breakages to one known breakage. What do we think?
Link: https://github.com/rust-lang/rust/issues/120797
TC: Last week we proposed to postpone this.
…proposing that we not do this in uncommon_codepoints, and that we consider this again after we have the split-out lint that @Manishearth suggests in point 1 of #120228 (a lint about confusables with operator/punctuation).
TC: If others agree, this FCP can move forward.
PartialOrd
and Ord
for Discriminant
" rust#106418Link: https://github.com/rust-lang/rust/pull/106418
TC: This has been on and off our radar. @scottmcm in particular has strong concerns about this that he first raised 5 years ago.
scottmcm:
I remain strongly opposed to anything that makes it impossible for a library author to leave open the door to reorder their enum variants later.
https://github.com/rust-lang/rust/pull/106418#pullrequestreview-1594299402
TC: Recently, T-libs-api decided to move forward on this:
We discussed this PR in today's T-libs-api meeting. Among the team members in the meeting (myself, Amanieu, Josh, Mara), we were still on board with unconditional Ord and PartialOrd impls; no need for a marker trait. Our approvals for the FCP are registered in #106418 (comment).
Exposing the discriminant order is the intended behavior. The documentation on
mem::discriminant
mentions that changing the definition of the enum can impact the order of discriminant values, and cites the Reference for detail on how discriminant values are assigned. Amanieu summarized the stability contract as being similar to transmute — the extent to which a caller gets to rely on particular properties across library versions is up to a contract between the caller and library author.
TC: tmandry has filed a concern:
Is it important that the discriminant order remain the same between different versions of the compiler? If not I'd like to document that it could change, and left a suggestion to that effect.
@rfcbot concern stability wrt compiler version
Otherwise this proposal looks good to me. Thanks for pushing it through.
TC: (In addition to tmandry, this one probably needs scottmcm present to discuss.)
TC: What do we think?
is
operator for pattern-matching and binding" rfcs#3573Link: https://github.com/rust-lang/rfcs/pull/3573
TC: Josh proposes for us that we should accept:
And:
TC: The main topic discussed in the issue thread so far has been the degree to which Rust should have "two ways to do things". Probably the more interesting issue is how the binding and drop scopes for this should work.
TC: Last week we discussed how we should prioritize stabilizing let chains, and tmandry suggested we may want to allow those to settle first.
TC: What do we think, as a gut check?
core::mem::variant_count
" rust#73662Link: https://github.com/rust-lang/rust/issues/73662
TC: We discussed this back in 2022, per Josh:
This seems like it fits in with a broader story of enums, including things like
AsRepr
.In the absence of those, we're not sure if we want to have this function in its current state.
Josh now renominates this for us:
Nominating this for lang, because empirically we've stalled out on a potentially useful library addition on the basis of proposed lang features, which themselves seem to have stalled out.
I'd love to see
AsRepr
if someone wants to pick that back up and get it over the finish line. But also, this might be a reasonable interim step, and it doesn't seem like it does any harm to have it even if we add better solutions in the future.
Josh: We had, at the time, some other proposals on the table. So our sentiment was to ask that someone would summarize these and propose how to move forward. The result was for everything to stall out. I'm still very enthusiastic about AsRepr
. We shouldn't block this on future lang items.
Josh: Proposal: we make it clear that this isn't blocked on any future lang work. If we do that, and resolve the lang blocker, then I'll renominate this for T-libs-api.
TC: In the 2024-02-21 meeting, we decided this probably needs scottmcm present to discuss.
TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/121346
TC: Mara nominates this for us:
This PR makes this work:
and
to make it consistent with:
This is one small part of the temporary lifetimes work.
This part is backwards compatible (so doesn't need be edition-gated), because all code affected by this change previously resulted in a hard error.
TC: In the meeting on 2024-02-21, we proposed FCP merge.
TC: What do we think?
#[no_coverage]
" rust#84605Link: https://github.com/rust-lang/rust/issues/84605
TC: This is about stabilizing a #[coverage(off)]
attribute to exclude items from -Z instrument-coverage
.
Josh proposed FCP merge and nominated this for us.
There are two open questions about applying this automatically to nested functions and to inlined functions.
TC: What do we think?
Link: https://github.com/rust-lang/rust/issues/62569
TC: Prior to main()
being executed, the Rust startup code makes a syscall to change the handling of SIGPIPE
. Many believe that this is wrong thing for a low-level language like Rust to do, because 1) it makes it impossible to recover what the original value was, and 2) means things like seccomp
filters must be adjusted for this.
It's also just, in a practical sense, wrong for most CLI applications.
This seems to have been added back when Rust had green threads and then forgotten about. But it's been an ongoing footgun.
There was discussion in 2019 about fixing this over an edition, but nothing came of it.
TC: Are we interested in fixing it over this one?
#[unix_sigpipe = "sig_dfl"]
on fn main()
" rust#120832Link: https://github.com/rust-lang/rust/pull/120832
TC: This is related to the above, and is a proposal to stabilize an option to have the startup code set SIGPIPE
to the other handler. However, this does not address the problem that the Rust startup code is making this syscall at all, which means that e.g. seccomp
filters must be correctly adjusted and it's still impossible to recover the original inherited setting of this handler.
There are also the following options to this attribute that are not proposed for stabilization here:
sig_ign
: This is the current default behavior.inherent
: This would prevent the startup code from making this syscall at all.TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/117329
TC: RalfJ nominates this for us:
Nominating for t-lang discussion. This implements the t-opsem consensus from rust-lang/opsem-team#10, rust-lang/unsafe-code-guidelines#472 to generally allow zero-sized accesses on all pointers. Also see the tracking issue.
- Zero-sized reads and writes are allowed on all sufficiently aligned pointers, including the null pointer
- Inbounds-offset-by-zero is allowed on all pointers, including the null pointer
offset_from
on two pointers is always allowed when they have the same address (but see the caveat below)This means the following function is safe to be called on any pointer:
Some specific concerns warrant closer scrutiny.
LLVM 16
We currently still support LLVM 16, which does not yet have the patches that make
getelementptr inbounds
always well-defined for offset 0. The function above thus generates LLVM IR with UB. No known miscompilations arise from that, and my attempt at just removing theinbounds
annotation on old versions of LLVM failed (I got segfaults, and Nikic suggested that keeping these attribute around is actually less risky than removing them). If we want to avoid this, we have to wait until support for LLVM 16 can be dropped (which apparently is in May).Null pointers
t-opsem decided to allow zero-sized reads and writes on null pointers. This is mostly for consistency: we definitely want to allow zero-sized offsets on null pointers (
ptr::null::<T>().offset(0)
), since this is allowed in C++ (and a proposal is being made to allow it in C) and there's no reason for us to have more UB than C++ here. But if we allow this, and therefore consider the null pointer to have a zero-sized region of "inbounds" memory, then it would be inconsistent to not allow reading from / writing to that region.
offset_from
This operation is somewhat special as it takes two pointers. We do want
test_ptr
above to be defined on all pointers, sooffset_from
between two identical pointers without provenance must be allowed. But we also want to achieve this property called "provenance monotonicity", whereby adding arbitrary provenance to any no-provenance pointer must never make the program UB.1 From these two it follows that callingoffset_from
with two pointers with the same address but arbitrary different provenance must be allowed. This does have some minor downsides. So my proposal (and this goes beyond what t-opsem agreed on) is to define theptr_offset_from
intrinsic to satisfy provenance monotonicity, but to document the user-facingptr.offset_from(...)
as requiring either two pointers without provenance or two pointers with provenance for the same allocation – therefore, making the case of provenance mismatch library UB, but not language UB.Footnotes
- This property should hopefully make some intuitive sense, and it is also crucial to justify optimizations that make the program have more provenance than before – such as optimizing away provenance-stripping operations. Specifically,
*ptr = *ptr
whereptr: *mut usize
is likely going to be a provenance-stripping operation, and so optimizing away this redundant assignment requires provenance monotonicity. ↩
TC: What do we think?
#[expect]
some lints: Stabilize lint_reasons
(RFC 2383) " rust#120924Link: https://github.com/rust-lang/rust/pull/120924
TC: Since the last time this was proposed for stabilization, various unresolved questions have now been resolved, so this is being proposed again.
Hey everyone, with the
#[expect]
implementation done, I'd like to propose stabilizing this feature. I've crated two stabilization PRs, one updating the documentation and one removing the feature from rustc:
- Let's
#[expect]
some lints: Stabilizelint_reasons
(RFC 2383) #120924- Document new
#[expect]
attribute andreasons
parameter (RFC 2383) reference#1237The RFC 2383 adds a
reason
parameter to lint attributes and a new#[expect()]
attribute to expect lint emissions.
- Here is an example how the reason can be added and how it'll be displayed as
part of the emitted lint message:
- Here is an example, that fulfills the expectation and compiles successfully:
Changes from the RFC
As part of my implementation, I renamed the
#[expect]
lint fromexpectation_missing
tounfulfilled_lint_expectations
. I think the name works better with other lint attributes and is more descriptive.Resolutions of unresolved questions
Where should the
reason
parameter be allowed?
- The current implementation only allows it as the last parameter in all lint attributes
How should
#[expect(unfulfilled_lint_expectations)]
be handled?
- In the RFC, it was suggested that the
unfulfilled_lint_expectations
can be expected by outer attributes. However, it was also questioned how useful this would actually be. The current implementation doesn't allow users to expect this lint. For#[expect(unfulfilled_lint_expectations)]
the lint will be emitted as usual, with a note saying thatunfulfilled_lint_expectations
can't be expected.How should
#[expect(XYZ)]
and--force-warn XYZ
work?
- This implementation, will emit the lint XYZ, as the lint level has been defined by
--force-warn
and also track the expectation as it usually would with only the#[expect]
attribute.Updates
Since the initial report, a few questions have been discussed by the lang team, here is a quick overview of the questions and resolutions:
Should the attribute really be called
#[expect]
or is the name too generic?
#[expect]
is good (Decision)What are the semantics of the
#[expect]
attribute?
- Decision: An expectation should count as fulfilled, if a
#[warn]
attribute at the same location would result in a lint emission (Decision)Open issues
#[expect(lint)]
currently doesn't work on macros. This is in line with other lint attributes. This bug is tracked in Specifying lint levels does not work on macros #87391 and tested inexpect_lint_from_macro.rs
TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/121720
TC: We agreed to do this. tmandry now would like some feedback about the implementation:
This PR implements that consensus, but I'd like feedback on the lint naming and documentation. See the tests for examples of the lints that are added.
TC: What do we think?
c_unwind
full stabilization request: change in extern "C"
behavior" rust#115285Link: https://github.com/rust-lang/rust/issues/115285
TC: BatmanAoD proposes for stabilization:
This is a request for full stabilization of the
c_unwind
feature, RFC-2945. The behavior of non-"Rust"
, non-unwind
ABIs (such asextern "C"
) will be modified to close soundness holes caused by permitting stack-unwinding to cross FFI boundaries that do not support unwinding.When using
panic=unwind
, if a Rust function markedextern "C"
panics (and that panic is not caught), the runtime will now abort.Previously, the runtime would simply attempt to unwind the caller's stack, but the behavior when doing so was undefined, because
extern "C"
functions are optimized with the assumption that they cannot unwind (i.e. inrustc
, they are given the LLVMnounwind
annotation).This affects existing programs. If a program relies on a Rust panic "escaping" from
extern "C"
:
- It is currently unsound.
- Once this feature is stabilized, the program will crash when this occurs, whereas previously it may have appeared to work as expected.
- Replacing
extern "x"
withextern "x-unwind"
will produce the intended behavior without the unsoundness.The behavior of function calls using
extern "C"
is unchanged; thus, it is still undefined behavior to call a C++ function that throws an exception using theextern "C"
ABI, even when compiling withpanic=unwind
.
TC: We had been waiting for a crater run and analysis on this, and that has now been completed:
https://github.com/rust-lang/rust/pull/116088#issuecomment-1870577466
There were no regressions of substance.
From an implementation perspective, this does seem currently blocked on #113923, which was reverted, but that probably doesn't need to block our FCP on the language questions.
TC: What do we think?
TC: Niko expressed +1 but did not check his box. With that box, this would move into FCP.
Link: https://github.com/rust-lang/rfcs/pull/3503
TC: This has been changed to use ---
syntax with an optional infostring (that is arbitrary except for forbidding whitespace and commas).
TC: tmandry, Josh, and I are +1. What do we think?
const {}
blocks, and const { assert!(...) }
" lang-team#251Link: https://github.com/rust-lang/lang-team/issues/251
TC: This issue was raised due to discussion in a T-libs-api call. Josh gives the context:
In discussion of rust-lang/libs-team#325 (a proposal for a compile-time assert macro), the idea came up to allow
const {}
blocks at item level, and then have people useconst { assert!(...) }
.@rust-lang/libs-api would like some guidance from @rust-lang/lang about whether lang is open to toplevel
const { ... }
blocks like this, which would influence whether we want to add a compile-time assert macro, as well as what we want to call it (e.g.static_assert!
vsconst_assert!
vs some other name).Filing this issue to discuss in a lang meeting. This issue is not seeking any hard commitment to add such a construct, just doing a temperature check.
CAD97 noted:
To ensure that it's noted: if both item and expression
const
blocks are valid in the same position (i.e. in statement position), a rule to disambiguate would be needed (like for statement versus expressionif
-else
). IMO it would be quite unfortunate for item-levelconst
blocks to be evaluated pre-mono if that sameconst
block but statement-level would be evaluated post-mono.Additionally: since
const { assert!(...) }
is post-mono (due to using the generic context), it's potentially desirable to push people towards usingconst _: () = assert!(...);
(which is pre-mono) whenever possible (not capturing generics).
TC: What do we think?
Link: https://github.com/rust-lang/rfcs/pull/3514
TC: In addition to documenting the current behavior carefully, this RFC (per RalfJ)…
says we should allow float operations in
const fn
, which is currently not stable. This is a somewhat profound decision since it is the first non-deterministic operation we stably allow inconst fn
. (We already allow those operations inconst
/static
initializers.)
TC: What do we think? tmandry proposed this for FCP merge back in October 2023.
Link: https://github.com/rust-lang/rust/pull/121201
TC: RalfJ nominates this for us:
For a long time, we have allowed
align_offset
to fail to compute a properly aligned offset, andalign_to
to return a smaller-than-maximal "middle slice". This was done to cover the implementation ofalign_offset
in const-eval and Miri. See #62420 for more background. For about the same amount of time, this has caused confusion and surprise, where people didn't realize they have to write their code to be defensive againstalign_offset
failures.Another way to put this is: the specification is effectively non-deterministic, and non-determinism is hard to test for – in particular if the implementation everyone uses to test always produces the same reliable result, and nobody expects it to be non-deterministic to begin with.
With #117840, Miri has stopped making use of this liberty in the spec; it now always behaves like rustc. That only leaves const-eval as potential motivation for this behavior. I do not think this is sufficient motivation. Currently, none of the relevant functions are stably const:
align_offset
is unstably const,align_to
is not const at all. I propose that if we ever want to make these const-stable, we just accept the fact that they can behave differently at compile-time vs at run-time. This is not the end of the world, and it seems to be much less surprising to programmers than unexpected non-determinism. (Related: rust-lang/rfcs#3352.)@thomcc has repeatedly made it clear that they strongly dislike the non-determinism in align_offset, so I expect they will support this. @oli-obk, what do you think? Also, whom else should we involve? The primary team responsible is clearly libs-api, so I will nominate this for them. However, allowing const-evaluated code to behave different from run-time code is t-lang territory. The thing is, this is not stabilizing anything t-lang-worthy immediately, but it still does make a decision we will be bound to: if we accept this change, then
- either
align_offset
/align_to
can never be called in const fn,- or we allow compile-time behavior to differ from run-time behavior.
So I will nominate for t-lang as well, with the question being: are you okay with accepting either of these outcomes (without committing to which one, just accepting that it has to be one of them)? This closes the door to "have
align_offset
andalign_to
at compile-time and also always have compile-time behavior match run-time behavior".
TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/120221
TC: CE handed this one to us, since it changes the contract of macro matchers:
Right now, the heuristic we use to check if a token may begin a pattern nonterminal falls back to
may_be_ident
.This has the unfortunate side effect that a
stmt
nonterminal eagerly matches against apat
nonterminal, leading to a parse error:
This PR fixes it by more accurately reflecting the set of nonterminals that may begin a pattern nonterminal.
As a side-effect, I modified
Token::can_begin_pattern
to work correctly and used that inParser::nonterminal_may_begin_with
.
TC: What do we think?
Link: https://github.com/rust-lang/rfcs/pull/3556
TC: This seems to be about making the following work:
There are apparently use cases for this.
What's interesting is that apparently it already does, but we issue a warning that is wrong:
TC: One of the author's asks of us is that we don't make this into a hard error (e.g. with the new edition).
TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/118879
TC: Nadri describes the change:
In the discussion to stabilize exclusive range patterns (#37854), it has often come up that they're likely to cause off-by-one mistakes. We already have the
overlapping_range_endpoints
lint, so I proposed a lint to catch the complementary mistake.This PR adds a new
non_contiguous_range_endpoints
lint that catches likely off-by-one errors with exclusive range patterns. Here's the idea (see the test file for more examples):
More precisely: for any exclusive range
lo..hi
, ifhi+1
is matched by another range buthi
isn't, we suggest writing an inclusive rangelo..=hi
instead. We also catchlo..T::MAX
.
TC: What do we think?
Link: https://github.com/rust-lang/rust/issues/116907
TC: nnethercote has implemented most of RFC 3349 ("Mixed UTF-8 literals") and, based on implementation experience, argues that the remainder of the RFC should not be implemented:
I have a partial implementation of this RFC working locally (EDIT: now at #120286). The RFC proposes five changes to literal syntax. I think three of them are good, and two of them aren't necessary.
TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/118939
TC: The idea here seems to be to improve some diagnostics around macro_rules
, but this seems to be done by way of reserving the macro_rules
token more widely, which is a breaking change. Petrochenkov has objected to it on that basis, given that reserving macro_rules
minimally has been the intention since we hope it will one day disappear in favor of macro
. What do we think?
Link: https://github.com/rust-lang/rfcs/pull/3325
TC: tmandry nominated this one for us so that we could finish the bikeshed that we started in time for Rust 2024.
Lokathor laid out these options:
The three basic proposals are:
#[unsafe attr]
("unsafe space")#[unsafe(attr)]
("unsafe parens")#[unsafe { attr }]
("unsafe braces")During the lang meeting on 2023-06-06, it was requested that a summary of how each option actually looks in practice be made,so that hopefully one of the proposals can be selected based on readability.
When using an attribute, the attribute itself can be one of three basic forms:
lone token:
#[no_mangle]
#[unsafe no_mangle]
#[unsafe(no_mangle)]
#[unsafe { no_mangle }]
key-val expression:
#[link_section = ".foo"]
#[unsafe link_section = ".foo"]
#[unsafe(link_section = ".foo")]
#[unsafe { link_section = ".foo" }]
an attribute "call":
#[link_ordinal(15)]
#[unsafe link_ordinal(15)]
#[unsafe(link_ordinal(15))]
#[unsafe { link_ordinal(15) }]
There is also the issue of readability when mixed with
cfg_attr
.
Interior, around only the attribute:
#[cfg_attr(cond, unsafe no_mangle)]
#[cfg_attr(cond, unsafe(no_mangle)]
#[cfg_attr(cond, unsafe { no_mangle } )]
Exterior, around the
cfg_attr
:
#[unsafe cfg_attr(cond, no_mangle)]
#[unsafe(cfg_attr(cond, no_mangle))]
#[unsafe { cfg_attr(cond, no_mangle ) }]
TC: This is an interesting case because we are not discharging unsafety, as with unsafe { expr }
in a function body. Neither does saying unsafe
here create and push upward a type-checked obligation. Instead, the upward obligation exists regardless and there is no means to signal to the compiler that it has been discharged and no enforcement of that.
TC: Another option I've seen discussed is finding some way to make these annotations safe.
TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/118833
TC: In the 2024-01-03 call, we developed a tentative consensus to lint against direct function pointer comparison and to push people toward using ptr::fn_addr_eq
. We decided to ask T-libs-api to add this. There's now an open proposal for that here:
https://github.com/rust-lang/libs-team/issues/323
One question that has come up is whether we would expect this to work like ptr::addr_eq
and have separate generic parameters, e.g.:
Or whether we would prefer that fn_addr_eq
enforced type equality of the function pointers. Since we're the ones asking for this, we probably want to develop a consensus here. We discussed this in the call on 2024-01-10, then we opened a Zulip thread:
TC: On this subject, scottmcm raised this point, with which pnkfelix seemed to concur:
I do feel like if I saw code that had
fn1.addr() == fn2.addr()
(ifFnPtr
were stabilized), I'd write a comment saying "isn't that whatfn_addr_eq
is for?"If the answer ends up being "no, actually, because I have different types", that feels unfortunate even if it's rare.
(Like how
addr_eq(a, b)
is nice even if with strict provenance I could writea.addr() == b.addr()
anyway.)
TC: scottmcm also asserted confidence that allowing mixed-type pointer comparisons is correct for ptr::addr_eq
since comparing the addresses of *const T
, *const [T; N]
, and *const [T]
are all reasonable. I pointed out that, if that's reasonable, then ptr::fn_addr_eq
is the higher-ranked version of that, since for the same use cases, it could be reasonable to compare function pointers that return those three different things or accept them as arguments.
TC: Adding to that, scottmcm noted that comparing addresses despite lifetime differences is also compelling, e.g. comparing fn(Box<T>) -> &'static mut T
with for<'a> fn(Box<T>) -> &'a mut T
.
TC: Other alternatives we considered were not stabilizing ptr::fn_addr_eq
at all and instead stabilizing FnPtr
so people could write ptr::addr_eq(fn1.addr(), fn2.addr())
, or expecting that people would write instead fn1 as *const () == fn2 as *const ()
.
TC: Recently CAD97 raised an interesting alternative:
From the precedent of
ptr::eq
andptr::addr_eq
, I'd expect a "ptr::fn_eq
" to have one generic type and a "ptr::fn_addr_eq
" to have two. Even ifptr::fn_eq
's implementation is just an address comparison, it still serves as a documentation point to call out the potential pitfalls with comparing function pointers.
TC: What do we think?
TC: Separately, on the 2024-01-10 call, we discussed some interest use cases for function pointer comparison, especially when it's indirected through PartialEq
. We had earlier said we didn't want to lint when such comparisons were indirected through generics, but we did address the non-generic case of simply composing such comparisons.
One example of how this is used is in the standard library, in Waker::will_wake
:
https://doc.rust-lang.org/core/task/struct.Waker.html#method.will_wake
It's comparing multiple function pointers via a #[derive(PartialEq)]
on the RawWakerVTable
.
We decided on 2024-01-01 that this case was interesting and we wanted to think about it further. We opened a discussion thread about this:
Since then, another interesting use case in the standard library was raised, in the formatting machinery:
https://doc.rust-lang.org/src/core/fmt/rt.rs.html
What do we think about these, and would we lint on derived PartialEq
cases like these or no?
clippy::invalid_null_ptr_usage
lint" rust#119220Link: https://github.com/rust-lang/rust/pull/119220
TC: Urgau proposes this for us:
This PR aims at uplifting the
clippy::invalid_null_ptr_usage
lint into rustc, this is similar to theclippy::invalid_utf8_in_unchecked
uplift a few months ago, in the sense that those two lints lint on invalid parameter(s), here a null pointer where it is unexpected and UB to pass one.
invalid_null_ptr_usages
(deny-by-default)
The
invalid_null_ptr_usages
lint checks for invalid usage of null pointers.Example
Produces:
Explanation
Calling methods who's safety invariants requires non-null pointer with a null pointer is undefined behavior.
The lint use a list of functions to know which functions and arguments to checks, this could be improved in the future with a rustc attribute, or maybe even with a
#[diagnostic]
attribute.
TC: What do we think?
Link: https://github.com/rust-lang/rust/pull/120193
TC: Apparently our unstable likely
and unlikely
intrinsics don't work. There's a proposal to do some work on fixing that and stabilizing a solution here. The nominated question is whether we want to charter this as an experiment.
.await
does not perform autoref or autoderef" rust#111546Link: https://github.com/rust-lang/rust/issues/111546
TC: This was nominated for T-lang by WG-async. @tmandry said:
We discussed this in a recent wg-async meeting (notes). The consensus was that we thought the change was well-motivated. At the same time, we want to be cautious about introducing problems (namely backwards compatibility).
There should probably be a crater run of this change, and we should also work through any problematic interactions that could be caused by this change. (@rust-lang/types should probably weigh in.)
The main motivation for the change is the analogy to
.method()
, as well as to wanting async and sync to feel similarly convenient in most cases.Note that there is another analogy that works against this, the analogy to
IntoIterator
, where the lang-effect form (for _ in foo {}
) does not do autoref/autoderef. However, given that this looks very different fromfoo.await
, and taking a reference with that form is significantly more convenient (for x in &foo
orfor x in foo.iter()
vs(&foo).await
), it seemed the analogy was stretched pretty thin. So we elected to put more weight on the above two considerations.That being said, this change would need lang team signoff. You can consider this comment wg-async's official recommendation to the lang team.
TC: There's now been a crater run done for this. The result was that this breaks a small number of crates, but at least one of those crates has a large number of dependents (aws-smithy-runtime
). It can be fixed in the dependency in such a way that dependent crates do not have to make changes, but those dependent crates would need to update to a fixed version of the dependency.
(See this discussion.)
TC: What do we think?
wasm_c_abi
future-incompat
lint" rust#117918Link: https://github.com/rust-lang/rust/pull/117918
TC: daxpedda gives the context:
This is a warning that will tell users to update to
wasm-bindgen
v0.2.88, which supports spec-compliant C ABI.The idea is to prepare for a future where Rust will switch to the spec-compliant C ABI by default; so not to break everyone's world, this warning is introduced.
TC: Is this something we want to do?
Link: https://github.com/rust-lang/rust/issues/116557
TC: nikomatsakis nominated this:
We had some discussion about types/lang team interaction. We concluded a few things:
- Pinging the team like @rust-lang/lang is not an effective way to get attention. Nomination is the only official way to get attention.
- It's ok to nominate things in an "advisory" capacity but not block (e.g., landing a PR), particularly as most any action can ultimately be reversed. But right now, triagebot doesn't track closed issues, so that's a bit risky.
Action items:
- We should fix triagebot to track closed issues.
TC: What do we think?
clippy::precedence
lint" rust#117161Link: https://github.com/rust-lang/rust/pull/117161
TC: The proposal is to lint against:
These would instead be written:
Prompts for discussion:
rustc
?!
, *
, &
)?Link: https://github.com/rust-lang/rust/pull/121364
TC: This is the implementation of the item above.
Link: https://github.com/rust-lang/rust/issues/117866
TC: The question is whether to adopt the following "must define before use" rule for opaque types:
If the body of an item that may define the hidden type of some opaque does define that hidden type, it must do so syntactically before using the opaque type in a non-defining way.
This is a breaking change to RPIT. Here's an example of code that works today that would break under this rule:
This rule has relevance to the new trait solver.
TC: What do we think?
Link: https://github.com/rust-lang/rust/issues/117860
TC: The question is whether this should be true:
Unless and until RFC PR 3373 is accepted and scheduled for stabilization in some future edition, items nested inside of other items may define the hidden type for opaques declared outside of those items without those items having to recursively be allowed to define the hidden type themselves.
The context is that we allow this:
Should we accept spiritually-similar TAIT code unless and until we decide to go a different direction with the language?
Link: https://github.com/rust-lang/rust/issues/117861
TC: The question is whether this should be true:
At least until the new trait solver is stabilized, any item that is allowed to define the hidden type of some opaque type must define the hidden type of that opaque type.
TC: This is important for the new trait solver.
TC: Here's one reason for that. The new trait solver treats strictly more code as being a defining use. It's also more willing to reveal the hidden type during inference if that hidden type is defined within the same body. This rule helps to avoid inference changes when moving from the old solver to the new solver. Adding this restriction makes TAIT roughly equivalent to RPIT with respect to these challenges.
TC: (This question is entirely orthogonal to how we notate whether an item is allowed to define the hidden type of an opaque.)
Link: https://github.com/rust-lang/rust/issues/117865
TC: The question is whether this should be true:
The compiler is allowed to rely on whether or not an item is allowed to define the hidden type of an opaque type to guide inference.
Here's the door that this would close:
If this rule is adopted, then after TAIT is stabilized, it will not be possible in a fully backward compatible way to later change the rules that determine whether or not an item is allowed to define the hidden type in such a way that an item in existing code that uses an opaque type could switch (without any code changes) from being not allowed to define its hidden type to being allowed to define it.
TC: This is of importance to the new trait solver.
TC: Here's one reason for this. When we're type checking a body and we find an opaque type, we sometimes have to decide, should we infer this in such a way that this body would define the hidden type, or should we treat the type as opaque (other than auto trait leakage) and infer based on that? Depending on that, we can get different answers.
TC: If we did not let inference rely on this, then we would be closing the door on later allowing inference to rely on this without provoking changes in inference.
TC: (This question is entirely orthogonal to how we notate whether an item is allowed to define the hidden type of an opaque. Answering this question in the affirmative would update one element of the #107645 FCP.)
Link: https://github.com/rust-lang/rfcs/pull/3519
TC: We discussed this on 2023-11-22. The general feeling seemed to be that we wanted to find some way to enable this, including for raw pointers, NonNull
, etc., but we were feeling unsure about the path to get there. We asked the author to cogitate on this and come back with a revised plan.
TC: The author did that, and we had an extensive discussion on 2024-01-17 without consensus. We have open threads for discussing this asynchronously.
Here's the thread for the proposal:
And here's the thread for the broader question of whether we want arbitrary self types at all:
TC: We have a design meeting schedule for 2024-02-28 for this.
None.
Link: https://github.com/rust-lang/lang-team/pull/236
Link: https://github.com/rust-lang/lang-team/pull/237
None.
S-waiting-on-team
Link: https://github.com/rust-lang/rust/pull/116675
Link: https://github.com/rust-lang/rust/pull/116863
Link: https://github.com/rust-lang/rust/pull/117329
Link: https://github.com/rust-lang/rust/pull/118879
AsyncIterator
back to Stream
, introduce an AFIT-based AsyncIterator
trait" rust#119550Link: https://github.com/rust-lang/rust/pull/119550
unnameable_types
" rust#120144Link: https://github.com/rust-lang/rust/pull/120144
Check your boxes!
Link: https://github.com/rust-lang/rfcs/pull/2375
Link: https://github.com/rust-lang/rfcs/pull/3325
Link: https://github.com/rust-lang/rfcs/pull/3336
Link: https://github.com/rust-lang/rfcs/pull/3379
Link: https://github.com/rust-lang/rfcs/pull/3503
gen
keyword in 2024 edition for Iterator
generators " rfcs#3513Link: https://github.com/rust-lang/rfcs/pull/3513
Link: https://github.com/rust-lang/rfcs/pull/3514
Link: https://github.com/rust-lang/rfcs/pull/3543
Link: https://github.com/rust-lang/rfcs/pull/3550
main
(RFC 1260)" rust#28937Link: https://github.com/rust-lang/rust/issues/28937
#[no_coverage]
" rust#84605Link: https://github.com/rust-lang/rust/issues/84605
Link: https://github.com/rust-lang/rust/pull/104087
PartialOrd
and Ord
for Discriminant
" rust#106418Link: https://github.com/rust-lang/rust/pull/106418
anonymous_lifetime_in_impl_trait
" rust#107378Link: https://github.com/rust-lang/rust/pull/107378
Link: https://github.com/rust-lang/rust/pull/112879
c_unwind
full stabilization request: change in extern "C"
behavior" rust#115285Link: https://github.com/rust-lang/rust/issues/115285
Link: https://github.com/rust-lang/rust/pull/116675
Link: https://github.com/rust-lang/rust/pull/116935
Link: https://github.com/rust-lang/rust/pull/117457
Link: https://github.com/rust-lang/rust/pull/117468
REDUNDANT_LIFETIMES
lint to detect lifetimes which are semantically redundant" rust#118391Link: https://github.com/rust-lang/rust/pull/118391
unnameable_types
" rust#120144Link: https://github.com/rust-lang/rust/pull/120144
Link: https://github.com/rust-lang/rust/pull/120700
Link: https://github.com/rust-lang/rust/issues/120797
Link: https://github.com/rust-lang/rust/pull/121346
Link: https://github.com/rust-lang/rust/pull/118879
None.