reference icon indicating copy to clipboard operation
reference copied to clipboard

Add trait_upcasting related languages changes

Open WaffleLapkin opened this issue 1 year ago • 4 comments

I applied review comments from #1259 and added updates from https://github.com/rust-lang/rust/pull/120248.

cc @crlf0710 @compiler-errors @RalfJung

WaffleLapkin avatar Sep 20 '24 08:09 WaffleLapkin

https://github.com/rust-lang/rust/issues/101336 is still open, did we actually end up committing to something?

WaffleLapkin avatar Sep 20 '24 08:09 WaffleLapkin

@WaffleLapkin: Yes, it's just pending documentation https://github.com/rust-lang/rust/issues/101336#issuecomment-1251216579 -- presumably this is (A.) on Niko's list.

compiler-errors avatar Sep 21 '24 01:09 compiler-errors

You may also want to edit https://doc.rust-lang.org/reference/behavior-considered-undefined.html as Niko mentioned in the issue you linked; you may want to re-read the FCP, but I believe it's UB to conjure up a vtable now since it must be valid for upcasting.

What exactly are you referring to here? I assume the "issue" is https://github.com/rust-lang/rust/issues/101336 (a link would have been good, it took clicking on 4 links to track this down :D ). Niko says a lot of things there, though. :)

RalfJung avatar Sep 21 '24 07:09 RalfJung

@compiler-errors doc.rust-lang.org/reference/behavior-considered-undefined.html already mentions invalid metadata in any kind of pointer makes an invalid value, so I don't think we need to add anything on top of that?

  • Invalid metadata in a wide reference, Box<T>, or raw pointer. The requirement for the metadata is determined by the type of the unsized tail:
    • dyn Trait metadata is invalid if it is not a pointer to a vtable for Trait.
    • Slice ([T]) metadata is invalid if the length is not a valid usize (i.e., it must not be read from uninitialized memory). Furthermore, for wide references and Box<T>, slice metadata is invalid if it makes the total size of the pointed-to value bigger than isize::MAX.

WaffleLapkin avatar Sep 21 '24 09:09 WaffleLapkin

:umbrella: The latest upstream changes (possibly bf115a45b6bbc97cafa9e7c90106c5856fd965ea) made this pull request unmergeable. Please resolve the merge conflicts.

rustbot avatar Dec 03 '24 22:12 rustbot

Any movement on this?

PoignardAzur avatar Dec 14 '24 17:12 PoignardAzur

@PoignardAzur I'm working on a stabilization PR (after which this can be merged)

WaffleLapkin avatar Dec 15 '24 14:12 WaffleLapkin

@compiler-errors could you take another look, do the changes still make sense?

WaffleLapkin avatar Dec 16 '24 15:12 WaffleLapkin

@rustbot ready

WaffleLapkin avatar Dec 16 '24 15:12 WaffleLapkin

In the original PR for this...

  • https://github.com/rust-lang/reference/pull/1259

...there's a discussion about adding a line to the behavior considered undefined of:

  • Performing non-nop coercion on a dangling or unaligned raw pointer.

There was some back and forth and it's not clear where that landed. Thoughts on that?

@compiler-errors @RalfJung @WaffleLapkin

traviscross avatar Dec 17 '24 23:12 traviscross

The comment here is the answer https://github.com/rust-lang/reference/pull/1259/files#r1404804424. I don't think this needs further changing. It doesn't really matter if the pointer is bad; upcasting only cares about the vtable metadata.

compiler-errors avatar Dec 17 '24 23:12 compiler-errors

@compiler-errors doc.rust-lang.org/reference/behavior-considered-undefined.html already mentions invalid metadata in any kind of pointer makes an invalid value, so I don't think we need to add anything on top of that?

  • Invalid metadata in a wide reference, Box<T>, or raw pointer. The requirement for the metadata is determined by the type of the unsized tail:

    • dyn Trait metadata is invalid if it is not a pointer to a vtable for Trait.
    • Slice ([T]) metadata is invalid if the length is not a valid usize (i.e., it must not be read from uninitialized memory). Furthermore, for wide references and Box<T>, slice metadata is invalid if it makes the total size of the pointed-to value bigger than isize::MAX.

@WaffleLapkin I think this isn't quite right. How I read the Behaviors Considered Undefined section, it says...

Producing an invalid value. “Producing” a value happens any time a value is assigned to or read from a place, passed to a function/primitive operation or returned from a function/primitive operation.

where "producing an invalid value is hence immediate UB". But the consensus from https://github.com/rust-lang/rust/issues/101336 was that having an invalid vtable is not a failure of the validity invariant. Rather, the UB occurs when a dyn pointer (raw, reference, whatever) with a malformed vtable is upcast or has a method invoked on it. Because safe code can perform those operations (including on raw pointers, in the case of upcast and potentially method calls in the future), this implies that the safety invariant (the conditions required to release such a value to safe code) requires a valid vtable. But if you can keep the *const dyn Foo confined to unsafe code and be absolutely sure nobody upcasts it, it doesn't require a valid vtable. Quoting https://github.com/rust-lang/rust/issues/101336:

The proposal is as follows:

  • Vtable-adjusting upcasts are safe operations. The upcast is UB if performed on a value without a valid vtable
  • As such, the "safety invariant" requires a fully valid vtable.
  • The "validity invariant" requires *dyn metadata to be word-aligned and non-null.

Vtable-adjusting upcasts are defined as:

  • Trait upcasts that alter the set of methods that can be invoked on the resulting value at runtime (e.g., dyn Bar to dyn Foo from the introduction). In particular, upcasts that simply add or remove auto-traits are not vtable-adjusting (e.g., dyn Debug + Send to dyn Debug).

nikomatsakis avatar Dec 18 '24 21:12 nikomatsakis

But the consensus from https://github.com/rust-lang/rust/issues/101336 was that having an invalid vtable is not a failure of the validity invariant.

To be clear, consensus was that we are not ruling on the validity invariant at this point. The validity invariant for vtable metadata is an open question, discussed at https://github.com/rust-lang/unsafe-code-guidelines/issues/516. Meanwhile, the reference says that the vtable pointer must point to a vtable of the right trait and Miri enforces this; this is following our usual strategy of having a bit more UB for now and possibly relaxing this in the future.

RalfJung avatar Dec 19 '24 06:12 RalfJung

Hmm, OK, that's not what I thought the consensus was. =) Maybe I'm misremembering, though when I read the text I quoted it seems clear-ish. We need to find some clearer way though to describe the "upper/lower bounds" of what is and is not UB, I think it's going to be very hard to keep things in sync over time the way it is now (where it is e.g. difficult to tell if the reference is out of date or over approximating).

On Thu, Dec 19, 2024, at 1:51 AM, Ralf Jung wrote:

But the consensus from rust-lang/rust#101336 https://github.com/rust-lang/rust/issues/101336 was that having an invalid vtable is not a failure of the validity invariant.

To be clear, consensus was that we are not ruling on the validity invariant at this point. The validity invariant for vtable metadata is an open question, discussed at rust-lang/unsafe-code-guidelines#516 https://github.com/rust-lang/unsafe-code-guidelines/issues/516. Meanwhile, the reference says that the vtable pointer must point to a vtable of the right trait and Miri enforces this; this is following our usual strategy of having a bit more UB for now and possibly relaxing this in the future.

— Reply to this email directly, view it on GitHub https://github.com/rust-lang/reference/pull/1622#issuecomment-2552917895, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABF4ZX7ZXAI3MZZOHKHJNL2GJUI7AVCNFSM6AAAAABORRYCSKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNJSHEYTOOBZGU. You are receiving this because you commented.Message ID: @.***>

nikomatsakis avatar Dec 20 '24 00:12 nikomatsakis

We currently say this above the UB list

The following list is not exhaustive; it may grow or shrink.

So the entire thing should be considered as approximating. Maybe we should start slowly widdling this down to just a few items in the list, though I think we should always reserve the right to remove UB.

Anyway this is getting off-topic for this PR. The validity invariant for vtables doesn't have to be settled for this one.

RalfJung avatar Dec 20 '24 06:12 RalfJung

@rustbot labels +I-lang-nominated

When we handled the nomination for starting the FCP on https://github.com/rust-lang/rust/pull/134367, we reviewed this text, leading to some back and forth. Let's nominate to double check we're OK with where that landed.

traviscross avatar Jan 07 '25 23:01 traviscross

As a note I'm working on rewriting most of src/type-coercions.md, when reading it carefully I found a lot of outdated/incorrect/misleading info. I'd like to land that as a follow up to this.

WaffleLapkin avatar Jan 08 '25 14:01 WaffleLapkin

OK, so I re-read https://github.com/rust-lang/rust/issues/101336 and in particular found this comment which was asking whether the validity invariant for vtables was a "decision" or just a "strong recommendation". I guess @RalfJung interpreted it as the latter, which seems fine. I have edited the issue to clarify. I agree then that no edits are needed to the list of UB, as no new validity invariants have been decided.

nikomatsakis avatar Jan 09 '25 16:01 nikomatsakis

Wearing lang-team hat: +1

EDIT: Well, +1 to the substance, I have some concerns lingering in comments actually that I would like to see resolved. Specifically the as point.

nikomatsakis avatar Jan 15 '25 16:01 nikomatsakis

@rustbot label -I-lang-nominated

I've also prepared a refactor of the unsizing section: de3ffc3e19c141ac7d6cf08beba4545a3f4e0a9f. I'll open a PR once this is merged.

WaffleLapkin avatar Feb 07 '25 01:02 WaffleLapkin

https://github.com/rust-lang/rust/pull/134367#event-16230091099 has been merged, so this can be merged as well :)

WaffleLapkin avatar Feb 07 '25 22:02 WaffleLapkin

I rebased to collapse some back and forth, to fix an author name, to make some minor stylistic tweaks (capitalization and line unwrapping), and to remove the note section mentioned above.

We're anticipating further work on this to address some things raised in the threads here in a follow-up PR that Waffle has in progress.

traviscross avatar Feb 08 '25 22:02 traviscross

Follow-up: https://github.com/rust-lang/reference/pull/1731

WaffleLapkin avatar Feb 09 '25 13:02 WaffleLapkin