---
title: "Design meeting 2026-03-18: Hierarchy of `Sized` traits, part 3 (names and bounds)"
tags: ["T-lang", "design-meeting", "minutes"]
date: 2026-03-18
discussion: https://rust-lang.zulipchat.com/#narrow/channel/410673-t-lang.2Fmeetings/topic/Design.20meetings.202026-03-18.3A.20Sized.20hierarchy.20names.20and.20bounds/
url: https://hackmd.io/TEI6cM06Q5KvDwKOX4OuTg
---
> [!NOTE]
> Thanks to Rémy Rakic and David Wood for the document.
# Summary
[summary]: #summary
[RFC 3729](https://github.com/rust-lang/rfcs/pull/3729) focuses on changes to the `Sized` infrastructure:
- to unblock extern types that are neither `Sized` nor `?Sized`
- to prepare for runtime-sized types: this was split into future work to remove const sizedness questions
It does this by introducing new marker traits, `SizeOfVal` and `Pointee`, with `SizeOfVal` being a supertrait of `Sized` and `Pointee` being a supertrait of `SizeOfVal`:
```
┌─────────────────────────────────────────────────────────────┐
│ ┌─────────────────────────────────────────────────┐ │
│ │ ┌────────────────┐ │ │
│ │ │ Sized │ SizeOfVal │ Pointee │
│ │ │ {type, target} │ {type, target, ptr metadata} │ {*} │
│ │ └────────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
The purpose of the 2026-03-18 meeting is to discuss [two unresolved questions from the RFC](https://github.com/davidtwco/rfcs/blob/sized-hierarchy/text/3729-sized-hierarchy.md#unresolved-questions):
- the names of the proposed traits
- and how to opt-in and opt-out at the different levels of the hierarchy
The meeting on 2026-03-25 will be about questions of transition and migration.
# Names
All of the trait names proposed in the RFC can be bikeshed and changed, they aren't the important part of the RFC. It initially proposed `Sized: MetaSized: Pointee`, where `MetaSized` referred to the size stored in pointer metadata.
However, in more recent discussions, there was a preference that the names be related to the operations they allow (with possible extensions in the future), so the current proposed names are `Sized: SizeOfVal: Pointee`.
The nightly implementation currently uses `Sized: MetaSized: PointeeSized`.
# Bounds
The design axes are explicit vs implicit, and opt-in vs opt-out.
### Why migrate away from `?Sized`?
`?Sized` is frequently regarded as confusing for new users and came up in the [prior art][prior-art] as a reason why new `?Trait` bounds were not seen as desirable (see [rfcs#2255][issue_more_implicit_bounds]). Furthermore, it isn't clear that `?Sized` scales well to opting out of default bounds that have constness or hierarchies.
This RFC's proposal to migrate from `?Sized` is based on ideas from an [earlier pre-eRFC][pre_erfc_fix_dsts] and then a [blog post][blog_dynsized_unsized] which developed on those ideas, and the feedback to this RFC's prior art, but is not a load-bearing part of this RFC.
### Why remove default bounds when a sizedness bound is present?
This RFC proposes removing `?Sized`, rewriting it as `SizeOfVal`, and that adding any sizedness bound removes the default bound - the "positive bounds" approach:
| Canonically | Syntax with positive bounds |
| ----------------- | ------------------------------------------------------- |
| `Sized` | `T: Sized`, or `T` |
| `SizeOfVal` | `T: SizeOfVal` (or `T: ?Sized` on the previous edition) |
| `Pointee` | `T: Pointee` |
There are alternatives which can roughly be compared by whether you opt-in or opt-out to the desired sizedness bound, and how implicit or explicit that is:
| | **Opt-in** | **Opt-out** |
| ------------ | ---------------------------------------------- | --------------------------------------- |
| **Implicit** | Positive bounds (what is proposed by this RFC) | [Adding `?SizeOfVal`](#Adding-SizeOfVal) |
| **Explicit** | [Adding `only` bounds](#Adding-only-bounds) | [Keeping `?Sized`](#Keeping-Sized) |
#### Keeping `?Sized`
Without adding any additional default bounds or relaxed forms, keeping `?Sized` could be compatible with this proposal as follows:
| Canonically | Syntax with positive bounds (as proposed) | Syntax keeping `?Sized` (this alternative) |
| ----------------- | ------------------------------------------------------- | ------------------------------------------ |
| `Sized` | `T: Sized`, or `T` | `T: Sized` or `T` |
| `SizeOfVal` | `T: SizeOfVal` (or `T: ?Sized` on the previous edition) | `T: ?Sized + SizeOfVal` |
| `Pointee` | `T: Pointee` | `T: ?Sized` or `T: ?Sized + Pointee` |
In the current edition, `?Sized` would need to be equivalent to `?Sized + SizeOfVal` to maintain backwards compatibility. In the next edition, `?Sized` would be rewritten to `?Sized + SizeOfVal` (read: remove the `Sized` default and add a `SizeOfVal` bound) and bare `?Sized` would only remove the `Sized` default bound.
#### Adding `?SizeOfVal`
Another alternative is to make `SizeOfVal` a default bound in addition to `Sized` and establish that relaxing a supertrait bound also implies relaxing subtrait bounds (but that relaxing a subtrait bound does not imply relaxing supertrait bounds):
| Canonically | Syntax with positive bounds (as proposed) | Syntax adding more relaxed forms (this alternative) |
| ----------------- | ------------------------------------------------------- | --------------------------------------------------- |
| `Sized` | `T: Sized`, or `T` | `T: Sized` or `T` |
| `SizeOfVal` | `T: SizeOfVal` (or `T: ?Sized` on the previous edition) | `T: ?Sized` |
| `Pointee` | `T: Pointee` | `T: ?SizeOfVal` |
In other words, when a less strict bound is desirable, it is achieved by opting out of the next strictest bound.
#### Adding `only` bounds
Yet another alternative is introducing new syntax that establishes "trait hierarchies", each with their own default bounds as a more explicit concept in the language.
An `only` keyword is applied to bounds/supertraits when any default bounds from that trait's hierarchy should be removed.
```rust
trait Pointee {}
trait SizeOfVal: only Pointee {}
// ^^^^ adding `only` removes any default bounds/supertraits from
// the hierarchy that the `only`-annotated trait is part of
#[default_trait] // (just for illustration purposes)
trait Sized: only SizeOfVal {}
```
| Bound as written | Interpreted as | Explanation |
| ------------------- | ---------------------- | ------------------------------------------------------------------ |
| `T` | `T: Sized` | Default bound |
| `T: Sized` | `T: Sized + Sized` | Adding an explicit bound alongside the default bound, redundant |
| `T: only Sized` | `T: Sized` | Removing the default bound and adding an explicit bound, redundant |
| `T: SizeOfVal` | `T: SizeOfVal + Sized` | Adding a relaxed bound alongside the default bound, redundant |
| `T: only SizeOfVal` | `T: SizeOfVal` | Removing the default bound and adding a relaxed bound |
| `T: Pointee` | `T: Pointee + Sized` | Adding a relaxed bound alongside the default bound, redundant |
| `T: only Pointee` | `T: Pointee` | Removing the default bound and adding a relaxed bound |
`only` cannot be used on user-defined traits or trait aliases, even those with sizedness supertraits. `only` cannot be used on supertraits in user-defined trait definitions.
#### Relaxed bounds and incremental stabilisation
With some of the above alternatives, the ability to incrementally stabilise new sizedness traits is made more challenging. For example, to express a `T: Pointee` bound, `T: ?SizeOfVal` is written, so stability of a degree of sizedness is based not on the stability of its trait but rather by stability of being able to relax the next strictest trait.
[blog_dynsized_unsized]: https://smallcultfollowing.com/babysteps/blog/2024/04/23/dynsized-unsized/
[issue_more_implicit_bounds]: https://github.com/rust-lang/rfcs/issues/2255
[pre_erfc_fix_dsts]: https://internals.rust-lang.org/t/pre-erfc-lets-fix-dsts/6663
[prior-art]: https://github.com/davidtwco/rfcs/blob/sized-hierarchy/text/3729-sized-hierarchy.md#prior-art
---
# Discussion
## Attendance
- People: TC, David Wood, Rémy Rakic, Zachary Sample, Frank Steffahn, Jack Huey, Chris Sena, Tyler Mandry, Josh Triplett, Niko Matsakis, Nurzhan Saken, Aapo Alasuutari, Yosh
## Meeting roles
- Driver: TC
- Minutes: Nurzhan
## Vibe checks
### Niko
I like `SizeOfVal` -- I continue to find that whenever I think I should name traits after something other than their "characteristic" method, I am wrong and I regret it (arguably, `Iterator` should've been `Next`! Change my mind!).
I favor the `only` proposal. My rationale is:
* These bounds are special and I think that it will help people to learn to see them flagged as special.
* It gives us a path to defining user-defined alias and things that *also* weaken default bounds (e.g., `trait MyDisplay = only SizeOfVal + Display`, `T: only MyDisplay`) and I think that's going to be useful and important.
* I am happy to put as many limits as we want to enable forward progress and leave us room for later experimentation (e.g., `only` bounds should only apply to special traits), but that's the direction I want to go eventually.
* Keywords >> sigils (another of those lessons that, whenever I second-guess it, I wind up coming back to it), both because they can be easily google'd and looked up in an index and because most users find them less intimidating.
*Meta note:* I like the way we setup the short document to focus on the key questions!
### tmandry
It may not surprise you that I like the `SizeOfVal` naming.
For relaxing bounds, I favor the `only` proposal. That leads us to a more general feature that doesn't require people to track which kinds of bounds are "special" like this.
### scottmcm
(Not present.)
### Josh
Big fan of the hierarchy proposed here (with the possible exception of the name `Pointee`).
I'm wondering whether `Pointee` would interact with proposed mechanisms to opt-out of being something you can point to. (Josh: e.g., may a field that cannot be pointed to not implement `Pointee`?)
I like the idea of `only` as a way to make this clear; I think that's much clearer than the more implicit alternative.
However, I would have expected some detailed examples of how this interacts with having traits at various levels.
For instance, if I write `trait MyTrait` and `impl<T: SomeTrait> MyTrait for T`, does that imply something about `Sized`? Can I then, elsewhere, write a bound of `X: MyTrait + only SizeOfVal`? How do those interact? Does that change depending on if `MyTrait` is implicit or explict about sizedness?
### TC
On the naming, I'm happy with `SizeOfVal` -- I like naming traits after the primary method. It'd be nice for that to eventually not be a marker and to have `size_of_val` as an associated item. I'm not sure about `Pointee`. Might that be stepping on a name we'd want otherwise? That's the risk that always comes up with noun names for traits.
On the bounds syntax, I like the opt-in + explicit quadrant, e.g. `only`. There is something that doesn't sit right we me about it, though. The syntax is tied to one of the bounds, but the effect is actually to turn off default bounds for the entire bounds list. It actually feels as though the modifier should apply to the entire bounds list in a way more similar to `+ use<..>`. Maybe `+ only`?
(Of note, also, I think there's a different interpretation of opt-in + implicit than the one proposed. The other interpretation would be to transitively apply relaxed bounds. I think I prefer opt-in + explicit better, but second to that, I'd prefer opt-in + implicit with transitively applied relaxed bounds. I like that the explicit option sidesteps the problems of this.)
tmandry: What do you mean by transitively apply relaxed bounds?
TC: By that I mean that if you have a trait that has `Pointee` as a super trait, and if you put that as the only item in the bounds list, it would relax the bounds in the same way as writing `Pointee` would.
### Jack
When initially proposed on Zulip, I was skeptical of the `only` bounds. But when reading through the doc, I actually have found that I kind of like it 🙂 It's also an interesting potentially parallel to `maybe` specialization. On `SizeOfVal`...eh. It doesn't align with how I typically think of trait names (either "is" or "is a"). Would prefer `ValueSized`.
## Semantic of `only`
Josh: I'm wondering if we *should* make `only` only affect the one bound. Rather than changing the syntax to make it affect the whole list.
David: The reason it doesn't apply to the list is is that it only affects he one bound; we can then introduce new hierarchies.. bound list-specific.
Josh: It sounds like `only SizeOfVal` only opts out of Sized, and if we had some other similar hierarchy it wouldn't opt out of those. That seems *important*, and correct, because I think you shouldn't be able to opt out of a bound you don't know about. This is an important lesson from Cargo and `default-features = false`; we should not repeat that same mistake.
### precise semantics of `only`
nikomatsakis: I have a pretty specific semantics for `only` in mind. Let me try to sketch them.
* There is a "default" `Sized` bound and a defined set of "supertraits" (`SizeOfVal`, `Pointee`, etc).
* In a `T` bound, you can apply `only` to
* one of the Sized traits
* any trait which has a `only` bound in its list of supertraits (feature-gated)
* Let's define `TraitDefault(Bound) = {TraitId}` as follows:
* `TraitDefault(Trait)` is empty set.
* `TraitDefault(only Trait)` is:
* If trait is in the `Sized` hierarchy, then the result is a singletons et `{Trait}`
* Otherwise, let `Traits_super` be the supertraits from `Trait`, then
* TraitDefault(only Trait) = Union(TraitDefault(s) for s in Traits_super)`
* Every type parameter has a default bound from the `Sized` family:
* Apply trait default to all bounds, if result is empty set, use Sized, else use the most specific
This can be generalized to other "families" of bounds with relative ease.
```rust
fn foo<T>(t: &T) {
// T: Sized
std::mem::forget(*t); // OK
}
// If you turned off "all defaults" by writing `only T`...
fn foo<only T>(t: &T) {
std::mem::forget(*t); // OK
}
// If you turn off only one default at a time
fn foo<T: only Pointee>(t: &T) {
// this can still imply Forget
std::mem::forget(*t); // OK
}
fn foo<T: only Pointee + only Destruct>(t: &T) {
// this no longer implies Forget
std::mem::forget(*t); // :(
}
```
We can't know what things we will want you to NOT be able to do by default in the future.
Josh: This is similar to the problem with cargo's `default-features = false`: if you can opt out of everything including things you don't know about yet, it becomes a breaking change to introduce new opt-outs.
Tyler: ?? We did talk about this in a previous meeting.
TC: What's the expected behavior of?:
```rust
trait Tr: only Pointee {}
fn f<T: only Tr>() {}
```
Niko: What I would eventually like is, per above, this would be equivalent to:
```rust
fn f<T: Tr + only Pointee>() {}
```
Josh: this seems to have the same underlying problem of "can you actually opt out of that?"
Niko: I don't think so -- can you give an example?
Josh: Is Tr actually providing as part of its API the set of implicit things opting out for s.t. ?? and not using
Niko: When you use only on me, you are specifically relaxing this default bound.
Josh: So it would be a bc in the future to opt out of any additional bound? e.g. + only Forget?
Niko: Yes?
Josh: ?? It's consistent with other trait behavior, so it's doable.
Tyler: There's a non-breaking change you can do, which is adding a new "rung". So for example, if you have `SizeOfVal: only Pointee`, you can change it to `SizeOfVal: only DataSizeOfVal` and `DataSizeOfVal: only Pointee`.
Josh: So we should be explicit that adding a new opt-out to a trait is a breaking change.
Josh: It's a breaking change to require *more* (e.g. go from `SizeOfVal` to `Sized`) if the trait is not sealed, but you can if you're sealed. You can go up if you're sealed because nobody else is allowed to implement you. It may be desirable to have a way to go *down*, by saying "people who depend on me aren't allowed to count on me providing `Sized`", so that you can switch to `SizeOfVal`.
Niko: Has an idea for privacy on implied bounds which would help
Josh: +1 for putting this off for later, and +1 for having a mechanism for opting explicitly for bounds being implied.
Niko: TC, to your point, I hadn't fully considered the edition angle of this -- that we could tie this to the type parameter and still migrate over editions. There may be some merit in that -- in practice, if you almost always when you opt out of one of a family of bounds, you want to opt-out of the rest too, that could make sense. I'll need to analyze this more.
---
David: Currently we propose that writing `only` in supertrait position is unstable (and that you can't write `only` on a user's trait).
TC: Do we similarly disallow?:
```rust
trait Tr where Self: only Pointee {}
```
David: We probably ought to allow that to permit opt-ing out of the default supertrait we introduce for backcompat - the limitation on where we allow writing `only` is just to reduce scope, if doing that on user traits only is sufficient then that's fine by me.
## `only` keyword
Frank: The use of an `only` keyword might seem like it could relate to [supertrait-auto-impls](https://github.com/rust-lang/rust/issues/149556), like someone wanting to "implement *only* some trait `Foo` but not its supertrait". I'm not sure yet if there's any other way besides vibes/English-language intuition that could connect supertrait-auto-impls and these hierarchies.
Josh: Do we believe we can ship `only` without an edition? Given where it appears, hopefully "types and traits *should* generally be capitalized" will give us enough that a crater run would let us ship it in every edition.
Niko: I was going to say it's a contextual keyword, but in the chat Zachary points out that `T: only ::Foo` could be parsed today where `only` is interpreted as a module.
Tyler: Technically it would be a breaking change.
Josh: I expect there to be methods named `only` in the ecosystem, so let's not make it a global keyword; it should be sufficient to only accept it in specific contexts.
TC: Yes, making it a full keyword would be too strong.
Niko: There was the following proposal:
```rust
trait Ord: PartialOrd {
auto impl PartialOrd;
}
// would also implement `PartialOrd`
impl Ord for u32 {
}
// --- OR ---
// would be used if you want to write
// the `PartialOrd` separately
impl only Ord for u32 { }
```
Frank: If they're distinct, the question is which feature gets the keyword?
Niko: I can imagine people getting confused about the meaning of the keyword.
Tyler: To me it's the meaning in each case that makes the most sense in the context of what you're doing: Specifying a bound versus implementing a trait.
Josh:
> I was going to say it's a contextual keyword, but in the chat Zachary points out that `T: only ::Foo` could be parsed today where `only` is interpreted as a module.
This has come up repeatedly. It came up when proposing `crate` as a visibility; that would break with code like `struct S(crate ::Type)`. Should we stop allowing that over an edition, and require no whitespace around `::`, to give ourselves room for future expansion?
TC: Not to say we shouldn't do it, but that would be a huge change to the Reference grammar. We'd be making Rust whitespace-sensitive. We'd need to combine our lexing and parsing, which is hard because our lexing surface area is user-visible.
Josh: Yes. We shouldn't settle this now. But this keeps coming up, and we should look at it.
## `only` and other default bound hierarchies
tmandry: What are some other hierarchies that we might use with `only`? Should those hierarchies share a common "root"?
* Move: UnknownBase
* Forget: Leak: Destruct: UnknownBase
Niko: Now, everything can be forgotten via `std::mem::forget`. Leak: can the memory be reused without running a destructor?
The unknown base might be `Linear`, but that might be too specific. I'd call that `Move`, in any case, a type that can only be moved is one that is "linear". UnknownBase is like "you can just access it".
Tyler: If we make `only` ??, it might mean having hierarchies in Rust that are artificially separated(?). We could handle it over an Edition.
David: I'm not sure the only keyword would work intuitively if ...
Tyler: I was saying that if you want to opt-out of one hierarchy but not the other, you might... your point is essentially that two hierarchies shouldn't have a common root if you want to opt-out of one of them (?)
David: `only Tr` opts-out of any defaults left of that in the hierarchy
```text!
(default)
Sized <-- SizeOfVal <----------\
Pointee
Forget <-- Leak <-- Destruct <--/
(default)
```
Tyler: You have a common root, and you want to opt-out of one of the branches. Let's say UnknownBase is Pointee. You want to opt-out of SizeOfVal but not Destruct. Say for the sake of argument that we had this:
```rust!
trait SizeOfVal: only Pointee {} // Stabilized first
trait SizeOfVal: only Pointee {} // Stabilized second
fn foo<T: only Pointee>() {} // meaning changes when we stabilize `B` above
fn foo<T: only Pointee + Destruct>() {} // old code would mean this
```
Tyler: So we can't add a new hierarchy that has a common base with another hierarchy, except over an edition. This seems fine.
Niko: For `Self` in traits we don't have `Sized`, and we're talking about migrating that.
```rust
// One model, when adding destruct, requires an edition for this
trait MyTrait {
// we need an edition to change to `Self: only Destruct` by default
}
// In the "only on parameter" model
trait MyTrait {
// we need an edition to change to `Self: only Destruct` by default
}
fn foo<only T: MyTrait> // <-- need an edition to change only here
// But there is also the option of going the other way and saying Sized *is* the default,
// which would mean we can uniformly add `only Foo`
trait MyTrait /* : Sized */ { }
```
Niko: We stumble over the fact that almost everywhere we apply default bounds, but we don't do that for supertrait bounds of traits. One option is that we could, over an edition, reverse that and say that, actually, traits are `Sized` by default.
Josh: I see how you'd need an edition to move from shared roots of hierarchy. MAybe would be easier to have independent traits for independent hierarchies for explicit naming of separate hierarchies. only Pointee would opt out of SizeOfVal but not anything else... I'd expect with Forget/Leak/Destruct we could find a different name for the base to be able to opt out. We shouldn't assume we can define everything up to the base. We can't opt out of Pointee without knowing what's under it. If we needed to, we'd define a new name under Pointee. That's how I think we should deal with overlapping hierarchies -- make them independent.
Tyler: Agree that this is an option. We could unite the hierarchies over an edition.
Niko: One last twist: Ed has a proposal for edition-specific type aliases. One could imagine trait aliases the same way. And similarly, separate trait hierarchies... we define an alias for type without any of the defaults, and you use that edition-versioned alias... this is similar to what Tyler said, but I'm saying we could tie edition-specific ?? to name resolution.
e.g.
```rust!
only trait Hierarchy1
only trait Hierarchy2
mod rust2021 {
trait NoDefault = only Hierarchy1; // in old edition
}
mod rust2024 {
trait NoDefault = only Hierarchy1 + only Hierarchy2; // in new edition
}
// ...then an edition specific pub use
```
TC: Makes sense.
Zachary: (see below under [## `only` -> `requires` and `implies`])
---
TC: To jump all the way back; Niko, I understand now what you're going for in terms of relaxing a particular hierarchy. I I wonder if we're overengineering it. Our trait model is additive, and having to go the other direction for traits is odd. Maybe it's simpler to just turn off the default bounds and then rely on editions for when we need to change these hierarchies. We'll be doing editions yearly.
Niko: We should look at use cases. We act like we can't know what hierarchies we'll want, but substructural type systems have been explored thoroughly. We could look for the possible hierarchies that have been explored. I like the alias-y approach, but it may be over-engineering indeed. The big catch is the default supertrait bounds.
TC: I do like the alias model. There are other places in the language where we could do things that rhyme with that to leverage editions.
## Next steps
TC: What are the questions we could answer for you to best help you move forward?
David: 1) names: seems like we have consensus for `SizeOfVal` and not for `Pointee`. It's not the biggest blocker. 2) what minimal `only` bound type syntax can we agree on that enables what this proposal needs and is sufficiently future compatible such that we can move forward considering that point settled for this RFC
Josh: I like Pointee okay, except that I think its name won't be super clear until we think about what it's like to *not* be Pointee. Some part of me wants it to be a verb, like `TakeRefrence`
TC: We abbreviate reference elsewhere as `Ref`, so we could say `TakeRefTo`.
Tyler: That's interesting. I still like `SizeOfVal`, but I'd like to make sure we've thought about the implications of that name.
Niko: I like the `AddrOf` direction. I usually think of it as taking the address of something. Referring means `&T` to me. I'm still aligned with only bounds how ?? described them. I'd like to see more examples/blogs. It will likely be common to say "this is a thing I can move". Moving and sizedness are orthogonal, I think. That might be an example where something like `T: only Move` would be nice. We should come up with different combinations.
TC: As a summary of where we are, I hear that we like names pointing in the direction of `SizeOfVal`, and we're wondering if we can do something in that direction with `Pointee` too. We seem to all be leaning in the direction of the opt-in + explicit quadrant (e.g., `only`). The question is how exactly that should work. To what degree should it lean on editions? How do we deal with overlapping hierarchies? Etc. Sound right, Niko?
Niko: Yes.
Tyler: We should resolve the "how much of the `only` semantics we need to resolve in order for the RFC to move forward?"
Frank: Should the super traits affect decisions in relaxing bounds? If not, then the exact mechanism of how to "create the hierarchy" isn't the highest importance, assuming this can stay unstable.
I also like verb names for traits in general, but there are 2 specific things in which the `Sized` hierarchy is different: First: Assuming we choose `only` syntax, it should be names that work well with the word `only` in before. The other is that there already exists the `Sized` trait which isn't a verb (nor a "method" name), so `Sized` next to `SizeOfVal` can seem inconsistent. I personally might like `T: only ValueSized`, as that reads as "for type `T`, *only a **value** (of type `T`) is sized* (not the type)".
Tyler: Every time you specify `MyTrait` it implies `only Pointee`
```rust
trait MyTrait: only Pointee {}
```
Niko: I expected `only` to only work with ...
Niko: We haven't decided on whether the syntax should be `+ only` or `only SizeOfVal`.
TC: I want to hear Niko's analysis after he thinks about it awhile.
Tyler: If we use the word `only`, the natural place for it would be in front of a bound or list of bounds. Further, it makes sense for it to be next to the bound "related to" the `only`.
Tyler: Not proposing this, but the maximally compatible path is if we only allow an "only bound" at the front of a bounds list, e.g.
```rust!
fn foo<T>
where
T: only SizeOfVal + Whatever, // allowed
T: Whatever + only SizeOfVal, // not allowed
```
Josh: Don't think it's worth it; I think we would want `only` to relax a single hierarchy.
Tyler: I have the same inclination.
David: I have an intuition for where the lang team stands on this, we could work it out with Niko. ?? Other than that, I got what I needed from this call.
## (naming) `SizeOfVal` doesn't access the value
Zachary Sample: I think it is a bit confusing that `SizeOfVal` does not access the value to compute the layout. I would expect a trait called `SizeOfVal` to be like what has been called `DynSized` or `ValueSized` in other places and can access the value, and that a trait that *only* uses the metadata to compute layout would not have `Val(ue)` in the name.
If we expect to ever add a `SizeOfValComputed`/`DynSized`/`ValueSized` trait that can access the value to compute its layout (e.g. `ThinCStr`, `LengthPrefixedSlice<T>`), then I think this confusion could become a larger issue, especially if `std::mem::size_of_val` is relaxed to support those types.
If we want to name the trait after a function, perhaps we could add a (bikeshed) `std::mem::size_for_meta<T: (bikeshed) only SizeForMeta>` that will use the metadata and not the value, even if we later add a `SizeOfValComputed`/`DynSized`/`ValueSized`-like trait and relax `size_of_val` to use that.
(and, unrelated to current discussion, perhaps a *safe* `std::mem::checked_size_for_meta` that can fail without UB)
---
Josh: The precedent there is that the existing method doesn't look at the value but only uses it to find the type. In the future, we could look at the value.
Tyler: My inclination is make `SizeOfVal` mean it can look at the value, and to add a new rung in the future if we need something that can only look at metadata. We might, but we're building in the ability to add new rungs to this design. That said, I'd like for y'all to do the analysis and include it in the RFC.
Zachary Sample: one possible issue is `UnsafeCell<T: only SizeOfVal>`, where looking at the value could cause a data race. More Info: https://github.com/rust-lang/lang-team/blob/master/src/design_notes/dynsized_constraints.md#mutex-and-more-generally-unsafecell
TC: What's the plan for next week?
Niko: Review the migrations.
David: We have a doc with the various migrations to make ?? defaults usable.
TC: Does this meeting influence that?
David: Not in important ways.
## Confirming behavior WRT supertrait bounds
> David: Currently we propose that writing `only` in supertrait position is unstable (and that you can't write `only` on a user's trait).
>
> TC: Do we similarly disallow?:
>
> ```rust
> trait Tr where Self: only Pointee {}
> ```
>
> David: We probably ought to allow that to permit opt-ing out of the default supertrait we introduce for backcompat - the limitation on where we allow writing `only` is just to reduce scope, if doing that on user traits only is sufficient then that's fine by me.
TC: I just want to confirm that, in general, at the end of the day, we'd expect that `trait Tr1: only Tr2 {}` to still be equivalent to `trait Tr1 where Self: only Tr2 {}`. There are other places, e.g. for implementable trait aliases, where it's been proposed for behavior to diverge between these. Want to confirm whether that's anticipated here or not.
David: It is my expectation that these would be equivalent
## `only` and other lang features
tmandry: I recall there being some other reasons to adopt `only` having to do with migration, does anyone remember those?
Nadri: chiming in from offline, I think that could be useful for effect generics, since we have this same "the default is you can do a bunch of things, then we have keywords (const, nopanic, etc) to remove some defaults behaviors"
tmandry: Ah, the one I remembered was the `auto impl` related one Niko put above.
## `only` bounds and module-level defaults, or ad-hoc trait hierarchies
tmandry: I'm thinking about a feature that would let you set certain "ambient" bounds in a module, like `Send` in async-heavy code, but allowing you to opt out with `only`. But I'm not sure that the meaning of `only` in this document would work for that.
```rust!
auto bound Future: Send;
fn foo() -> impl Future<Output = ()> // implicitly + Send
{ ... }
fn foo() -> impl only Future<Output = ()>
{ ... }
async fn foo() {} // implicitly Send
async(only Future) fn foo() {} // not Send
```
## `only` -> `requires` and `implies`
Zachary Sample: Maybe we could have different "upper bounds" and "lower bounds", e.g. `trait Tr: requires Sized, implies only SizeOfVal` can only be implemented for `Sized`, but (in other crates?) only implies `SizeOfVal`, so it can be strengthened to `Tr: Sized` or relaxed to `Tr: only SizeOfVal` non-breaking-ly. I'm not sure how useful this would be though. Maybe the `requires` should be treated as implied in the same crate?
Zachary Sample: this could also ease adding a new hierarchy to an edition; traits on existing editions would be implicitly `requires Strongest, implies only Weakest`. This wouldn't *entirely* fix it for if we want something stronger than `Weakest` to be implied in general.
Frank: This could also relate to the `Self` special case meaning in `where` bounds on traits, that `Self: …`-ones are the only one that end up implying things
New reality could be
```rust
trait Foo: Bar
where
i32: Qux<Self>,
{}
// equivalent to
trait Foo
implies
Self: Bar,
where
i32: Qux<Self>,
{}
// whereas
trait Foo2
where
Self: Bar,
i32: Qux<Self>,
{}
// could change in meaning over an edition (no longer implying `T: Bar`
// when someone writes `T: Foo2`, making the behavior consistent
// with the `i32: Qux<Self>` bound)
```
Frank: These thoughts (mine, regarding syntax specifically) are probably are mostly orthogonal to `Sized` hierarchy questions.
Tyler: I like the semantic clarity of `implies`/`requires` bounds, though I'm not sure how it would be to use in a practical sense