You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a trait has a nontrivial parameter, materialize it in the caller.
(Technically, this does let you call trait methods with nontrivial arguments,
but it's not in a final/decent place.)
This is an alternate version of unknown commit which tried to continue to defer
materialization. However, as discussed in[]
currently impossible.
In particular, we cannot define a trait like this:
```rs
impl<T: Ctor<Output=A>> MyTrait<T> for S {...}
impl<T: Ctor<Output=B>> MyTrait<T> for S {...}
```
... because Rust does not understand that these impls are disjoint:
rust-lang/rust#20400
#### What's next?
(Apologies if this is a bit unorganized, I've spent too much time in the trenches.)
So this CL is just a first step: we *must* monomorphize the implementation.
Rather than accepting any `T: Ctor`, accept an `RvalueReference` (a concrete type).
After this CL, I think we have a slightly more open field than I thought. In particular,
we should be able to regain the `Ctor` API, except using only *one* parameterized impl.
So, instead of the broken impls above, we can have this impl:
```rs
impl<'a> MyTrait<RvalueReference<'a, A>> for S {...}
impl<'a> MyTrait<RvalueReference<'a, B>> for S {...}
impl<U, CtorType> MyTrait<CtorType> for S
where
&C : for<'a> MyTrait<RvalueReference<'a, U>>,
CtorType: Ctor<Output=U>
{...}
```
Because this is only _one_ parameterized impl, there's no conflicts. It is
implemented in terms of the concrete non-parameterized impls as generated by
this change.
However, I'm not yet 100% certain this will work, and it is actually not a small task
to do, even on top of this CL. For example, there's a bunch of refactoring to let one
generate a second blanket impl using knowledge about the trait function etc. from the
concrete impl.
##### RvalueReference might need to get replaced.
If we can use the `Ctor` approach described above... we can't use `RvalueReference`,
actually, because Rust will then recurse infinitely. The `RvalueReference` type used
for the `for<'a> MyTrait<RvalueReference<...>>` bound must be in the _same_ crate so
that Rust knows that `RvalueReference` doesn't itself impl `Ctor`. And unfortunately,
no, negative impls aren't good enough here, yet, apparently. At least, it didn't
resolve it when I tried it!
You can test this in a local two-crate setup.
Crate 1:
```rs
pub trait Ctor {
type Output;
}
pub struct RvalueReference<'a, T>(&'a T);
```
Crate 2:
```rs
use lib1::*;
pub struct A1;
pub struct A2;
pub struct B;
impl <'a> From<RvalueReference<'a, A1>> for B {
fn from(_: RvalueReference<'a, A1>) -> Self { todo!(); }
}
impl <'a> From<RvalueReference<'a, A2>> for B {
fn from(_: RvalueReference<'a, A2>) -> Self { todo!(); }
}
impl <T: Ctor> From<T> for B
where B : for<'a> From<RvalueReference<'a, T::Output>> {
fn from(_: T) -> Self { todo!(); }
}
```
If you build crate 2, it will fail with the following error:
```
error[E0275]: overflow evaluating the requirement `for<'a> B: From<lib1::RvalueReference<'a, _>>`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`lib2`)
note: required because of the requirements on the impl of `for<'a> From<lib1::RvalueReference<'a, _>>` for `B`
--> src/lib.rs:15:16
|
15 | impl <T: Ctor> From<T> for B
| ^^^^^^^ ^
= note: 126 redundant requirements hidden
= note: required because of the requirements on the impl of `for<'a> From<lib1::RvalueReference<'a, _>>` for `B`
For more information about this error, try `rustc --explain E0275`.
error: could not compile `lib2` due to previous error
```
But it will work fine if you move `RvalueReference` to another crate!
##### If all else fails, we'll force the caller to materialize the Ctor
If even the approach outlined above doesn't work, well, we'll just have to force callers
to materialize the `Ctor`: call `Trait::method(mov(emplace!(foo())))` instead of
`Trait::method(foo())`.
That's what I described in[]
but I'm hoping we can work our way out after all!
Either way, both approaches build on this change. Investigating the followups may take some
time, so I'd rather not leave this change sitting around generating merge conflicts,
if possible. :X
PiperOrigin-RevId: 464613254
0 commit comments