-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Can derive
be smarter about lifetime parameters?
#27950
Comments
Your suggested transformation could very easily go wrong: in some cases, the derived implementation wouldn't compile. Very simple example: you write Input2<'a>, which contains a field Input<'a>, and Input's PartialEq is implemented like |
@eefriedman Can you expand on your example? |
use std::cmp::PartialEq;
struct Input<'a> {
bytes: &'a [u8],
}
impl <'a> PartialEq for Input<'a> {
#[inline]
fn eq(&self, _other: &Input<'a>) -> bool {
panic!()
}
}
struct Input2<'a> {
i: Input<'a>
}
impl<'a, 'b> PartialEq<Input2<'b>> for Input2<'a> {
#[inline]
fn eq(&self, other: &Input2<'b>) -> bool {
self.i == other.i // error here
}
}
fn main() {} |
@eefriedman You're missing the |
@eddyb The compiler currently rejects |
Created pull request #27972. |
So, it's one year later. I took @eefriedman's example with the error, added @eddyb's where clause, and it compiles just fine: https://is.gd/m3phSn Is it time we could change the derive code to work this way now? |
I was just talking with ajeffrey on IRC about the most generalized version of #[derive(PartialEq)]
struct Foo<'a, A, B> {
a: &'a [A],
b: Vec<B>,
c: String,
}
// generated
impl<'a1, 'a2, A1, A2, B1, B2> PartialEq<Foo<'a2, A2, B2>> for Foo<'a1, A1, B1>
where
&'a1 [A1]: PartialEq<&'a2 [A2]>, // for self.a == other.a
Vec<B1>: PartialEq<Vec<B2>>, // for self.b == other.b
String: PartialEq<String>, // for self.c == other.c. Obviously redundant, but not a real problem and the macro can't be type-directed.
{
...
} That is, with a fully separately generalized right-hand side type and constraints based on the actual field types you will be comparing, not on the type parameters. Note that it can be the case that This formulation should handle cases like in the OP and a lot more besides. |
I'm going to close this in favor of #26925. That's the specific issue this is tracking (derive being not as intelligent as perhaps we'd want); I don't think separate issues are useful in this case. |
rust-lang/rust#27950 was closed in favor of rust-lang/rust#26925.
briansmith on IRC ran into trouble using
#[derive(PartialEq)]
on a struct with a lifetime parameter. See the code at http://is.gd/R6Jx2x which fails with:Even though a similar function working directly with byte slices is fine with the lifetime parameters differing. Following the error message's suggestion works, but forces explicit lifetimes where one would expect elision to work (as it does with the byte slices).
The issue is shown in the expanded code from
derive
pasted below. It's because theRhs
type for the impl defaults toSelf
, which isInput<'a>
, which strictly requires the exact same lifetime.Below that, I wrote a modified version of the derived impl showing what we wanted to be generated. It introduces a new lifetime parameter on the impl for each lifetime parameter on the original struct and sets
Rhs
to be the same type asSelf
except with those lifetime parameters substituted. (In this case, just'a
replaced with'b
.) This actually works: http://is.gd/1GjWDDSo, can
derive
do this (seemingly) simple transformation for types with lifetime parameters? Can someone with more experience chip in and explain why this would go horribly wrong? :PThe text was updated successfully, but these errors were encountered: