Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure to use Receiver trait when extracting object method candidate #135179

Merged
merged 1 commit into from
Feb 8, 2025

Conversation

compiler-errors
Copy link
Member

@compiler-errors compiler-errors commented Jan 7, 2025

In method confirmation, the extract_existential_trait_ref function re-extracts the object type by derefing until it reaches an object. If we're assembling methods via the Receiver trait, make sure we re-do our work also using the receiver trait.

Fixes #135155

cc @adetaylor

@rustbot
Copy link
Collaborator

rustbot commented Jan 7, 2025

r? @Nadrieril

rustbot has assigned @Nadrieril.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 7, 2025
@Nadrieril
Copy link
Member

r? compiler

@rustbot rustbot assigned petrochenkov and unassigned Nadrieril Jan 8, 2025
@petrochenkov
Copy link
Contributor

r? compiler

@rustbot rustbot assigned jieyouxu and unassigned petrochenkov Jan 8, 2025
@compiler-errors
Copy link
Member Author

r? wesleywiser who has reviewed the other arbitrary self types prs, though perhaps re-roll to someone on t-types if you're uncomfortable with reviewing this

@rustbot rustbot assigned wesleywiser and unassigned jieyouxu Jan 8, 2025
Copy link
Member

@wesleywiser wesleywiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me but I would like someone from T-types to confirm I'm not overlooking anything 🙂

@wesleywiser
Copy link
Member

r? types

@rustbot rustbot added the T-types Relevant to the types team, which will review and decide on the PR/issue. label Jan 21, 2025
@rustbot rustbot assigned BoxyUwU and unassigned wesleywiser Jan 21, 2025
@adetaylor
Copy link
Contributor

Thanks for this - I just discovered the same thing. Fix looks good to me.

adetaylor added a commit to google/autocxx that referenced this pull request Jan 22, 2025
Background:

Rust references have certain rules, most notably that the underlying data
cannot be changed while an immutable reference exists. That's essentially
impossible to promise for any C++ data; C++ may retain references or pointers
to data any modify it at any time. This presents a problem for Rust/C++ interop
tooling. Various solutions or workarounds are possible:

1) All C++ data is represented as zero-sized types.
   This is the approach taken by cxx for opaque types. This sidesteps all of the
   Rust reference rules, since those rules only apply to areas of memory that
   are referred to. This doesn't really work well enough for autocxx since
   we want to be able to keep C++ data on the Rust stack, using all the fancy
   moveit shenanigans, and that means that Rust must know the true size and
   alignment of the type.

2) All C++ data is represented as UnsafeCell<MaybeUninit<T>>.
   This also sidesteps the reference rules. This would be a valid option for
   autocxx.

3) Have a sufficiently simple language boundary that humans can
   reasonably guarantee there are no outstanding references on the C++ side
   which could be used to modify the underlying data.
   This is the approach taken by cxx for cxx::kind::Trivial types. It's
   just about possible to cause UB using one of these types, but you really
   have to work at it. In practice such UB is unlikely.

4) Never allow Rust references to C++ types. Instead use a special
   smart pointer type in Rust, representing a C++ reference.
   This is the direction in this PR.

More detail on this last approach here:
https://medium.com/@adetaylor/are-we-reference-yet-c-references-in-rust-72c1c6c7015a

This facility is already in autocxx, by adopting the safety policy
"unsafe_references_wrapped". However, it hasn't really been battle tested
and has a bunch of deficiencies.

It's been awaiting formal Rust support for "arbitrary self types" so that methods
can be called on such smart pointers. This is now
[fairly close to stabilization](rust-lang/rust#44874 (comment));
this PR is part of the experimentation required to investigate whether that rustc
feature should go ahead and get stabilized.

This PR essentially converts autocxx to only operate in this mode - there should
no longer ever be Rust references to C++ data.

This PR is incomplete:
* There are still 60 failing integration tests. Mostly these relate to subclass
  support, which isn't yet converted.
* `ValueParam` and `RValueParam` need to support taking `CppPin<T>`, and possibly
  `CppRef<T: CopyNew>` etc.
* Because we can't implement `Deref` for `cxx::UniquePtr<T>` to emit a
  `CppRef<T>`, unfortunately `cxx::UniquePtr<T>` can't be used in cases where
  we want to provide a `const T&`. It's necessary to call `.as_cpp_ref()` on the
  `UniquePtr`. This is sufficiently annoying that it might be necessary to
  implement a trait `ReferenceParam` like we have for `ValueParam` and `RValueParam`.
  (Alternatives include upstreaming `CppRef<T>` into cxx, but per reason 4 listed
  above, the complexity probably isn't merited for statically-declared cxx
  interfaces; or separating from cxx entirely.)

This also shows up a [Rustc problem which is fixed here](rust-lang/rust#135179).

Ergonomic findings:
* The problem with `cxx::UniquePtr` as noted above.
* It's nice that `Deref` coercion allows methods to be called on `CppPin` as well
  as `CppRef`.
* To get the same benefit for parameters being passed in by reference, you need
  to pass in `&my_cpp_pin_wrapped_thing` which is weird given that the whole
  point is we're trying to avoid Rust references. Obviously, calling `.as_cpp_ref()`
  works too, so this weirdness can be avoided.
* When creating some C++ data `T`, in Rust, it's annoying to have to decide a-priori
  whether it'll be Rust or C++ accessing the data. If the former, you just create
  a new `T`; if the latter you need to wrap it in `CppPin::new`. This is only
  really a problem when creating a C++ object on which you'll call methods. It
  feels like it'll be OK in practice. Possibly this can be resolved by making
  the method receiver some sort of `impl MethodReceiver<T>` generic; an implementation
  for `T` could be provided which auto-wraps it into a `CppPin` (consuming it at that
  point). This sounds messy though. A bit more thought required, but even if this
  isn't possible it doesn't sound like a really serious ergonomics problem,
  especially if we can use `#[diagnostic::on_unimplemented]` somehow to guide.

Next steps here:
* Stabilize arbitrary self types. This PR has gone far enough to show that
  there are no really serious unexpected issues there.
* Implement `ValueParam` and `RValueParam` as necessary for `CppRef` and
  `CppPin` types.
* Work on those ergonomic issues to the extent possible.
* Make a bold decision about whether autocxx should shift wholesale away from
  `&` to `CppRef<T>`. If so, this will be a significant breaking change.
@compiler-errors
Copy link
Member Author

This has been open for a month with no review, re-rolling

r? types

@rustbot rustbot assigned jackh726 and unassigned BoxyUwU Feb 4, 2025
@BoxyUwU
Copy link
Member

BoxyUwU commented Feb 7, 2025

r? @BoxyUwU
@bors r+ rollup
sorry

@bors
Copy link
Contributor

bors commented Feb 7, 2025

📌 Commit 999695b has been approved by BoxyUwU

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 7, 2025
@RalfJung
Copy link
Member

RalfJung commented Feb 7, 2025

Should this be added as a testcase or is it "obviously the same" as the existing testcase?

@compiler-errors
Copy link
Member Author

It's obviously the same. It just has to do with any dyn dispatch through a pointer that impls Receiver but not Deref.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Feb 7, 2025
…es-object, r=BoxyUwU

Make sure to use `Receiver` trait when extracting object method candidate

In method confirmation, the `extract_existential_trait_ref` function re-extracts the object type by derefing until it reaches an object. If we're assembling methods via the `Receiver` trait, make sure we re-do our work also using the receiver trait.

Fixes rust-lang#135155

cc `@adetaylor`
bors added a commit to rust-lang-ci/rust that referenced this pull request Feb 8, 2025
…iaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#135179 (Make sure to use `Receiver` trait when extracting object method candidate)
 - rust-lang#136554 (Add `opt_alias_variances` and use it in outlives code)
 - rust-lang#136556 ([AIX] Update tests/ui/wait-forked-but-failed-child.rs to accomodate exiting and idle processes.)
 - rust-lang#136589 (Enable "jump to def" feature on rustc docs)
 - rust-lang#136615 (sys: net: Add UEFI stubs)
 - rust-lang#136635 (Remove outdated `base_port` calculation in std net test)
 - rust-lang#136682 (Move two windows process tests to tests/ui)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit c49fc91 into rust-lang:master Feb 8, 2025
6 checks passed
@rustbot rustbot added this to the 1.86.0 milestone Feb 8, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Feb 8, 2025
Rollup merge of rust-lang#135179 - compiler-errors:arbitrary-self-types-object, r=BoxyUwU

Make sure to use `Receiver` trait when extracting object method candidate

In method confirmation, the `extract_existential_trait_ref` function re-extracts the object type by derefing until it reaches an object. If we're assembling methods via the `Receiver` trait, make sure we re-do our work also using the receiver trait.

Fixes rust-lang#135155

cc ``@adetaylor``
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ICE: self-type MyDispatcher<dyn Trait> for ObjectPick never dereferenced to an object