--- title: Triage meeting 2025-11-19 tags: ["T-lang", "triage-meeting", "minutes"] date: 2025-11-19 discussion: https://rust-lang.zulipchat.com/#narrow/channel/410673-t-lang.2Fmeetings/topic/Triage.20meeting.202025-11-19/ url: https://hackmd.io/m-7R6nBwR-23M9V0UHb2TQ --- # T-lang meeting agenda - Meeting date: 2025-11-19 ## Attendance - People: TC, nikomatsakis, Aapo, dianne, Tomas, Jack, Amanieu, theemathas, Josh, Nadri, tmandry, Eric Holk, Yosh Wuyts, scottmcm, bendn ## Meeting roles - Driver: TC - Minutes: Tomas ## Scheduled meetings None. 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!) ### Proposal to adopt Rust in CPython Josh: There is a Python proposal to adopt Rust in CPython (slowly and incrementally). Reach out, welcome them, offer help. Similar to what we do for Rust for Linux. TC: Tomas, do you want to reach out and set up a call with the folks. Tomas: Yep, happy to! (TODO: Tomas.) Josh: Note that Niko and Jack are already on the discord; be good ta talk with them. https://discuss.python.org/t/pre-pep-rust-for-cpython/104906/141 ### Cloudflare outage Josh: They had an issue in a backend service database. The actual error handling had an `unwrap` in their Rust code. This panicked, brought down the whole server across the Rust fleet. There may be bad takes on the internet. So heads-up. Josh: Personal take: in 2017 [Cloudbleed](https://en.wikipedia.org/wiki/Cloudbleed) meant a buffer handling resulted in other user's secrets sent to the wrong users. In 2025, a database configuration error combined with some bad error-handling code caused some servers to go down. Bad for the Internet and lessons learned in both case, but that's still an improvement. ### Guest attendee items TC: For any guests who are present, please note in this section if you're attending for the purposes of any items on (or off) the agenda in particular. ### Moving right along TC: As we've been doing recently, due to the impressive backlog, I'm going to push the pace a bit. If it's ever too fast or you need a moment before we move on, please raise a hand and we'll pause. ### Design meeting at 12:30 EST / 09:30 PST / 17:30 CET TC: Remember that we have a design/planning meeting that starts half an hour after this call ends. ### Next meeting with RfL We're meeting with RfL *today* (on 2025-11-19) to review the status of RfL project goals. https://github.com/rust-lang/rfcs/pull/3614 ## Nominated RFCs, PRs, and issues ### "Explicitly export core and std macros" rust#139493 **Link:** https://github.com/rust-lang/rust/pull/139493 TC: We've been trying to get a good description on the name resolution rules change. This is the first stabilization by this contributor, and we've now looked into backfilling some help here. Jane has volunteered to dig into this. She's doing amazing work with Petrochenkov on documenting name resolution. We can do the FCP after she posts the rule relevant to this PR. Josh: This is definitely not an intro-level difficulty. Wow. Props to them for working on a hard problem. Jack: Are they feeling okay? TC: Yes, we received back a positive response. Jack: As hard as we are, I don't want people to feel they get turned away and can't go back. Glad they had positive feeling. ### "`format_args` deduplicates consts with interior mutability or destructor" rust#145739 **Link:** https://github.com/rust-lang/rust/issues/145739 Josh: This came up in the format dotted implicit arguments RFC. We noticed an issue with the way the current handling is desugared. Theemathas has already been on it for a few months. If you have an object with interior mutability or destructor, constants will be deduplicated into a single constant that would run destructors e.g. This is different from passing args to function because there you would get separate copies. You can observe this with interior mutability. TC: What we're talking about is this: ```rust const X: TypeWithDrop = TypeWithDrop::new(); format_args!("{X}{X}"); // Desugars to: format_args!("{X}{X}", X=X); ``` TC: It goes against our rule that something should be dropped as many times as you see it. So this feels pretty wrong. Apropos of Josh's RFC, you end up with the same question about deref. Trying to stay consistent with that forces Josh's RFC to do some really iffy things. Josh: This is already an issue within the language, but this RFC... Tyler: Don't we normally capture format args by reference? TC: The desugaring is exactly what's above. Tyler: If you print a type that's not copy, you can use the value again. dianne: This happens for constants which don't have places. So it has to create a temporary value. And the question is whether it creates a single temporary or multiple ones. theemathas: a format_args takes a place expression and it automatically adds a reference in front of it. Josh: That's what I was going to say. This is the desugaring. And then all format arguments are borrowed. Tyler: Sounds like we handle const specially. TC: It's borrowed. But the operand of a borrow is a place expression context. Tyler: So if you mention a const, it cretaes a temporary implicitly. Niko: Did the RFC specify the alternative (deduplicated) desugaring initially? Josh: It didn't specify desugaring initially. We discussed it later and came up with a desugaring that we would like. But what's the RFC is compatible with this. Niko: It seems edge-casey. It's hard to see that people would depend on it. I want Rust users to be able to unwrap these constructs down to a simler core. A simple desugaring is probably what we watnt to go with here. Jack: Is there an example of that desugaring? TC: Here's the alternate desugaring: ```rust! const X: TypeWithDrop = TypeWithDrop::new(); format_args!("{X}{X}"); // Desugars to (today): format_args!("{0:}{0:}", X); // Proposed desugaring: format_args!("{0:}{1:}", X, X); ``` Niko: The zeros and ones are appended based on the arguments that exist. It wouldn't be hard for us to preserve the existing behaviour. Can we say if it's just a simple place expression we'd desugar it to something else. Niko: thought it intuitively it would desugar to this: ```rust // How Niko thought about this in his head: format_args!("{X}{X}", /* X = X */); ``` Josh: It's trivial to match it to whatever behaviour we want. TC: Where this gets hard in Josh's RFC is this question: ```rust! use core::ops::Deref; struct W<T>(T); impl<T> Drop for W<T> { fn drop(&mut self) { println!("drop"); } } impl<T> Deref for W<T> { type Target = T; fn deref(&self) -> &Self::Target { println!("deref"); &self.0 } } struct S<T> { f: T } fn main() { const X: W<S<u8>> = W(S { f: 0 }); println!("{X.f} {X.f}"); //~ Format string to desugar. println!("-- 1:"); println!("{} {}", X.f, X.f); //~ Desugaring 1. println!("-- 2:"); { let x = X; println!("{} {}", x.f, x.f) }; //~ Desugaring 2. println!("-- 3:"); println!("{f} {f}", f=X.f); //~ Desugaring 3. } ``` TC: There's an interaction with deref. It's about the execution order. Niko: A rule I could imagine: * `{X}` -- for a simple identifier, we add `X = X` if it is not defined * `{A (.F)+}` -- for a path expression, we add a fresh identifier `FRESH = A.F+` ```rust println!("{X} {X} {X.f} {X.f}"); //~ Format string to desugar. // becomes println!("{X} {X} {FRESH0} {FRESH1}", X = X, FRESH0 = X.f, FRESH1 = X.f); ``` TC: Then `X` gets dropped three times in that example. Niko: Sure. dianne: Would be drawing the line on path expressions or simple place expressions? Path expressions that refer to constants are generally not place expressions. Niko: I was distinguishing identifiers from non-identifiers. You have the option of making a named identifier. It's not about any kind of expression. All things considered, I prefer the simple "everything gets desugared to a fresh name". But I did want to explore what a backwards compatible version would look like. I think it makes sense in a path-dependent fashion, but not in a fresh fashion. If there were serious backwards compatibility hazards, this is what I'd go for. Josh: I agree that the approach that ends up with 3 (instead of 1 or 4) is path dependent. Josh: It's not just about constants. You can put any ident into implicit format args. Including a nullary struct constructor. Today that gets deduplicated. You get one of those and use it several times. That's differetn from passing it into a function. Seems inconsistent with how we evaluate in the language. Josh: Additional thought-provoking case ([play](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=6668c606e99401a6834f63b4fc5ba6f2)): ```rust struct NoisyDrop; impl Drop for NoisyDrop { ... } impl Display for NoisyDrop { ... } // Today: calls drop only once println!("{NoisyDrop}{NoisyDrop}"); ``` Scott: Are there any other future things where we could share stuff. Where we would prefer not to make a bunch of copies. The more I think about it from this discussion, the more I think each things should be a separate capture. We have optimization issues where putting a println deoptimizes a loop because of the implicit taking of a reference and that messing up LLVM. TC: Niko, I see your note about backticks in the chat. Is anyone working on it? Niko: Not backticks specifically. I want you to put arbitrary expressions there. TC: All this is a vibe check. The lang team is generally inclined to align this with this with our model that the number of drops should match the number of mentions. We're open to a proposal and would want to see the crater run. Josh: I can write that up. ### "Revert "Do not check privacy for RPITIT."" rust#146470 **Link:** https://github.com/rust-lang/rust/pull/146470 TC: This is about private-in-public. The model Petrochenkov has is: if you have an associated type, then anything in the definition of that type that's private should fire a hard error. This can get surprising where the definition of the associated type is an `impl Trait` where the trait is a private trait. It's clear why private types should be an error. It's less clear why a private trait shoud be an error, but for the moment, he's pushing for a consistent behavior where this would cause a hard error too. Tyler: Where's a starting point for something I can read? TC: The best message is this one from Petrochenkov: https://github.com/rust-lang/rust/pull/146470#issuecomment-3528254000 > So, an associated type's interface can contain > * Generics > * Predicates > * Default type > * Bounds > > And we just don't differentiate and check all of them when reporting the hard error version of the priv-in-pub check. Originally that was simply a conservative choice allowing to avoid thinking too much about which of those can actually leak something private. Maybe predicates and bounds cannot actually leak anything, then they can be demoted to a lint, we just need to have some more or less convincing proof of that written. Jack: What prompted this PR? I'm confused on the timeline, why is the PR open. Nadri: this issue it seems: https://github.com/rust-lang/rust/issues/143531 TC: This was originally part of a PR that was cleaning up other things. They reverted this piece because that was a breaking change and needed lang nomination. And now they're reverting the revert. Jack: So this change was desired and now it needs to be okayed? TC: Yes. Niko: Why is this change desired? Is this part of Petrochenkov's RFC about private things from the past? TC: This is similar to Ralf's quests. Petrochenkov's quest is to align everything with the private-in-public RFC. This is part of that ongoing quest for alignment. Josh: Sounds like this might potentially be something reviewable by the types team? Niko: Not types. TC: https://github.com/rust-lang/rust/pull/146470#issuecomment-3530539418 ```rust! #![feature(impl_trait_in_assoc_type)] pub trait Super {} trait PrivTr: Super {} impl Super for () {} impl PrivTr for () {} pub trait PubTr { type F1: Super; fn f1() -> Self::F1; } impl<T> PubTr for T { type F1 = /* This might be private; but what is this? */ //~^ error[E0446]: private trait `PrivTr` in public interface fn f1() -> Self::F1 {} } ``` TC: This is the core of what we're getting to here. You have something in the definition of an associated type that may be private. The model Petrochenkov has is that, if it's a type then this is a problem. You're going to be able to project to a private type. You have a priv-in-pub violation. TC: Where it gets more ambiguous is, what if the associated type definition is an impl trait that has item bounds that include a private trait. Is that a problem? TC: Petrochenkov is saying maybe not but so far we've implemented everything like this to be a hard error. Jack: I don't think this is a problem. If you're saying "you can't name this in this way", I'd want to see a good example of why you wouldn't want that. It doesn't make a ton of sense when you have type = private type. But maybe you want to contraint the generics. So my first instinct is it's not a problem. TC: The model from the RFC is this: ```rust struct S; pub fn f() -> S { S } // Not OK. // But... mod m { pub struct S; } pub fn f() -> m::S { m::S } // OK. ``` TC: In the second one, `S` is transitively not public. From the outside of this crate you still can't name `S`. But in the priv-in-pub model this is okay. The first one, though, is not OK, since the item is not marked public at the def-site. Jack: This is fine, right? Aliases, associated types are fundamentally different. You're specifically giving a different name to a type. And I think it's okay. TC: So you're saying?: ```rust struct S; pub type T1 = S; // Jack: This is OK. ``` Jack: Yes, that's my argument. This is ok. You can imagine something like this: ```rust struct S<T>(_t: T); pub type T1 = S<u32>; // Jack: This is OK. ``` Niko: I agree with what Jack is saying -- that our module system is extremely complicated and flexible and allows you to make many different paths by which to get to a name. Petrochenkov's RFC was trying to establish a simple rule. But sometimes it'd be useful to be able to expose a type through an alias of some kind. But the flipside is it can be hard to know if you have exposed it to something. Niko: So you can say you can expose the final visibility. So what you could do is make the type `pub` and have it in a private module and have an alias to it. Where Petrochenkov's RFC comes in is, if there are inherent methods and I'm writing some unsafe code, in older versions of Rust we had return values with types you couldn't possibly named, that was hard. Petrochenkov's RFC says error when we come to MIR. Niko: In the compiler, type aliases get erased quickly. In my mind though, they are separate entities that can be named. There's a big question here. I agree it's useful to sometimes to make these aliases. But I'm also aligned with it being useful to look at the declaration and know. TC: At the declaration site, the pub there is a capability marker. It's the maximum visibility the item can get. Niko: That's the design we landed on. TC: Makes sense. As applied here, in the thread, the unsatisfying answer seemed to be it was a bit unclear of whether or how this needed apply to traits in this context. Niko: I start with: what reasoning an unsafe code author might want. If you have a private trait you know that ... (e.g. no one outside will call it). Jack: Is there some interaction with RTN here? Niko: I could imagine a default impl in specialization and knowing that it implements a private trait would affect normalization. Tyler: You could use this to produce a value that implements this private trait, hand it to a function that implements that trait. You can't access any items on that trait, but you can still treat that value as an opaque black box you can hand back. Niko: Tyler I think this was your example: ```rust // Crate A trait PrivateToMyCrate; pub fn foo(t: impl PrivateToMyCrate) { } pub trait Get { type Output; fn get_output() -> Self::Output; } impl Get for () { type Output = impl PrivateToMyCrate; // ... fn get_output() -> Self::Output { () } } // in Crate B: crate_a::foo(<() as Get>::get_output()) ``` Niko: I don't think there's any loss of having a program that can't be modified to do what you want to do. ```rust // Crate A mod private { pub trait PrivateToMyCrate; } pub fn foo(t: impl private::PrivateToMyCrate) { } pub trait Get { type Output; fn get_output() -> Self::Output; } impl Get for () { type Output = impl private::PrivateToMyCrate; // ... fn get_output() -> Self::Output { () } } // in Crate B: crate_a::foo(<() as Get>::get_output()) ``` TC: If we were doing Rust today, I'm not sure I'd adopt this capabilities model for the item visibility (maybe!); it's a bit subtle. But we've accepted the RFC, and people are driving towards making it consistent. So let's make it consistent with the model. Josh: There may be reasons for the future. But for now consistency is important. TC: I'm looking at the crater results. We're taking some breakage here to do this. Jack: If there's not a lot of breakage, I'm in favour of just doing it. It's compatible with removing it later. If we're unsure today, it makes sense to be a bit more conservative with what we allow. But it depends on how bad the breakage is. Niko: That might also be an interesting plate to look for patterns. What are the "capabilities of a trait": * Knowing if it is implemented for a particular type? * :point_up: this is to me a very interesting one * Using its members --> this is not possible * Knowing that it "exists" * today it *can* appear in the signature of a public function... maybe? But perhaps you can never *call* that function? So arguably this holds? TC: I proposed FCP merge. Niko: I don't love the way we manifested the model. If we were starting form scratch, though, I'd definitely want some way to cap the capabilities. And from that perspective it's useful to talk about what the capabilities are. My two tests would be what kind of things unsafe code might want. And what are there things you can do to leak the capabilities? Can you delete a private trait? TC: Side note, this doesn't work as I would expect on the PR: ```rust trait PrivTr {} impl PrivTr for () {} pub trait PubTr { #[expect(private_bounds)] //~ warning: this lint expectation is unfulfilled fn f1() -> impl PrivTr; //~^ warning: trait `PrivTr` is more private than the item `PubTr::f1::{anon_assoc#0}` } ``` Tyler: Is this only a lint? TC: Yes, this is on the trait side, not the impl side. (The team took a 30 minute break here.) --- TC: Did anyone check their boxes? (looks) Not yet. Tyler: The way Niko defined the capabilities helped clarify to me. I'd love to see that written out. And potentially check a box on that basis. Niko: Yeah I was thinking of taking stab at writing that out on the issue. But my preference would be at least a dedicated issue, possibl y an RFC. Tyler: If you're taking about a refinement of the earlier RFC to fill some gaps, that makes sense to me. It seems like this way is probably the way to go but I'm not entirely sure. Tyler: I'd be happy to brainstorm and write it out with you. Niko: I'll write something shorter and maybe we can refine it later. TC: What would the separate issue be for? Niko: Declaring the list of capabilities that we expect. If you have visibility on an item in a module what can and can't you do with that? Tyler: We can try out the model of making a PR to an existing RFC and keep the version history. TC: If you wanted to dig into revising the private-in-public RFC, you'd have a lot of work cut out for you. https://rust-lang.github.io/rfcs/2145-type-privacy.html Niko: This also make sense to fit this into the Reference. TC: +1. ## Nominated RFCs, PRs, and issues (part 2) People: TC, nikomatsakis, Josh, tmandry, Aapo, Nadri, dianne, Tomas, Amanieu, Jack, Yosh ### "Local variable deallocated out of order in the panic path?" rust#147875 **Link:** https://github.com/rust-lang/rust/issues/147875 Nadri: Context is: ```rust struct Wrap<T: Display>(T); impl<T: Display> Drop for Wrap<T> { fn drop(&mut self) { println!("{}", self.0); } } fn main() { let x; { let y = 1; x = Wrap(&y); panic!(); } } ``` This compiles and prints `"1"`, because the `y` is kept longer on the basis that its `Drop` code is not significant. [This](https://github.com/rust-lang/rust/issues/147875#issuecomment-3434579232) explains why, which to me reads like "doing otherwise would confuse LLVM/optimize worse". Nadri: A local variable is kept for longer than it should. It's observable and surprised theemathas. I found it surprising too. This was a conscious choice made in the compiler for something to do with LLVM. But it has a language impact. My intuition is that this should not compile. Niko: I know why this compiles; I can give the background. I agree this feels like a bug. I'd call it a borrow-checker bug. It's useful to look at the MIR. What Nadri expects (and what I think is reasonable) is something like this: * Panic statement * which flows to StorageDead(y) * which flows to Drop(x) * and we report an error because `StorageDead(y)` is occurring even though `x` is live and has borrowed `y` What happens is when we're on unwinding paths we omit `StorageDead`s because it improves codegen quality. "You're just going to pop the whole stack anyway". ```rust! fn main() { let x; { let y = 1; x = Wrap(&y); // error `y` does not live long enough return } } ``` Niko: What I think we ought to do is adding a synthetic StorageDead. We used to accept programs like this: ```rust! fn foo() { let x = 1; let y: &'static i32 = &x; loop { } } ``` Niko: We always pretend the loop terminates even if it doesn't. We could always drop the storage in the order we want. Josh: +1. If we're going to visibly drop these things we should always do it in the correct order. It's fine to do as-if optimizations, but it should *appear* as if things are dropped in order if they're dropped at all. Niko: The great thing about MIR, borrow checker and codegen is that they stay in sync. The bad thing is that you could accept programs that change on optimization and behavior that's visible even thought it shouldn't be. Tyler: This has resulted in unsoundness in the generativity library; not sure what that is. TC: It implements the thing from Ralf's paper to mint unique lifetimes. Josh: The GhostCell thing? TC: Yes; generativity uses drop order tricks and a macro to mint the unique lifetime without forcing things into a closure. Tyler: My sense is: we should fix it but it may be quite hard to do. https://docs.rs/generativity Niko: +1. I'm not sure you mean it'll be hard because of breaking changes or compiler performance reasons. Both are plausible. Tyler: I meant potential breakage. Niko: This is easy for us to do a FCW if we want. TC: Even if it is a breakage we can do it carefully. ### "Support composing two deref coercion adjustments" rust#148320 **Link:** https://github.com/rust-lang/rust/pull/148320 TC: Rust today allows multiple coercions. If you look at code like this: https://github.com/rust-lang/rust/pull/148320#issuecomment-3539749305 TC: If you have a chain of coercions one through two to three. We'll go from three to one. It'll use the unsized coercion. This also comes up for the Least Upper Bounds. When you have a LUB, the compiler can ICE sometimes. I reported a bug. https://github.com/rust-lang/rust/issues/148283 TC: From the types side, there are questions to answer about what's in the realm of possibility, what the implementation constraints are, what might make sense, etc. I nominate it here for two reasons. One, and the main one, is that I want to hear from Niko on the history here. Also, I think there's a lang side to this in terms of what we'd expect in terms of the user-facing behavior of what code is run and what code is not run. Niko: It did indeed say that we should do unsized (?) coercions. I agree with theemathas that we shouldn't do them. The history's kind of a mess. We have to try to straighten it out. Jack: I think this is entirely within Types. I don't think this is a Lang thing. There have been Lang decisions that have been delegated to Types. I'm assigned to review this, it's on my list. Niko: I like that suggestion. Josh: That was going to be my recommendation as well. You can detect the distinction with this behaviour. But there's not obviously a clear visible reason for one behaviour or the other. This is well within Type's purview to go out and figure it out. If there is something user visible Types would let us know. TC: I agree the types should figure out what's going on, what's possible. But the behavior at runtime, in this case, seems the kind of user-facing behavior where I would expect input from lang. I'd prefer to see a dual FCP with lang/types due to that. Tyler: I'm fine delegating as long as any impact on our ability to evolve the language in the future (adding new coersions etc.) I'd want that flagged. TC: In terms of "flagged", what do you mean exactly? That they CC us? Tyler: I'd expect to be on the FCP. Niko: I'd prefer to avoid excessive FCPs. We can document some parameters on some high level perspectives and Types can decide whether that works for tem. Jack: to Tyler's point: this is true for a lot of things. I don't think Lang needs to be involved in a lot of the Types team's decision. And they have a history of bringing Lang in when there's need for it. But here I think there's going to be one implementation that makes most sense. Let me do the revie, let me come up with an idea and I'll loop in lang if there are things that are questionable. Tyler: That sounds good to me. TC: I broadly agree with that. But as we're trying to drill down into what these cases mean, I want us to write down the details of the delegations. The Types team is largely composed of people implementing type system. But how do we distinguish that from the Petrochenkov's issue we discussed above. It's not clear why we shouldn't delegate that one and ones like it to compiler-fcp. Maybe we should! That's why I'd like to write it down. The scope, responsibilities, when it comes back to lang, etc. But as long as we are still dealing with things ad-hoc, without such a written delegation, I don't see dual-FCP ing things where there is overlap as a big issue. Doing that gives us visibility on how the language is changing. Niko: It's possible we should be delegating. There's a distinction between Types and Compiler. Delegating to Petrochenkov in my mind is separate from delegating tot he Types team. In some criteria I am interested in bound expectations. I expect the shortest path possible if there's more than one path. It'd be interesting to try to think what the delegation would we do. Jack: Niko, that's sort of right. But I wonder how much you're saying that with the Types hat on where you understand the implementation and how much this is a Lang thing. The Lang team co-chartered the Types team with the Compiler team in mind that there's some level of Lang space that a team focused on that area is going to be the main expert. But e.g. name resolution is similar but not exactly in that position. If the Lang team felt there was too much name resolution falling on them, then it would make sense. But it's not. I think it's shown that it works because the Types team has made strong decisions like this one. Where the Types team clarified the semantics and tied it with implemenation. In the last 3 years, the Types team has made half the FCPs as the Lang team. Can you imagine adding another 50% workload to the Lang team and add that load on them? TC: I don't think lang team should be on most Types FCPs. I've followed much types team work closely, and the vast majority of those FCPs are cleanly in the domain of types. I distinguish certain categories of PRs where there is meaningful effect on the user interface of the language. And this falls in that category, I think. There were a number of good examples of this effective and specific delegation in the work on type alias impl trait. The lang team made some specific directional decisions, in consultation with types (e.g. https://github.com/rust-lang/rust/pull/116935, https://github.com/rust-lang/rust/issues/116652, the "may define == must define" rule, the "opaque type within its defining scope acts exactly like an infer var" rule, etc.), and from there, the types team did a large number of types-only FCPs to follow through on those. That was great. Josh: We're going from the specific to the general. We started with this issue but now we're talking about a general policy. We should have this discussion, but also we should make sure we don't block this issue on it. Josh: I'm aligned with what Jack was saying with the sheer number of FCPs. There will be some FCPs where we will need to be included. One kind of unknown-unknown is that Types is in a better position to know where something falls into Lang's scope to pull in. We should write down the scoping of what scope the Types think. I'd ask Jack and the Types team to write the scope down and then we can amend it if we need more precision. But we have an effective delegation at the moment and should make it more effective and more precise if we need to. Niko: I think we should move on from this topic but it is something that should be discussed. Some kind of meeting and writing down sharpened criteria would be valuable. I'd also want more of the Types people involved. Niko: For this issue, Jack is on these calls, we should let him see what he finds out. TC: +1 to that. TC: On the meta point, sometimes it is useful to go from the specific to the general. It's good to have the texture of a concrete example on hand for when we later dig into the general point. Josh: Sounds like we should continue to have a conversation. Do we have people to set that conversation up? Jack: I'll work with Niko on it. ### "Stabilize the `supertrait_item_shadowing` feature" rust#148605 **Link:** https://github.com/rust-lang/rust/pull/148605 TC: Amanieu, last week we looked at this. We named the lints. And looking at the Reference side we realized this affects method resolution so there should be a Reference PR. Amanieu: I'm happy with whatever lint names the Lang team recommends. For the Reference PR I'll look into it and write something up. TC: Thanks. Also, on the Reference side, there are two pieces to this: name resolution and method resolution. Obviously name resolution is not yet documented, but if you could just add the bullet point to the name resolution stub that says the one rule, that'd be good, as then when Jane fills out the stub she can incorporate it in. Amanieu: Sounds good. Jack: The `shadowing_supertrait_items`, there's a fix me for the allow. Could it be done prior to the stabilization? Amanieu: I can do it. I don't think it matters since no one is using. Josh: Generally, the closer we can do to make stabilization just flipping the feature on, the better. Amanieu: Would you like the lint renaming done in a separate PR? Josh: If it's no trouble, it would be nice to do it in a separate PR. Josh: Generally, we shouldn't be spending time on naming lints. To the extent there's something that aligns with existing terms we should delegate that to e.g. the compiler team. They can come back to us if they need a specific term. TC: It would be great for somebody else to do it. We need to communicate how we'd like it to be done, what good and bad lint names are, etc. As we've seen recently, when a lint name comes in that is named according to our practices, we approve it quickly without significant discussion as part of our overall FCP. So that hard part, as I see it, is working out how to get other people to name it to the standards we expect. At the point that happens, I don't know that it much matters if we're still FCPing it. Josh: What I'm saying is it's a big deal if we're doing even the rubber stamp that implies we should be stamping it. Just as a perfect name leads to a five-second rubberstamp, an improper name should give us five-second delegate to the right people to do this. This shouldn't even be in our scope. TC: It comes down having a team that we can safely delegate this to who are excited about producing names with the same care and attention as the Lang team. The other alternative, of course, would be saying that the lint names just don't matter, and so we're OK if these aren't treated with care. But I think the names do matter and should be treated carefully. Jack: Lint teams don't matter. They're either for looking them up and copy/pasting from the compiler. They do matter, but not enough to warrant spending 30 minutes for the Lang team. Josh: We have to spend time to figure out whom to delegate them to. I'm arguing that we should be delegating them. And we can always undelegate things. And we should just empower teams to do things. Tyler: I agree the names matter but I also agree that it doesn't matter to the degree of spending 30 minutes in a meeting. I'd love to delegate it but also write guidelines so anyone (not just a team) can do it. Maybe we need a design meeting where we come up with a list Niko: Seems like a place where champions can have a role. TC: +1. TC: Back to this item, I propose we wait for next week when the Reference PR is up before proposing FCP merge. Personally, I've reached a point where I prefer to not propose FCP merge myself or check a box until the Reference PR is there. Josh: Have you reached the point where you think the FCP shouldn't be proposed at all until that is done? TC: It's my personal view that the Lang team should consider reviewing the Reference language as part of our duty of care when changing the language. So, as a personal matter, I've reached a point where I don't feel comfortable checking a box or proposing FCP merge without that (where a Reference PR is otherwise appropriate). But we haven't yet adopted this as a team policy, so as mentioned, it's a personal view, and I don't object to someone else proposing FCP merge. Niko: That all seems fine. I agree with TC I'd like to see us doing Reference additions earlier. I also agree we've not really put this into practice and that fcp merge at this moment seems ok, though I'd be inclined to hold off on checking my box (as we have often done...) until a Reference PR is available. ### "const validation: remove check for mutable refs in final value of const" rust#148746 **Link:** https://github.com/rust-lang/rust/pull/148746 TC: I proposed FCP, Josh and I checked a box. TC: There are two classes of rules for const evaluation. One is for the const eval itself. Then we have another category of rules of what can appear as a final value of a const item. While the former rules are critical, these latter rules are not and are ad-hoc. TC: This came up with the FLS work. Due to questions that came up while writing FLS documentation, we found places where the Reference was incomplete on these latter rules. But then people wanted the text to talk about the rationale of these rules, and there really isn't any. Ralf suggested we could drop these rules. That will make the Reference smaller, and that makes me happy. Josh: Going beyond "there isn't a rationale for this", I think it actually makes logical sense to *not* do this, and to allow mutable references like this for consistency. We e.g. allow you to have references to const in static. This seems like an arbitrary rule, so we can just say "this could work so it should". TC: It's in FCP now. ### "Warn on codegen attributes on required trait methods" rust#148756 **Link:** https://github.com/rust-lang/rust/pull/148756 TC: I proposed FCP here. Josh: These attributes are being applied to a trait method that has no body in a definition of a trait. You're marking a trait method with no body as `#[cold]`. That has currently no meaning. This won't show up in the trait implementation. So we should disallow them. Josh: There are other things that do get propagated such as `#[track_caller]`. Tyler: The description says FCW, is the intention to elevate this into a hard error? TC: Yes, I think we can make it hard error here later. Jack: Has there been a crater run done here? FCW is good, but I'm curious about the timeline. If there's no usage, can we make it an error today? Tyler: I don't think it's not doing any harm. I'm leaning more in the direction of let's just warn. Jack: I'd be curious to see the crater run. I wouldn't want to happen that someone tries to do this in a year and finds this is everywhere. If we want to make this into an error, we should have an idea for why it's not an error yet. TC: Jack, are you proposing raising a concern on having a crater run? Niko: I agree with Jack. I don't want us to FCW willy-nilly. I think the data will help us decide. TC: What other options are on the table? Niko: Just warn but not error. Or go over an edition. TC: Do you see other options right now? Niko: I consider FCW to be very serious. Josh: For the most part we often tend to equate FCW with warn-in-deps. I don't know this isn't necessarily worth an FCW with warn-in-deps. TC: I don't think FCW equates to warn-in-deps. The model we've been using recently is to not warn-in-deps for FCW and at the point we warn-in-deps we also set a deny-by-default lint. TC: I agree FCW is a serious statement, but I don't believe that at the time we do an FCW we have to have a concrete path to breaking this. I see it as an intention of this being in a category where we want to do it. But that means I don't need to see an crater run for an FCW. Josh: I do think we should warn here. I don't think this is worth warn-in-deps. So we should do an FCW without warn in deps. Jack: I do think FCW is a signal we want to remove something. But Crater would lets know whether we can remove it now. If crater is clean, you might as well have deny-by-default a lint. The only thing crater does is delaying merging the PR. And this is in FCP so it'll take a 10 days anyway. And it will provide us with a lot of information. I don't see why we shouldn't do a crater run. TC: What's the value of blocking the PR on it vs. signaling to the author that this is a good thing to do in follow up work? Jack: It signals that his is an important thing to not drop. Tyler: Jack is a lang advisor so he can file a concern. Jack: I'll write a summary on the PR and someone can file a concern. (edit: done https://github.com/rust-lang/rust/pull/148756#issuecomment-3554169899). ### "Tracking Issue for `FnStatic` and `FnPtr::addr`/`from_ptr`/`as_ptr` and `Code`" rust#148768 **Link:** https://github.com/rust-lang/rust/issues/148768 Amanieu: We're proposing two new traits. On on function pointers and one for things that can convert to function pointers. The Lang question here is: do we guarantee that the size of a function pointer is always a `usize`? That's for the `addr` method. And second, are we happy with `as_ptr` converting a function pointer to `NonNull` which has the same size as the function pointer. Amanieu: This is fine for every architecture we support. There are architectures where this isn't true. Neither GCC nor LLVM support those. Or rather, they support them only in the modes where the size of the data and code pointers are the same. Tyler: Are there any architectures where the sizes are different? Amanieu: Maybe 16-bit x86? I don't know how much support this still has. I think 16-bit code is not supported in LLVM. Tyler: What's the significance of the extern type? Amanieu: The extern type is there to ensure you don't try to dereference it. Tyler: We were discussing this recently. Does anyone have a link to the issue? Niko: Was that talking about the cast question? TC: That was it. Niko: We were talking about linting against casting from a code to data pointer. Tyler: I'm between us not supporting such architecture today and there maybe coming up in the future. TC: I think we'd expect these traits to be sealed. So you could always add methods later if it came up. Tyler: So if you're writing code that would be compatible with these architectures, we could add a method to handle it? TC: Yes, we could add a method that would be a more general way to handle this. Tyler: This is essentially adding methods to all function pointer types. That's a grey area between Libs-API and Lang I'd say. TC: Dual FCP. Tyler: That makes sense. Niko: Amanieu did a good job of highlighting the Lang-specific aspect of this. I've hard time tracking where and what commitments we've made. Josh: This is different from what we've dealt with before but it's in the same family. This one is purely "what if code and data have different pointer sizes". That hasn't come up before but it's important for us to think about it. But I think it's fine to say we'll support usize because that's what people need. Niko: Is this only 16-bit systems where this would come up? Or are there others? Josh: I've seen proposals for architectures where the pointers might have different tags, but not concrete architectures. TC: We already have an addr method on pointer and `NonNull` that return usize. So for consistency, just as an API matter, we should return `usize`. And due to the fact these traits are sealed, we can handle the other case later by extending the trait. Niko: I'm inclined to say we should just commit. Tyler: Here's my earlier comment: https://github.com/rust-lang/libs-team/issues/589#issuecomment-3463450364 > LLVM not supporting these platforms today doesn't weigh too strongly for me on the direction I think we should be going, just on how long it needs to take. In other words, we shouldn't design the language around the lack of support always being the case. I'm not arguing for a perfect solution, but one that pushes people in the right direction and makes it easier for us to support them with existing code in the future. > > My hope is to get to a point where when someone does come along with a use case for one of these (something highly resource constrained) and is willing to put in work in the backend, it will be surprisingly easy to port Rust code to it. Tyler: What LLVM does or doesn't support doesn't waigh too heavily on me on what the language should be able to express. But I want to have a solution that makes it easy to ??. The addr returning usize doesn't bother me. On `NonNull<Code>` I'm imagining it could be a different size than a `NonNull` of some other type. Jack: At some point Types should be pinged to make sure there's not going to be a Type-related issue here. But I don't expect there's going to be there. Josh: The whole target dependence and global mechanism is something we should pull the Types team team on. Tyler: Were you saying this would be easy to fix when we do `where Platform`? Josh: I don't think this would be easy to fix. But we could use that to *express* it if we wanted to. (But we can also use `#[cfg]` here.) Niko: ... Amanieu: I just wanted to quickly point out: what are people supposed to do on those architectures to get the address? Niko: I'd expect is you'd add another method that's more general. Josh: It would take a lot of design we shouldn't do now. But you could imagine having a different method on x86-16 that would return a far pointer. Amanieu: It makes sense. We would not provide these functions and it would be a compiler error. Amanieu: I'd expect most of these being embedded targets. Niko: For the perspective of this conversation I think config should suffice. Amanieu: I think the question's been answered. We should use `usize` and we can config targets out if they come in at some point. Tyler: This doesn't meet the goal I was trying to get to: having a path that encourages people to write code that makes it more portable writing code for the future. We have this WASM example where every funciton pointer is 32 bit integer. For WASM64 they want to configure it to be 64 for compatibility reasons. Niko: The alternative is a discriminant or something. What's unclear is how many usecases would fit into this that would be forwards compatible TC: Does someone want to write this up? Tyler: I'm still unsure what I'm comfortable with the direction. Amanieu: There is some precedentfor this in the CHERI discussion. We decided that CHERI is more restrictive than what the opsem model allows. CHERI pointers have to be copied as a whole. You can't do partial pointer copies by bytes. And that's something you have to accept when using such a platform. (The meeting ended here.) ### "Derive macros that emit unsafe code can't rely on mentioning the field type twice" rust#148793 **Link:** https://github.com/rust-lang/rust/issues/148793 ### "const-eval: always do mem-to-mem copies if there might be padding involved" rust#148967 **Link:** https://github.com/rust-lang/rust/pull/148967 ### "Not linting irrefutable_let_patterns on let chains" rust#146832 **Link:** https://github.com/rust-lang/rust/pull/146832 ### "Add `cargo_cfg_target_family_multivalued` FCW" rust#147545 **Link:** https://github.com/rust-lang/rust/pull/147545 ### "RFC: cfg_target_version" rfcs#3750 **Link:** https://github.com/rust-lang/rfcs/pull/3750 ### "repr(ordered_fields)" rfcs#3845 **Link:** https://github.com/rust-lang/rfcs/pull/3845 ### "Match guard can both move and static-promote a single constant" rust#145237 **Link:** https://github.com/rust-lang/rust/issues/145237 ### "`ref` patterns can const-promote a single constant more than once" rust#145555 **Link:** https://github.com/rust-lang/rust/issues/145555 ### "Uplifts and extends `clippy::needless-maybe-sized` into rustc" rust#145924 **Link:** https://github.com/rust-lang/rust/pull/145924 ### "Decide about future of `rustc_legacy_const_generics`" rust#146613 **Link:** https://github.com/rust-lang/rust/issues/146613 ### "Tracking Issue for enum access in offset_of" rust#120141 **Link:** https://github.com/rust-lang/rust/issues/120141 ### "Stabilize the `breakpoint` function" rust#142325 **Link:** https://github.com/rust-lang/rust/pull/142325 ## Project goals ### "Const Generics" rust-project-goals#100 **Link:** https://github.com/rust-lang/rust-project-goals/issues/100 ### "Ergonomic ref-counting: RFC decision and preview" rust-project-goals#107 **Link:** https://github.com/rust-lang/rust-project-goals/issues/107 ### "Finish the std::offload module" rust-project-goals#109 **Link:** https://github.com/rust-lang/rust-project-goals/issues/109 ### "Getting Rust for Linux into stable Rust: language features" rust-project-goals#116 **Link:** https://github.com/rust-lang/rust-project-goals/issues/116 ### "Stabilize cargo-script" rust-project-goals#119 **Link:** https://github.com/rust-lang/rust-project-goals/issues/119 ### "SVE and SME on AArch64" rust-project-goals#270 **Link:** https://github.com/rust-lang/rust-project-goals/issues/270 ### "Unsafe Fields" rust-project-goals#273 **Link:** https://github.com/rust-lang/rust-project-goals/issues/273 ### "C++/Rust Interop Problem Space Mapping" rust-project-goals#388 **Link:** https://github.com/rust-lang/rust-project-goals/issues/388 ### "Continue Experimentation with Pin Ergonomics" rust-project-goals#389 **Link:** https://github.com/rust-lang/rust-project-goals/issues/389 ### "Design a language feature to solve Field Projections" rust-project-goals#390 **Link:** https://github.com/rust-lang/rust-project-goals/issues/390 ### "Develop the capabilities to keep the FLS up to date" rust-project-goals#391 **Link:** https://github.com/rust-lang/rust-project-goals/issues/391 ### "Evolving trait hierarchies" rust-project-goals#393 **Link:** https://github.com/rust-lang/rust-project-goals/issues/393 ### "In-place initialization" rust-project-goals#395 **Link:** https://github.com/rust-lang/rust-project-goals/issues/395 ### "MIR move elimination" rust-project-goals#396 **Link:** https://github.com/rust-lang/rust-project-goals/issues/396 ### "Reborrow traits" rust-project-goals#399 **Link:** https://github.com/rust-lang/rust-project-goals/issues/399 ### "reflection and comptime" rust-project-goals#406 **Link:** https://github.com/rust-lang/rust-project-goals/issues/406