--- title: "FLS team meeting 2025-11-14" tags: ["meeting-minutes"] date: 2025-11-14 discussion: https://rust-lang.zulipchat.com/#narrow/channel/520710-t-lang.2Ffls/topic/Meeting.202025-11-14/ url: https://hackmd.io/LU_m_4koQD6AZm4VnF-bTw --- # 2025-11-14 - `t-fls` Meeting ## Attendance ### Attendees - Alex Celeste - Tshepang Mbambo - Eric Huss - Hristian Kirchev - TC ### Regrets - Pete - Tomas ## Agenda - Walk-in topic triage - 1.90 FLS: clarify issues, come about with solutions ## FLS 1.90 update https://github.com/rust-lang/fls/pull/580 TC: We're reviewing first the language starting here: https://github.com/rust-lang/fls/pull/580#discussion_r2514102274 The proposed language is: > The final value of a constant, after the constant initializer is evaluated to a value of the declared type, cannot contain any mutable references except when... The referent is not a temporary and is subject to interior mutability, or ... There are two sets of rules that are applicable here. One is the set of rules for what is a valid constant expression. This can be seen in the Reference here: https://doc.rust-lang.org/nightly/reference/const_eval.html?highlight=constant%20ev#r-const-eval.const-expr And in the FLS here: https://rust-lang.github.io/fls/expressions.html#constant-expressions These rules apply recursively throughout the body of any constant expression. Then, separately, we have rules about what may appear in the final value of a constant item. Incidentally, due to the specificational discussions about these rules, there's a proposal on the table for the lang team to eliminate this second category of rules. https://github.com/rust-lang/rust/pull/148746 As it applies to mutable references and references to values with interior mutability, for the first class of rules, the validity of constant expressions, the applicable rule is: https://doc.rust-lang.org/nightly/reference/const_eval.html?highlight=constant%20ev#r-const-eval.const-expr.borrows > r[const-eval.const-expr.borrows] > * All forms of [borrow]s, including raw borrows, except borrows of expressions whose temporary scopes would be extended (see [temporary lifetime extension]) to the end of the program and which are either: > * Mutable borrows. > * Shared borrows of expressions that result in values with [interior mutability]. Tshepang has already updated the FLS, as part of this PR, to incorporate this rule. That leaves us to document this second part correctly. In the Reference, that's documented here: https://doc.rust-lang.org/nightly/reference/items/constant-items.html#r-items.const.no-mut-refs Here, we are looking at the final value of a constant. As the Reference says: > r[items.const.no-mut-refs] > The final value of a `const` item, after the initializer is evaluated to a value that has the declared type of the constant, cannot contain any mutable references except as described below. > > Mutable references where the referent is a value of a [zero-sized type] are allowed. > > Values of [union type] are not considered to contain any references; for this purpose, a value of union type is treated as a sequence of untyped bytes. > > Mutable references contained within a [mutable static] may be referenced in the final value of a constant. > > Mutable references contained within an [external static] may be referenced in the final value of a constant. There's a subtle point on the penultimate item here -- that we're going to clarify in the Reference -- when we say "except for... mutable references contained within a mutable static", we mean here "a static whose memory is mutable". That could be either a `static mut` item or a `static` item whose type contains a type with interior mutability. In this instance, it really is a check on the type rather than on the value -- for the checks for valid constant expressions, we do it by value rather than by type. Tshepang: Should we bother to document this at all if the lang team might remove these rules? TC: That's a question of philosophy on how accurate we want the FLS to be for particular versions. The lang team hasn't made a final decision to remove this second class of rules, and if we were to do so, it wouldn't land until a few versions from now. Hristian: Not documenting it would also increase the divergence from the Reference for these versions. With all that in mind, new proposed wording (from Hristian): The final value of a constant, after the constant initializer is evaluated to a value of the declared type, cannot contain any mutable references except when - The mutable reference is contained within an external static, or - The mutable reference is contained within a mutable static, or - The mutable reference is contained within an union, or - The referent is a value of a zero-sized type. TC: That's close, but we'd need to look at how the FLS defines a "mutable static". As mentioned above, there's some subtlety here. Hristian: > 7.2:6 A mutable static is a static with keyword mut whose value can be modified. TC: Right. So we need to adjust something to account for this. Here's what the Reference is going to say when I push my next PR for this: > [Except...] Mutable references contained within a mutable `static` may be referenced in the final value of a constant. A mutable `static` is a [`static mut`] item or a [`static`] item with an [interior mutable] type. Hristian: Next draft of proposed FLS text: > 7.2:6 A mutable static is a static with keyword mut or a static of a type subject to interior mutability, whose value can be modified. TC: If we were to change the definition of a "mutable static" generally in the FLS, though, we'd have to look for anywhere else that is used in the FLS, as probably there are places that really do mean a `static mut` item (and only such an item) when saying that. Hristian: How about we turn: > - The mutable reference is contained within a mutable static, or into: > - The mutable reference is contained within a mutable static or a static whose type is subject to interior mutability, or TC: Yes, that looks correct. Hristian: Final draft then: > The final value of a constant, after the constant initializer is evaluated to a value of the declared type, cannot contain any mutable references except when > > - The mutable reference is contained within an external static, or > - The mutable reference is contained within a mutable static or a static whose type is subject to interior mutability, or > - The mutable reference is contained within an union, or > - The referent is a value of a zero-sized type. TC: Yes, that looks correct. OK. When we get that incorporated, we should have the FLS updates for 1.90 ready. ## Documenting panic strategies Tshepang: Are panic strategies in scope for the language... should we document things like `--codegen panic=abort`? Am not sure what the right boundary is. TC: This is related to one of the most infamous Reference PRs... ever. That was: https://github.com/rust-lang/reference/pull/1226 Hristian: The FLS does talk about abort: https://rust-lang.github.io/fls/exceptions-and-errors.html#abort. The FLS should not discuss options of a conforming tool. It could however present the various exceptional mechanisms, and indicate that a conforming tool is free to choose a particular mechanism (or mechanisms). TC: In the Reference, part of this is documented in functions: https://doc.rust-lang.org/nightly/reference/items/functions.html#r-items.fn.extern.unwind Then we do have chapter on panic: https://doc.rust-lang.org/nightly/reference/panic.html The other place this comes up is in our ABI chapter, due to having separate ABI for unwind variants: https://doc.rust-lang.org/nightly/reference/items/external-blocks.html#abi Hristian: UnwindSafe and RefUnwindSafe in the core library: https://doc.rust-lang.org/core/panic/index.html ## How do we distinguish the language and the library Tshepng: It's not always clear to me where the language stops and the library begins; how do we distinguish? TC: The model I use is as follows. First, obviously nothing in `std` is part of the language. Tshepang: Right. TC: In `core`, what we have to look at is whether the type or trait could be implemented in stable Rust. If it can, then it's not part of the language. If it can't, then it's a "language item". The special behavior of the type or trait is a "language behavior". If we were to change the language such that the type or trait could be implemented in stable Rust, then it would no longer be special, and would no longer be a language item. The language behavior would then be encompassed by the stabilized feature that allows for expressing the type or trait. Hristian: Yes, that makes sense.