-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Unexpected lifetime issue when comparing Option<&i32> #42966
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
The compiler says that this code, with explicit lifetime parameters, has a type mismatch between fn check<'a, 'b>(a: Option<&'a i32>, b: &'b i32) -> bool {
let tmp: Option<&'b i32> = Some(b);
a == tmp //< mismatched types
} It says fn check<'a, 'b>(a: Option<&'a i32>, b: &'b i32) -> bool where 'b: 'a {
let tmp: Option<&'b i32> = Some(b);
a == tmp
} And it compiles well. What's strange is, fn check<'a, 'b>(a: Option<&'a i32>, b: &'b i32) -> bool where 'b: 'a {
let tmp: Option<&'b i32> = Some(b);
let eq1 = a == tmp;
let eq2 = tmp == a; //< mismatched types
assert_eq!(eq1, eq2);
eq1
} This is definitely wrong. |
More testcases. This works well: fn should_equal<'a, 'b>(a: Option<&'a usize>, b: &'b usize) {
let b = Some(b);
assert_eq!(a, b);
assert_eq!(b, a);
} However, this fails compiling: fn should_equal<'a, 'b>(a: Option<&'a usize>, b: &'b usize) {
let b = Some(b);
assert!(a == b);
assert!(b == a);
} |
The |
This is the code generated by #[automatically_derived]
#[allow(unused_qualifications)]
#[stable(feature = "rust1", since = "1.0.0")]
impl <T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for Option<T> {
#[inline]
fn eq(&self, __arg_0: &Option<T>) -> bool {
{
let __self_vi =
unsafe { ::std::intrinsics::discriminant_value(&*self) } as
isize;
let __arg_1_vi =
unsafe { ::std::intrinsics::discriminant_value(&*__arg_0) } as
isize;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Option::Some(ref __self_0),
&Option::Some(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
_ => true,
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &Option<T>) -> bool {
{
let __self_vi =
unsafe { ::std::intrinsics::discriminant_value(&*self) } as
isize;
let __arg_1_vi =
unsafe { ::std::intrinsics::discriminant_value(&*__arg_0) } as
isize;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Option::Some(ref __self_0),
&Option::Some(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
_ => false,
}
} else { true }
}
}
} |
And a "simpler" case that generates the same error: pub struct Foo<'a>(&'a usize);
impl<'a> ::std::cmp::PartialEq for Foo<'a> {
fn eq(&self, _: &Foo<'a>) -> bool { true }
fn ne(&self, _: &Foo<'a>) -> bool { false }
}
fn should_equal<'a, 'b>(a: Foo<'a>, b: &'b usize) {
assert!(a == Foo(b));
} |
This appears to be a problem with the equal operator, not the PartialEq implementation or trait, as this works fine: https://play.rust-lang.org/?gist=32afb56e08f6d275711698f0a4fc7f61&version=stable&backtrace=0 fn check(a: Option<&i32>, b: &i32) -> bool {
a.eq(&Some(b))
} |
This issue looks resolved? The error no longer occurs when I try my example in the playground. However I've no idea when, why or what caused the issue. Can anyone confirm as fixed? |
Fix was probably #45435 |
that sounds plausible, I'll close this issue then |
I tried this code:
I expected to see this happen: Code compiles and works as expected.
Switching the equality around like this compiles successfully and works as expected:
Alternatively explicitly forcing both references to a shared lifetime works too:
Instead, this happened: error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
Meta
https://play.rust-lang.org/?gist=9bd7c205c280df1ea37bb49cd3ecca25&version=stable&backtrace=0
The text was updated successfully, but these errors were encountered: