---
# System prepended metadata

title: Triage meeting 2024-01-17
tags: [triage-meeting, T-lang, minutes]

---

---
title: Triage meeting 2024-01-17
tags: ["T-lang", "triage-meeting", "minutes"]
date: 2024-01-17
discussion: https://rust-lang.zulipchat.com/#narrow/stream/410673-t-lang.2Fmeetings/topic/Triage.20meeting.202024-01-17
url: https://hackmd.io/mdjFFEhXTmurVGQQHgKnfA
---

# T-lang meeting agenda

- Meeting date: 2024-01-17

## Attendance

- People: TC, scottmcm, Urgau, Lukas Wirth, Santiago, Waffle, tmandry, nikomatsakis, Josh, pnkfelix

## Meeting roles

- Minutes, driver: TC

## Scheduled meetings

- 2024-01-17: "Discuss RFC 2442: Simple postfix macros" [#247](https://github.com/rust-lang/lang-team/issues/247)
- 2024-01-24: "Bounds for RPIT/RPITIT/async fn" [#246](https://github.com/rust-lang/lang-team/issues/246)
- 2024-01-31: "Design meeting: Rust for Linux" [#240](https://github.com/rust-lang/lang-team/issues/240)

Edit the schedule here: https://github.com/orgs/rust-lang/projects/31/views/7.

## Announcements or custom items

(Meeting attendees, feel free to add items here!)

## Rust 2024 review: Priority issues

Project board: https://github.com/orgs/rust-lang/projects/43/views/5

### Tracking Issue for Lifetime Capture Rules 2024 (RFC 3498) #117587

**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're currently working on the stabilization report for that.  We're hoping to have that ready this month.

NM: :dancer:

### Reserve gen keyword in 2024 edition for Iterator generators #3513

**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 reserving the keyword.

NM: For the edition we definitely want to accept the RFC and take this step.  But there is probably other work here we can push forward this year.

Waffle: `gen` as a token is used in `rand`.

TC: There has been discussion of that.

scottmcm: I'd be happy to accept an RFC that says how we'd want generators to work.

JT: I think we had said that we didn't want to do keyword reservation for a feature not designed yet and that was speculative.  What we have a proposal for here is a mostly-designed feature that we probably want.  It's currently being implemented on nightly.  I'm perfectly fine taking this even though we might iterate on the design.  It'll probably ship in the edition anyway.

scottmcm: (Not said synchronously or discussed, but:) I would say that `throw` was at least as designed for what it should do as generators, since it was mentioned in future work for an accepted RFC, for example.

### Tracking issue for promoting `!` to a type (RFC 1216) #35121

**Link:** https://github.com/rust-lang/rust/issues/35121

TC: We're hoping to land a lint here and work is progressing on that.

Waffle: I'm implementing it.  There are some open design questions.  The short version is that the never type feature currently has a number of backward compatibility hacks.

TC: As a reminder to all, this is what we want to lint against:

```rust
fn never_type_fallback() { unsafe {
    if false { panic!() } else { transmute::<_, _ /* ?0 */>(()) }
    // later in fallback:     ?0 := ()
    // after ! stabilization: ?0 := !
}}
```

Waffle: I'll write up more about this.

## Rust 2024 review: Needs triage

### Match ergonomics means bindings have different types in patterns and match arm; cannot deref references in pattern #64586

**Link:** https://github.com/rust-lang/rust/issues/64586
**Link:** https://github.com/rust-lang/rust/issues/105647

TC: We had a design meeting on 2023-12-13 about this proposal.  The consensus was general agreement about the goals.  We probably want `&` patterns everywhere, and we probably want to fix the problem of `mut` resetting the binding mode; i.e. we want to make it such that adding `mut` doesn't change the type of the binding.  Nadrieril expressed that with agreement on those goals, he can invest further time in writing code, performing crater runs, etc.

TC: The main edition-relevant change is the fact that `mut` changes the binding mode.

What do we think?

tmandry: Sounds like "accepted" to me, given that we had a design meeting about it.

JT: We should definitely put it on the board.  It's something we wanted to improve.

tmandry: I feel like we had consensus on making an edition-relevant change.

tmandry: We probably need an RFC in the near future.

NM: I'm kind of in favor of using `&` to solve the problem.  It seems like there are many details there.

scottmcm: If this is an edition change, which it seems to be, 
then we need an RFC soon.

NM: Maybe we could lint on this.  Why do we care about `mut` specifically anyway?

Waffle: It's because of cases like this:

```rust
fn f(x: &u32) {
    match x {
        mut y => /*
                  * currently: y: u32
                  * proposal:  y: &u32
                  */
    }
}
```

NM: Agreed it makes sense if someone wants to push on this.  We do need an RFC.

TC: So maybe "discuss".

tmandry: +1.

*Consensus*: Let's mark this as "discuss" on the board.

### RFC: constants in patterns - #3535

**Link**: https://github.com/rust-lang/rfcs/pull/3535

TC: We accepted this RFC and it completed FCP (I'll merge it later today).  The RFC itself does not propose to require an edition to implement these changes, even the breaking ones.  It does propose as a future possibility:

> To avoid interpreting `derive(PartialEq)` as a semver-stable promise of being able to structurally match this type, we could introduce an explicit `derive(PartialEq, StructuralPartialEq)`.  However, that would be a massive breaking change, so it can only be done over an edition boundary.  It probably would also want to come with some way to say "derive me all the usual traits" so that one does not have to spell out so many trait names.

What do we think?

JT: I'd be in favor of removing that magic and requiring it to be explicit over an edition.  This would be trivial in `cargo fix`.

tmandry: If we automatically derived `PartialEq` if you derived `StructuralPartialEq`, that would be fine.  And similarly we could derive `PartialEq` if you derive `Eq`.

JT: +1.

NM: This situation is depressing.

scottmcm: The list is already too long and we should have a feature to declare sets of derives and makes it shorter.

NM: Stepping back, there's the question of what we want to do over the edition, then there's the question of ergonomics fixes. I would be happier if we could address the need to write `PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Hash` all the time -- and get the structural case as part of that.

NM: Would we be willing to make this a hard error with no ergonomics support at all?

tmandry: If we have a `cargo fix`, then that adds `StructuralPartialEq` to all the crates in existence...

NM: I don't like it.  There are going to be memes about it, that's for sure.

scottmcm: The fix is great for existing code, but for new code, I don't really want to write it.

pnkfelix: The trait isn't stabilized, right?  That's implicit in this whole discussion?  Part of the process would be stabilizing that.

tmandry: I was skeptical that we would have this for Rust 2024.

NM: +1.

pnkfelix: It seems having groups would solve a lot of these issues.  We should shift our focus to that.

NM: +1.

scottmcm: This could pull in the discussion of perfect derives.

NM: On a meta note, it'd be interesting to have something on our page about describing the dependency graph underlying our plans.  This is an interesting case of that.

TC: So to confirm, we're happy doing the other breaking changes in the RFC without an edition, as the RFC proposed?

all: +1.

TC: So we'll move it to "reject"?

NM: I don't want to talk about it again, so probably "reject".

JT: We've talked before about parameterized derive.  We could have deriving `Eq` mean all the things by default, and it could have an option to not derive `StructuralPartialEq`.

pnkfelix: Wasn't the main goal of having `StructuralPartialEq` to allow people to implement their own `PartialEq` while still allowing derive of `StructuralPartialEq`?

tmandry: There are SemVer implications here also.

scottmcm: We'd have to ensure that you've implemented `PartialEq` with the derive of `StructuralPartialEq`.

tmandry: I would like a way out of the SemVer hazard, but I don't see a way for Rust 2024.

NM: In some ways, the SemVer hazard is better than the proposed ergonomic hit.

JT: We're not closing any doors here; we could always offer an opt-out ("I don't want `StructuralPartialEq`") in the future, and offer a simpler way to easily derive/impl it for a hand-implemented `PartialEq`.

*Consensus*: We'll mark this as "reject" and separately discuss how to make progress on what we want to improve here.

## Nominated RFCs, PRs, and issues

### "Detect `NulInCStr` error earlier." rust#119172

**Link:** https://github.com/rust-lang/rust/pull/119172

TC: nnethercote nominated this for us:

> [Detect `NulInCStr` error earlier by] making it an `EscapeError` instead of a `LitError`. This makes it like the other errors produced when checking string literals contents, e.g. for invalid escape sequences or bare CR chars.
>
> NOTE: this means these errors are issued earlier, before expansion, which changes behaviour. It will be possible to move the check back to the later point if desired. If that happens, it's likely that all the string literal contents checks will be delayed together.
>
> One nice thing about this: the old approach had some code in `report_lit_error` to calculate the span of the nul char from a range. This code used a hardwired `+2` to account for the `c"` at the start of a C string literal, but this should have changed to a `+3` for raw C string literals to account for the `cr"`, which meant that the caret in `cr"` nul error messages was one short of where it should have been. The new approach doesn't need any of this and avoids the off-by-one error.
>
> In short, the delayed C NUL str check is inconsistent with all other string literal checks. If it ships in its current state, we're stuck with that behaviour permanently. If we move it earlier right now before it ships, we have the option to delay it (and all other string literal checks) later on (as implemented in #118699). So if we do this in the next few days, we avoid a one-way door shutting.

(This also has some relationship with: https://github.com/rust-lang/rust/pull/118699)

TC: On the basis of this observation, we decided to revert the stabilization of C string literals from Rust 1.76:

https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/rfc.203349.3A.20mixed.20utf8.20literals

TC: However, we still need to decide the issue before we can move to restabilize.  What do we think?

JT: What was the rationale for wanting to do this earlier?

TC: Consistency.

scottmcm: This would be the one exception that errors in strings are a lexical issue.  We could always move it later.

JT: Why was this originally done late?

scottmcm: I'd reference #118699.  There are reasonable arguments that some of these things should be later.

tmandry: I have an intuition that a lexer should be simple, for Rust.  Putting these kind of checks in the lexer feels wrong to me.  But I'm in favor of doing what's expedient now for getting this out the door while leaving doors open.

JT: I'd propose that we defer discussion of whether we might want to do this later, and approve doing this at lexing time for now, since it leaves the door open later to change this.

scottmcm, tmandry, niko, pnkfelix: +1.

*Consensus*: Let's do this.

### "Arbitrary self types v2" rfcs#3519

**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: Here's what the author came back with, in summary:

The goal here is that we want receivers like `NonNull<Self>` to work.  The problem is that `NonNull` could later add a method that shadows your method with this receiver.  How do we prevent breakage and not constrain `NonNull` from adding methods?

The answer goes as follows.  Suppose we have a `Receiver`/`Deref` chain such that `A<B<C>>` derefs to `B<C>` which derefs to `C`.

When we're resolving methods, there is an *outer* level of iteration that follows along this deref chain, checking first `A<B<C>>` (et al.), then `B<C>` (et al.), then `C` (et al.).

But there's also an *inner* level of iteration that occurs for each link in that chain.  For `A<B<C>>`, e.g., we check for:;

- `impl C { fn method(self: A<B<C>>) }`
- `impl B<C> { fn method(self: A<B<C>>) }`
- `impl A<B<C>> { fn method(self: A<B<C>>) }`

We pick the *first* of those for which there is a match (the "most nested").  If more than one matches, we accept the code and lint about it at the level of warn-by-default.  The idea here is that people will switch to the fully-qualified syntax on seeing the warning, and this will keep warning-free code unambiguous.

As applied to `NonNull`, this means that if someone writes `impl Foo { fn foo(self: NonNull<Foo>) }` and we later add a `foo` method to `NonNull`, we won't break that person's code, we'll just produce a warning that can be fixed by making the call fully-qualified.

The author's full response starts here:

https://github.com/rust-lang/rfcs/pull/3519#issuecomment-1856141480

In the 2024-01-10 call, we said we would read so that we could discuss, and we opened a Zulip thread:

https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Arbitrary.20self.20types.20v2.20RFC

TC: What do we think, or would we like to propose this one for a design meeting?

NM: We already have this problem today.  It seems the recommendation here was that things with methods should't implement `Deref`.

JT: We have methods on some smart pointers.

scottmcm: I would like to see the example, because we're almost always good about `ManuallyDrop` and `Box` and such having associated functions that are self-less.  We have them for things where we control the deref target -- like deref to slice -- but deref to *user* type I don't know an example.

NM: I found this [unstable fn](https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-Rc%3CMaybeUninit%3CT%3E,+A%3E), but it's pretty narrow in scope (and meets Scott criteria above).  But I didn't look too hard.

scottmcm: That's on `Rc<MaybeUninit<>>`, so it can't shadow a *user* method -- it's us shadowing our own method.

JT: This proposal proposes to give priority to use code with a receiver rather than the type in question.  And it would warn about it.  That handles the ambiguity for that direction.  The other direction probably can't happen in practice.

tmandry: It can if the impl is generic, if the upstream impl is generic over the downstream type.

JT: I don't think that can happen, since the proposal bans having a generic receiver.

tmandry: But clearly the `Self` type could be generic.  But it seems less likely that way around.

NM: Do we think will be more or less likely with custom receiver types?  I'm trying to see where the recommendation to not add methods isn't adequate.

JT: `NonNull` is an example of this.  Same for raw pointers.

NM: These wouldn't implement `Deref`?

JT: But they would implement `Receiver`.

scottmcm: Can someone remind me why raw pointers and `NonNull` need to work here?

TC: NM made an argumen in the thread about how these are the main use case.

NM: To me, they're super useful, because you want to use them to avoid e.g. stacked borromws issues.

scottmcm: I feel like you'd have to newtype it to be safe.

NM: But why does it have to be safe?  I know that for rayon this was super annoying.

JT: There are also places this is needed for C++ interop.

NM: So the argument here is that we'd be discouraged from adding new methods for `NonNull`.

scottmcm: When I look at `NonNull`, I'm sure this isn't the full set of methods that we want.

TM: We could make an `.as_receiver()` on raw pointers that wrapped it in a canonical newtype which is designed to be used as a receiver type.

TC: As a procedural matter, we asked the author to come back with a proposal here.  What do we think about that proposal and want to feed back?

NM: I have two concerns. One that it's complicated, but partly that's inherent in method call resolution, but also that it only protects against adding methods in one direction (i.e., adding a method to the outer type vs adding a method to the inner type with a receiver self).

Waffle: The proposal suggests that this direction is the one that we want to protect against, since the other direction is kind of impossible.  To mention the inner type, you have to know about the outer type.

NM: But that assumes that the set of methods on the outer type don't grow.

Waffle: No, that's irrelevant.

tmandry: Because we resolve in favor of the inner type.

NM: OK, I see.  I'm reading the comment and pondering it.  I should read the proposal in depth.  I'm getting convinced.

tmandry: I feel like we should find some way forward for raw pointers.

scottmcm: My specific issues with the proposal (as copied above):

- Anything resolving via `Deref` doesn't fix conflicts for `NonNull` as a receiver without that doesn't involve `Deref`.
- It's the opposite direction from normal `Deref`, which seems confusing.
- The set of things on `NonNull` is definitely not complete, so a solution that's "we can't add the new strict provenance method that we know we want" without it being break.

JT: I think this proposal does resolve all of the compatibility hazards that Niko raised.

JT: I'm glad we asked for this proposal, and I would ask the question now, and we should answer over time, do we actually want arbitrary self types?  Because I think this is adding the complexity needed to add arbitrary self types without SemVer hazards.

scottmcm: That feels overly strong in a statement to me.  By analogy to `Deref`, we could do this without otherwise addressing it.

TC: +1 to JT's point.  My feeling also, in reviewing the proposal in detail, was that this was exactly the complexity required if we wanted this at all while addressing the SemVer hazards.  scottmcm: doesn't what you propose boil down to keeping the SemVer hazards?

scottmcm: Yes, but maybe it's controllable by limiting the types to which this applies.  And it means that some types are not appropriate to be used as arbitrary self types.

JT: Perhaps people should read the proposal, and we should evaluate whether we want arbitrary self types at all or not?

*Consensus*: Let's read and review the proposal and all give some thought to arbitrary self types in general.

Here's the thread for the proposal:

https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Arbitrary.20self.20types.20v2.20RFC

And here's the thread for the broader question of whether we want arbitrary self types at all:

https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Do.20we.20want.20arbitrary.20self.20types.3F

(The meeting ended here.)

### "Add lint against function pointer comparisons" rust#118833

**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.:

```rust
/// Compares the *addresses* of the two pointers for equality,
/// ignoring any metadata in fat pointers.
///
/// If the arguments are thin pointers of the same type,
/// then this is the same as [`eq`].
pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool { .. }
```

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:

https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Signature.20of.20.60ptr.3A.3Afn_addr_eq.60

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()` (if `FnPtr` were stabilized), I'd write a comment saying "isn't that what `fn_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 write `a.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: 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:

https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Function.20pointer.20comparison.20and.20.60PartialEq.60

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?

### "unsafe attributes" rfcs#3325

**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?

### "Tracking Issue for cfg-target-abi" rust#80970

**Link:** https://github.com/rust-lang/rust/issues/80970

TC: Chris Denton proposes to stabilize `#[cfg(target_abi = "..")]`:

> ## Stabilization report
>
> I propose to stabilize `#[cfg(target_abi = "...")]`, This implements [RFC-2992](https://rust-lang.github.io/rfcs/2992-cfg-target-abi.html) (cfg-target-abi). The implementation was completed in #86922 and this tracking issue was subsequently marked as ready for stabilization by @joshtriplett.
>
> ### Summary
>
> This stabilizes the `cfg` option called `target_abi`:
>
> ```rust
> #[cfg(target_abi = "macabi")]
> ```
>
> And `target_abi` is also shown when using `--print=cfg` (output snipped for length):
>
> ```
> > rustc --print=cfg --target aarch64-apple-ios-sim
>
> target_abi="sim"
> target_arch="aarch64"
> target_env=""
> target_os="ios"
> target_vendor="apple"
> ```
>
> Without `target_abi`, cfgs are limited to `target_arch`, `target_vendor`, `target_os`, and `target_env`. However, some targets are only differentiated by their abi and thus it's necessary to resort to parsing the full target string in a build script when there's a need to disambiguate. For example, the following targets are the same if only using stable `target_*` `cfg`s:
>
> * `aarch64-apple-ios` and `aarch64-apple-ios-sim` (arch: "aarch64", vendor: "apple", os: "ios", env: "")
> * `x86_64-pc-windows-gnullvm` and `x86_64-pc-windows-gnu` (arch: "`x86_64", vendor: "pc", os: "windows", env: "gnu")
>
> ### Notes
>
> The `target_abi` defaults to `""` (the empty string) and most targets don't set it. This is similar to `target_env` where if it's not needed for disambiguation then it's often not set.
>
> In the future `target_abi` could be an array of zero or more properties that affect the ABI (e.g. `softfloat` may be combined with other ABI properties), However, this feature can be added later without breaking compatibility.

TC: Given the recent discussions over ABI issues, I made sure RalfJ was aware of this, and he had no particular concerns.

### "Make `ConstPropLint` lint run on promoteds" rust#119432

**Link:** https://github.com/rust-lang/rust/pull/119432

TC: Oli nominates this for us:

> Nominating for T-lang for awareness.... TLDR: existing lints will trigger in more situations where we were missing them before. In our test suite this causes duplicate lint emissions, but they are deduplicated for users.

gurry:

> Fixes #117949 wherein the lint didn't fire for the following promoteds:
>
> * SHL or SHR operators in a non-optimized build
> * any arithmetic operator in an optimized build
>
> What I have done here is simply enabled `ConstPropLint` to run on promoted bodies by removing the relevant `if` check.
>
> After this change _all_ promoted arithmetic operators will lint _in both non-optimized and optimized builds_. On the flip side programs containing the above mentioned overflowing promoteds that were accepted earlier will now be rejected. Hope that is okay from a backward compatibility standpoint.
>
> I have added tests covering all overflowing promoted & non-promoted ops for both compile-time and runtime operations and for optimized as well as non-optimized builds.
>
> I had to amend some existing tests to make them pass and had to delete a couple that were set to pass despite overflows.
>
> This PR increases the number of duplicate diagnostics emitted (because the same operator might get linted in both the promoted MIR and the main MIR). I hope that is an acceptable trade-off given that we now lint overflows much more comprehensively than earlier.

What do we think?

### "Uplift `clippy::invalid_null_ptr_usage` lint" rust#119220

**Link:** 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 the [`clippy::invalid_utf8_in_unchecked` uplift](https://github.com/rust-lang/rust/pull/111543) 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
>
> ```rust
> // Undefined behavior
> unsafe { std::slice::from_raw_parts(ptr::null(), 0); }
> // Not Undefined behavior
> unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); }
> ```
>
> Produces:
>
> ```
> error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused, consider using a dangling pointer instead
>   --> $DIR/invalid_null_ptr_usages.rs:14:23
>    |
> LL |     let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0);
>    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
>    |                                                  |
>    |                                                  help: use a dangling pointer instead: `core::ptr::NonNull::dangling().as_ptr()`
> ```
>
> ### 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?

### "Decision: semantics of the `#[expect]` attribute" rust#115980

**Link:** https://github.com/rust-lang/rust/issues/115980

TC: @nikomatsakis gives this background:

> This issue is spun out from #54503 to serve as the decision issue for a specific question. The question is what the 'mental model' for the `expect` attribute should be. Two proposed options:
>
> 1. The expectation is fulfilled, if a #[warn] attribute in the same location would cause a diagnostic to be emitted. The suppression of this diagnostic fulfills the expectation. ([src](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Expect.20attribute.20mental.20model/near/341522535)) (Current implementation in rustc)
> 2. The expectation is fulfilled if removing the `#[expect]` attribute would cause the warning to be emitted. ([src](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Expect.20attribute.20mental.20model/near/354082551))
>
> @xFrednet created a [list of use cases](https://hackmd.io/@xFrednet/expect-attr-use-cases) to help with the discussion of these two models; they found both models work equally well, except for [use case 4](https://hackmd.io/@xFrednet/expect-attr-use-cases#Use-case-4-Suppress-lints-from-CI) which would only be possible with the first model.

TC: ...and proposes that we adopt option 1.

### "Support overriding `warnings` level for a specific lint via command line" rust#113307

**Link:** https://github.com/rust-lang/rust/pull/113307

TC: We discussed in the 2023-09-26 meeting, but were unsure of the question we were being asked.  @jieyouxu has since replied:

> I believe I wanted to ask that if the command line indeed forms the root of the tree, or if it actually overrides the source annotations.

TC: On that basis, @tmandry replied:

> ### Nesting
>
> I think the command line (specifically `-A`, `-W`, `-D` flags) should form the root of the tree. We have `--cap-lints`, `--force-warn`, and `-F` (forbid) for overriding the source. (Actually the mental model documented in the [rustc book](https://doc.rust-lang.org/rustc/lints/levels.html) is that `force-warn` and `forbid` still form the root of the tree, but cannot be overridden; I think the distinction is mostly academic.)
>
> That's almost all the expressive power one could want along this axis. One wrinkle is that `--forbid` is overridden by `--cap-lints`, while `--force-warn` is not. If we wanted full fine-grained control we could always add `--force-allow` and `--force-deny`.
>
> ### `warnings`
>
> Regarding the meaning of `warnings`, it _is_ a simpler mental model for this to mean "the set of things that are warn-by-default". But this ignores what I perceive to be a common (and valid) use case, which is to disallow _all_ warnings in a codebase: In other words, prevent code from being checked in that causes warnings to be printed to a user's screen. Of course, for this to be practical one must control the version of rustc being used to build a codebase, but that is common in monorepo setups.
>
> ### Conclusion
>
> Given that there is an existing use case that relies on documented behavior, I think we should continue to treat `warnings` as a "redirect" for all warnings that come out of a particular level of the tree. Interpreting `-Awarnings -Wfoo` in the way proposed by this PR would muddy the (already complicated) mental model and add inconsistency between CLI and the command line, as noted by @oli-obk.
>
> A different group, like `default-warnings`, could be used to mean "the set of things that are warn-by-default". The compiler could further warn users that specify `-Awarnings -Wfoo` on the command line to use `-Adefault-warnings -Wfoo` instead.

TC: Where do we want to go from here?

### "`.await` does not perform autoref or autoderef" rust#111546

**Link:** 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](https://hackmd.io/G6ULofyXSIS4CK9u-jwYRg)). 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 from `foo.await`, and taking a reference with that form is significantly more convenient (`for x in &foo` or `for 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](https://rust-lang.zulipchat.com/#narrow/stream/187312-wg-async/topic/Perform.20autoref.2Fautoderef.20on.20.2Eawait.20-.20.23111773).)

TC: What do we think?

### "Add `wasm_c_abi` `future-incompat` lint" rust#117918

**Link:** 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.
>
> Addresses https://github.com/rust-lang/rust/issues/71871

TC: Is this something we want to do?

### "`refining_impl_trait` only fires on public traits" rust#119535

**Link:** https://github.com/rust-lang/rust/issues/119535

TC: We recently in Rust 1.75 stabilized RPITIT/AFIT.  Along with that, somewhat unusually, we stabilized two "please confirm you understand how Rust works" lints against the new feature.

One lint is `async_fn_in_trait`:

```rust
pub trait Foo {
    async fn foo() -> impl Sized;
    //~^ WARN use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
    //~| NOTE you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
    //~| NOTE `#[warn(async_fn_in_trait)]` on by default
    //~| HELP you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change
}
```

The other is `refining_impl_trait`:

```rust
pub trait Foo {
    fn foo() -> impl Sized;
}

impl Foo for () {
    fn foo() -> () {}
    //~^ WARN impl trait in impl method signature does not match trait method signature
    //~| NOTE add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
    //~| NOTE `#[warn(refining_impl_trait)]` on by default
    //~| HELP replace the return type so that it matches the trait
}
```

TC: We decided to make the first lint fire only when the trait is crate public.  We did the same for the second lint but it was discussed less explicitly.

TC: tmandry proposes that we make the second lint always fire:

> - The `async fn` lint is only temporary to help avoid footguns created by missing language features, and we want to make non-footgunny uses more convenient.
> - Refinement is a mechanism that will always exist and is fundamental to trait implementations.
> - Refinement's ability to "punch through" abstraction boundaries can happen accidentally, even within a crate.

TC: CE has advocated to keeping it so that the lint only fires for publicly-reachable traits:

> My understanding was that private traits are always crate-local, and be always fixed in a non-semver-breaking way, so it makes no sense to bug people about things local to their crate.
>
> The refines lint being public-only has to do with the fact that refinement is a possibly-accidental over-promising of trait bounds on an implementation. when that implementation is published as part of a public (and reachable) trait in a library, then it becomes a breaking change to remove it. It doesn't make sense to enforce that internally within a crate, imo.

TC: What do we think?

### "RFC: Syntax for embedding cargo-script manifests" rfcs#3503

**Link:** https://github.com/rust-lang/rfcs/pull/3503

TC: We discussed this for most of one triage meeting in November without reaching any consensus.  There is a design meeting proposal, but we have not yet scheduled it for a date.  At Josh's suggestion, Ed Page has renominated this for us.

Earlier context included:

> @**scottmcm** raised these interesting points:
>
> > My biggest question here is how much it should be thought of as tied to the script use, and thus to the `#!`.
> >
> > My instinct is that either
> >
> > 1. This is tied to the shebang, so there's only one of them, to be consumed only by whatever tool is in the shebang, and rustc completely ignores it, like we completely ignore the shebang line.  And thus the "`` ``` `` right after the shebang" syntax seems entirely reasonable to me.
> > 2. This is a general tool feature, for which there will be multiple of them, and for which they'd want something like tool attribute namespacing so there's a clear route to lots of them under understood namespaces, and are a full part of the parsed structure of the crate, maybe included in rustdoc, etc.  (Like perhaps `--document-private-items` on a crate would show an embedded `rustfmt::config` block somewhere, one day.)
>
> @**nikomatsakis** noted that, even if it's tied to a shebang, he doesn't see a reason to limit it to only one.
>
> @**tmandry** suggested that:
>
> > With my lang hat on, I don't see a reason we should RFC a feature that only allows `cargo` front matter, without specifying a path to generalizing it to other tooling. If we want to be conservative in what we stabilize, let's approach that in the stabilization rather than in the RFC.
>
> In the meeting, @**nikomatsakis** suggested that we seem misaligned on the purpose of this.  Others in the meeting suggested that the syntax should derive from a clear understanding of that purpose and the eventual goals for it.

TC: We've since discussed this asynchronously here:

https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Syntax.20for.20embedded.20tooling.20metadata/near/409126434

We seemed to agree that:

- `.rs` files should parse as valid Rust.
  - I.e., we don't want to expect the runner to have to strip out these blocks.
- Rust itself should not validate the content of these blocks.

The open questions include:

- Should there be only one of these blocks or potentially many?
  - If we only support one block, tools that need many will define their own syntax for delineation.
    - It could be awkward to change our mind later on this, as tools will have already defined this delineation in their own SemVer commitments.
  - Supporting only one is simpler (for us) and gives tools flexibility.
  - But if we want IDEs to eventually support syntax highlighting for these blocks (e.g. based on the file type indicated in the info string), then we probably need to handle this ourselves.
    - tmandry: "Making that kind of editor integration possible is important to me, even though I expect that many editors won't support that level of generality in their syntax definitions today."
- Relatedly, do we want to support info strings?
- Should the shebang be optional or required when using these blocks?
  - It's more conventional for the shebang to be optional.
  - If it's required, people may end up writing e.g. `#!/bin/false` as a workaround.
  - The shebang is meaningless for Windows.
- What syntax to use?
  - Triple (or more) backticks.
    - Upside: Beginners may prefer this, but of course they would due to Markdown familiarity.
    - Downside: Even figuring out how to encode those backticks literally in this document is difficult.  Users would need to know advanced Markdown to encode these Rust files.  Some markdown parsers (e.g. the one for Discord) are not sophisticated enough to allow this.
      - tmandry: "I think that is a serious quality of life hazard we should be cognizant of. If I were to boil it down to a principle I would say that Rust should feel pleasant to use, and that includes in places like github comments, chatrooms, and forums, where many people write Rust code every day!"
    - Downside: It's a new matched string literal syntax when Rust already uses `#` for this.
  - Triple (or more) hashes (`###`).
    - Upside: This would look natural with the shebang and would suggest association with the shebang.
    - Upside: Rust already uses matched `#`s for literals.
    - Downside: We may want a space before the info string.
  - Triple (or more) dashes (`---`).
    - Upside/downside: This is associated with YAML header blocks.
    - Downside: It's a new matched string literal syntax when Rust already uses `#` for this.
    - Downside: This may look less natural with an info string, or we may want a space before it.

There is an open experiment on the `cargo` side that simulates the various syntax options, e.g.:

- https://github.com/rust-lang/cargo/pull/13241
- https://github.com/rust-lang/cargo/pull/13247

TC: What do we think?

### "TAIT decision on whether nested inner items may define" rust#117860

**Link:** https://github.com/rust-lang/rust/issues/117860

TC: The question is whether this should be true:

> Unless and until [RFC PR 3373](https://github.com/rust-lang/rfcs/pull/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:

```rust
trait Trait {}
struct S;
const _: () = {
    impl Trait for S {} // Allowed.
};
```

Should we accept spiritually-similar TAIT code unless and until we decide to go a different direction with the language?

### "TAIT decision on "may define implies must define"" rust#117861

**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.)

### "TAIT decision on "may not define may guide inference"" rust#117865

**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][].)

[#107645 FCP]: https://github.com/rust-lang/rust/issues/107645#issuecomment-1571789814

### "Uplift `clippy::precedence` lint" rust#117161

**Link:** https://github.com/rust-lang/rust/pull/117161

TC: The proposal is to lint against:

```rust
-2.pow(2); // Equals -4.
1 << 2 + 3; // Equals 32.
```

These would instead be written:

```rust
-(2.pow(2)); // Equals -4.
1 << (2 + 3); // Equals 32.
```

Prompts for discussion:

- Is this an appropriate lint for `rustc`?
- How do other languages handle precedence here?
- Is minus special enough to treat differently than other unary operators (e.g. `!`, `*`, `&`)?

### "types team / lang team interaction" rust#116557

**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.

## Action item review

- [Action items list](https://hackmd.io/gstfhtXYTHa3Jv-P_2RK7A)

## Pending lang team project proposals

None.

## PRs on the lang-team repo

### "Add soqb`s design doc to variadics notes" lang-team#236

**Link:** https://github.com/rust-lang/lang-team/pull/236

### "Update auto traits design notes with recent discussion" lang-team#237

**Link:** https://github.com/rust-lang/lang-team/pull/237

## RFCs waiting to be merged

### "RFC: constants in patterns" rfcs#3535

**Link:** https://github.com/rust-lang/rfcs/pull/3535

## `S-waiting-on-team`

### "Stabilize `anonymous_lifetime_in_impl_trait`" rust#107378

**Link:** https://github.com/rust-lang/rust/pull/107378

### "make matching on NaN a hard error, and remove the rest of illegal_floating_point_literal_pattern" rust#116284

**Link:** https://github.com/rust-lang/rust/pull/116284

### "Fix `non_camel_case_types` for screaming single-words" rust#116389

**Link:** https://github.com/rust-lang/rust/pull/116389

### "warn less about non-exhaustive in ffi" rust#116863

**Link:** https://github.com/rust-lang/rust/pull/116863

### "Delay literal unescaping" rust#118699

**Link:** https://github.com/rust-lang/rust/pull/118699

### "Add lint against function pointer comparisons" rust#118833

**Link:** https://github.com/rust-lang/rust/pull/118833

### "Detect `NulInCStr` error earlier." rust#119172

**Link:** https://github.com/rust-lang/rust/pull/119172

### "Rename `AsyncIterator` back to `Stream`, introduce an AFIT-based `AsyncIterator` trait" rust#119550

**Link:** https://github.com/rust-lang/rust/pull/119550

## Proposed FCPs

**Check your boxes!**

### "RFC: inherent trait implementation" rfcs#2375

**Link:** https://github.com/rust-lang/rfcs/pull/2375

### "unsafe attributes" rfcs#3325

**Link:** https://github.com/rust-lang/rfcs/pull/3325

### "MaybeDangling" rfcs#3336

**Link:** https://github.com/rust-lang/rfcs/pull/3336

### "Add text for the CFG OS Version RFC" rfcs#3379

**Link:** https://github.com/rust-lang/rfcs/pull/3379

### "add float semantics RFC" rfcs#3514

**Link:** https://github.com/rust-lang/rfcs/pull/3514

### "RFC: patchable-function-entry" rfcs#3543

**Link:** https://github.com/rust-lang/rfcs/pull/3543

### "Stabilise inline_const" rust#104087

**Link:** https://github.com/rust-lang/rust/pull/104087

### "Implement `PartialOrd` and `Ord` for `Discriminant`" rust#106418

**Link:** https://github.com/rust-lang/rust/pull/106418

### "Stabilize `anonymous_lifetime_in_impl_trait`" rust#107378

**Link:** https://github.com/rust-lang/rust/pull/107378

### "Report monomorphization time errors in dead code, too" rust#112879

**Link:** https://github.com/rust-lang/rust/pull/112879

### "`c_unwind` full stabilization request: change in `extern "C"` behavior" rust#115285

**Link:** https://github.com/rust-lang/rust/issues/115285

### "Decision: semantics of the `#[expect]` attribute" rust#115980

**Link:** https://github.com/rust-lang/rust/issues/115980

### "References refer to allocated objects" rust#116677

**Link:** https://github.com/rust-lang/rust/pull/116677

### "Prevent opaque types being instantiated twice with different regions within the same function" rust#116935

**Link:** https://github.com/rust-lang/rust/pull/116935

### "Stabilize Wasm target features that are in phase 4 and 5" rust#117457

**Link:** https://github.com/rust-lang/rust/pull/117457

### "Stabilize Wasm relaxed SIMD" rust#117468

**Link:** https://github.com/rust-lang/rust/pull/117468

### "static mut: allow mutable reference to arbitrary types, not just slices and arrays" rust#117614

**Link:** https://github.com/rust-lang/rust/pull/117614

### "Add `REDUNDANT_LIFETIMES` lint to detect lifetimes which are semantically redundant" rust#118391

**Link:** https://github.com/rust-lang/rust/pull/118391

## Active FCPs

### "Avoid non-local definitions in functions" rfcs#3373

**Link:** https://github.com/rust-lang/rfcs/pull/3373

### "Fix `non_camel_case_types` for screaming single-words" rust#116389

**Link:** https://github.com/rust-lang/rust/pull/116389

### "revert stabilization of const_intrinsic_copy" rust#117905

**Link:** https://github.com/rust-lang/rust/pull/117905

### "Undeprecate lint `unstable_features` and make use of it in the compiler" rust#118639

**Link:** https://github.com/rust-lang/rust/pull/118639

### "Warn on references casting to bigger memory layout" rust#118983

**Link:** https://github.com/rust-lang/rust/pull/118983

## P-critical issues

None.
