-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Unexpected lifetime issue when comparing Option<&i32> #42966
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: