# Tyler / Ding
# Jan 30, 2025
## Review lag... what can we do about it?
Insufficient reviews "across the board"
* Compiler
* rustfmt
* bindgen
## Status of inflight work
Supertrait auto impl: Parser blocked on review. Going to move ahead with the resolution changes.
Receiver trait: Blocked on review. Jack has taken a look at the perf part.
## Pattern type... what can we do about it?
#### Niche opt
https://users.rust-lang.org/t/pointer-with-niche-for-unaligned-values/130692
provenence: https://doc.rust-lang.org/std/primitive.pointer.html#method.with_addr
## In-place init
### When to arm the destructor?
### Empty structs, units and uninhabitables?
Can we assume that places holding these values can be considered initialised?
```rust
struct Empty;
let x: Empty;
```
On the MIR side,
# Jan 2, 2025
# Dec 19, 2025
## In-place init
From Alice
- Too many proposals
- Wanna keep things simple, ...
```rust
// #[placing] but in a different syntax
type T = #[placing] fn() -> T;
fn init_me(arg: Arg) -> init(out) MyStruct {
out.arg = arg;
}
let _: impl Init<Output = MyStruct> = init_me(arg);
// ====
fn try_init_me(arg: Arg) -> Result<init(out) MyStruct, Error> {
out.arg = arg;
if check_something() {
Ok(())
} else {
Err(Error)
}
}
let _: impl TryInit<Output = MyStruct, Error = Error> = try_init_me(arg);
// ====
Box::new(try_init_me(arg)?)
// becomes something like..
Box::new_try_init(try_init_me(arg))?
// Ding: :(
// How does the question mark move outside!?!?
```
There are applications for in-place initialization of two disjoint memory locations, like in cryptography, or io_vec.
https://rust-lang.github.io/beyond-refs/in_place_init.html
## Niche optimisation with unoccupied bits of aligned pointers
Our niche optimisation only process continugous range of scalar values, not bit patterns. Aligned pointers have lower bits cleared.
Kernel devs are interested in optimisation using these bits. WDYT?
---
We have pattern types..
```rust
type Nonzero = i32 is 1..;
type Aligned<T> = *const T is align(align_of::<T>());
#[repr(something)] // <- needed because..
enum Complicated {
V1,
V2(Aligned<u32>), // <- ..can't take a reference to the inner value because it might be invalid
V3(Aligned<u64>),
}
let v: &Complicated
// (This would not compile:)
match v {
V2(ref x) => { ... } // the lower bits of raw (x: &Aligned<u32>) value is 0x1
V3(ref y) => { ... } // the lower bits of raw (y: &Aligned<u64>) value is 0x2
}
```
Works a lot like a packed struct.
## Supertrait auto impl
I am still on it, taking the Boxy's suggestion to rip out the new AssocKind from the design.
Ok to stabilize a subset that doesn't include the impl detection.
WriteFmt trait probably needs it, may have to wait.
## Autoref
Tyler's sketch (read the last section) for a custom, general Autoref trait
https://github.com/rust-lang/rust/issues/136987#issuecomment-2658112604
Tangential to the field projection stuff but related.
For field projections we need to figure out how it works.
## Reborrow
Aapo has more-or-less completed the core bits for Reborrow. One lifetime, no CoerceShared.
# Dec 5, 2025
## Supertrait Auto Impl
### Need for auto impl priority
[A question from lcnr@](https://github.com/rust-lang/rfcs/pull/3851#discussion_r2550353764).
```rust
trait SuperTrait {
type Type;
}
trait Foo: SuperTrait {
auto impl SuperTrait {
type Type = u8;
}
}
trait Bar: SuperTrait {
auto impl SuperTrait {
type Type = u32;
}
}
struct MyType<T>(T);
// should add `impl SuperTrait for MyType<u32>` if no other impl for `MyType<_>` exists
impl Foo for MyType<u32> {}
// should add `impl SuperTrait for MyType<i32>` if no other impl for `MyType<_>` exists
impl Bar for MyType<i32> {}
// Question: which `auto impl Supertrait` should we pick for `MyType<u32>` or `MyType<i32>`?
```
https://gist.github.com/rust-play/0ab82539ad83b447884beff4df22b17f
Zulip discussion: https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/Lang.20.2B.20Libs-API.20interest.3A.20impl.20subtrait.20via.20supertrait
### Nested auto impl
```rust
trait Super1: Super2 {
auto impl Super2;
}
trait Sub: Super1 {
auto impl Super1 { // Suppose that this has conflict
auto impl Super2 {
// Override Super1's auto impl
}
}
// Tyler: Can it be here instead?
auto impl Super2 {
}
}
impl Sub for ... {
extern impl Super1;
}
```
Interesting design question here of what behavior people would prefer (probably depends on the trait)... If a user writes a manual Super1 impl do they want the original auto impl of Super2 or Sub's auto impl of Super2?
We could potentially support both the flat and nested cases, with different behaviors for each when manually implementing Super1.
Tyler's inclination is to start with keeping it flat and add nested auto impl later. (Or making it an extension feature gate)
### extern impl vs scanning for impl
https://github.com/rust-lang/rfcs/pull/3851#discussion_r2393031851
Talk to lcnr or maybe Jack Huey on the types team to work out an implementation strategy.
We can treat this as an extension for now.
## Arbitrary self types
Ding working on an optimization that should reduce the method probing cost by half.
Most types have the same target for deref/receiver.
Tyler is inclined to keep the receivers the same for now. Fine with experimenting.
Option: WF check to require that receivers are the same, rather than keeping it as a supertrait relationship.
* Can we make this forward-compatible with making this a supertrait relationship? So people have to write extra bounds now that they can erase later.
```rust!
trait Receiver {
type Target;
}
trait Deref {
type Target;
// Note: No supertrait relationship!
// Do we need this? Probably not.
// But if we add it later, it could result
// in ambiguity errors.
auto impl Receiver {
type Target = <Self as Deref>::Target;
}
}
// Check: Prove that Self: Receiver<Target = <Self as Deref>::Target>.
impl Deref for MyType { }
fn foo<T: Deref + Receiver>() where
<T as Deref>::Target = <T as Receiver>::Target,
{}
```
Two-definition problem: The only wrinkle here is that if we evolve to a supertrait/auto impl setup there will be two definitions of the Target assoc type for types that implement both traits. We could make a one-off exception for these traits in older editions or something, continuing to apply the special check.
### Why do we need `trait Deref: Receiver`?
Tyler: Actually my preferred setup might be 3 traits..
```rust!
trait Target {
type Target: ?Sized;
}
trait Receiver: Target {}
trait Deref: Target {}
```
With the above setup including the equality check (with or without the auto impl in Deref), we should be able to evolve to this. It still has the two-definition problem.
Ding: I will need to write an exposition on method calls.
Tyler: I do see some of the argument for having types that implement Deref but not Receiver; not sure if it's important to split them or not. Another option we have is to make Deref "all-inclusive" but tell people to implement HasPlace (Nadri's proposal) and related traits if they want Deref behavior without Receiver. (Not sure if this is "good")
## in-place init
Tyler: What we want to prevent, I think, is creating `&'a uninit` where `'a = 'static`. To ensure that, we must create a fresh lifetime for each `&uninit` expression and that lifetime cannot be said to outlive any input generic lifetimes.
# Nov 21, 2025
## in-place init
### `&own` pointer signature
Problem: Some people want covariant lifetimes for `&own T`.
Intuition: If `T` is as good as `&own T` you should be able to make it live for a shorter range.
`&'a own<'b> T` where `'b: 'a` and `T: 'b`.
`&'static own T`, `&'a own<'static> T` for us
`&'a uninit T` has `'a` invariant.
`fn foo<'a>(&'a uninit T) -> &'a own T` marks `'a` as invariant.. does this work?
```rust
let a: &'1 uninit Foo = &uninit Foo;
let b: &'2 uninit Foo = &uninit Foo;
a.field = 0;
// a <- a;
b <- a;
fn init<'a: 'b, 'b>(x: &'a uninit Foo, y: &'b uninit Foo) -> &'b own Foo {
x.field = 0;
x as &'a own Foo as &'b own Foo
}
```
@Daniel Henry-Mantilla wants covariance in `&own T`.
https://rust-lang.zulipchat.com/#narrow/channel/528918-t-lang.2Fin-place-init/topic/uninit-pointer.2C.20Nov.202025.20edition/near/557910436
Can we solve the "`'static` problem" if we can say `own<'a> T` does *not* outlive `'a`?
In other words, you can construct `&'static own<'a> T` s.t. `'a` is not `'static`.
This seems *possible*, but annoying/dangerous to implement: Many type system APIs are likely to assume that a type outlives any free lifetime `'a` in that type.
~~Doing anything like this would require a matching token on `&uninit`:
`fn foo<'a>(&uninit<'a> T) -> &out<'a> T`~~
Maybe one lifetime on `&uninit` can suffice.
Ding AI: try to find a way to reduce the "load" on type system for the extra lifetime that is not the branded lifetime on `&'a own<'b>`.
```
let foo: Foo;
// This produces a new "brand" '1:
let foo_uninit: &'1 uninit Foo = &uninit foo;
fn foo(&uninit Foo) -> &own Foo
// Desugars to: (maybe)
fn foo<'a>(&'a uninit Foo) -> &'a own<'a> Foo
```
```
&own Foo
// should mean
&'a own Foo
// should mean
&'a own<'a> Foo
```
Alternatively, we can have separate `&'a own T` and `&'a out<'a> T` reference types.
(These two names are way too easily confused)
Observation... This doesn't on its own solve the "`'static` problem"... but... *maybe* it could if we wrangled the type system impl enough... like try to remove all assumptions that ~~`own<'a> T: 'a`~~ but don't allow anyone to rely on that yet... put that behind a different feature flag.
* The goal is that `&'static own<'a> T` can exist without ever implying that `'a: 'static`
Q: Can we say anything about the outlive relation between `T` and `'a`?
WF rule: `&'a T` requires/implies that `T: 'a`
`&'a own<'b> T`: `T: 'b` is actually fine
Tyler: Initialising static case is one.
```rust
static FOO: Foo = const {
// We will have FOO visible in the lexical scope but
// FOO is uninit
let unfoo: &'2 uninit FOO = &uninit FOO;
unfoo <- Foo;
let own_foo: &'1 own<'2> Foo = unfoo;
// 'static: '1 because of subtyping
// '1: 'static
};
// Something like this...
// ... but which lifetime to fill for branding?
static FOO: Mutex<Option<&'static own Foo>> = {
Mutex::new(Some(&own Foo::new()))
// The typing here is &'static own<'_>
};
// Actually we cannot do the following, statics can't have generics
static FOO<'a>: Mutex<Option<&'static own<'a> Foo>>;
```
```
// This works..
let x: &'static i32 = &42;
```
We can avoid this situation by not allowing you to create `&'static own Foo`... somehow. Maybe: Anytime we see `'a` in `own<'a>` we force it to be shorter than `'static`.
### Transfer `&uninit T` to `&uninit UnsafeCell<T>`
Actually it seem to do with many "wrapper" types that are equivalent from the **memory view**. The question is, does it uphold the `UnsafeCell` contract well?
Can this extensionality notion of `&uninit Wrapper<T>` being just `&uninit T` apply for any `Wrapper<_>`?
### Notarisation done with plain `=`
Summary of [thread on this topic](https://rust-lang.zulipchat.com/#narrow/channel/528918-t-lang.2Fin-place-init/topic/notarization.20syntax.20of.20uninit.20pointers/with/558242339).
When we type-check assignments `LHS = RHS;`, we look at the matching pairs of a place in `LHS` and a value `RHS`.
- If the LHS place has a type `&own ?P` and the RHS value has `&own ?Q`, this is a direct own-reference assignment;
```rust
fn make_own_A<'a>() -> &'a own<'a> A;
let mut a: &own<'a> A = ...;
// LHS is &own<'static> A, RHS is &own<'static> A
a = make_own_A(); // this is assignment
// A unifies with A
// own<'a> unifies with 'a, we are good
```
- If the LHS place has a type `?P` and the RHS value has `&own ?Q`, this is an emplacement and we should unify `?P := ?Q`.
```rust
fn make_uninit_place<'a, T: 'a>() -> &'a uninit A;
let a = make_uninit_place();
// *a is typed as A
// LHS is A, RHS is &own A
*a = make_own_A(); // this is emplacement
// A unifies with A, own<'a> unifies with 'a, we are good
```
Two alternatives:
* Use `<-` both in notarization statement and in struct initializer syntax,
* Use `=` in the first and `:` in the second (as we do today)
Tyler leaning toward the first, but could be convinced.
# Oct 23rd, 2025
## Arbitrary self types
```rust
// Crate core
#[unstable_feature_bound(merge_chain)]
impl<T: ?Sized + Deref> Receiver for T {
type Target = <T as Deref>::Target;
}
// == CUT HERE ==
// Crate A - use multi-chain
// NOTE: we are not applying `#![feature(merge_chain)]` feature gate here in A
impl<T: ?Sized> Receiver for MyBox<T> {
// conflicting impl with core
type Target = T;
}
impl<T: ?Sized> Deref for MyBox<T> {
type Target = Inner<T>;
..
}
impl<T> Inner<T> {
fn method(&self) { .. }
}
struct AType;
impl AType {
fn method(self: MyBox<AType>) { .. } // this is preferred in case `??.method()`
}
let x: MyBox<AType>;
x.method(); // this is resolved to `AType::method`
// == CUT HERE ==
// Crate B - use single chain
#![feature(merge_chain)]
use a::{AType, MyBox};
impl MyStruct {
fn method(self: MyBox<MyStruct>) {
// WF error, `MyBox<MyStruct>` cannot receive `method` for `MyStruct`
}
}
// also...
let x: MyBox<AType>;
x.method(); // this is resolved to `Inner::method` here in this crate
```
### Experimentation problem
We don't enough justification to split the chains.
### Philosophy of when to use deref / receiver
Why use Receiver at all?
* The containing type includes more information: Contracts, invariants, fields
* e.g. pinned
* Convenience
We have types in std that are currently Deref but not Receiver
* AssertUnwindSafe
* `std::collections::binary_heap::PeekMut`
* ...
Why split target types?
* We have some examples of where it's useful
### AIs
- Eye patching, pretending that Deref -> Receiver exists without blanket impl
- Write down the answer to the [philosophical question](https://hackmd.io/BZgRy4MFRq6HtYkpo_V5ow#The-use-case-matrix) in t-lang and ask for their opinions
## In-place init
### Various proposals, out-ptr solution
#### Vibe check
####
## Evolving trait hierarchy
https://rust-lang.zulipchat.com/#narrow/channel/435869-project-goals/topic/Evolving.20trait.20hierarchies.20.28goals.23393.29/near/546690945
## Crubit