question-mark introduces move error
matthiaskrgr opened this issue · 0 comments
matthiaskrgr commented
Summary
this code is somehow cursed, when I tried to remove more functions the error went away :(
Lint Name
question-mark
Reproducer
I tried this code:
// run-rustfix
#![allow(unreachable_code)]
#![allow(clippy::unnecessary_wraps)]
fn some_func(a: Option<u32>) -> Option<u32> {
if a.is_none() {
return None;
}
a
}
fn some_other_func(a: Option<u32>) -> Option<u32> {
if a.is_none() {
return None;
} else {
return Some(0);
}
unreachable!()
}
pub enum SeemsOption<T> {
Some(T),
None,
}
impl<T> SeemsOption<T> {
pub fn is_none(&self) -> bool {
match *self {
SeemsOption::None => true,
SeemsOption::Some(_) => false,
}
}
}
fn returns_something_similar_to_option(a: SeemsOption<u32>) -> SeemsOption<u32> {
if a.is_none() {
return SeemsOption::None;
}
a
}
pub struct CopyStruct {
pub opt: Option<u32>,
}
impl CopyStruct {
#[rustfmt::skip]
pub fn func(&self) -> Option<u32> {
if (self.opt).is_none() {
return None;
}
if self.opt.is_none() {
return None
}
let _ = if self.opt.is_none() {
return None;
} else {
self.opt
};
let _ = if let Some(x) = self.opt {
x
} else {
return None;
};
self.opt
}
}
#[derive(Clone)]
pub struct MoveStruct {
pub opt: Option<Vec<u32>>,
}
impl MoveStruct {
pub fn ref_func(&self) -> Option<Vec<u32>> {
if self.opt.is_none() {
return None;
}
self.opt.clone()
}
pub fn mov_func_reuse(self) -> Option<Vec<u32>> {
if self.opt.is_none() {
return None;
}
self.opt
}
pub fn mov_func_no_use(self) -> Option<Vec<u32>> {
if self.opt.is_none() {
return None;
}
Some(Vec::new())
}
pub fn if_let_ref_func(self) -> Option<Vec<u32>> {
let v: &Vec<_> = if let Some(ref v) = self.opt {
v
} else {
return None;
};
Some(v.clone())
}
pub fn if_let_mov_func(self) -> Option<Vec<u32>> {
let v = if let Some(v) = self.opt {
v
} else {
return None;
};
Some(v)
}
}
fn func() -> Option<i32> {
fn f() -> Option<String> {
Some(String::new())
}
if f().is_none() {
return None;
}
Some(0)
}
fn func_returning_result() -> Result<i32, String> {
Ok(1)
}
fn result_func(x: Result<i32, String>) -> Result<i32, String> {
let _ = if let Ok(x) = x { x } else { return x };
if x.is_err() {
return x;
}
// No warning
let y = if let Ok(x) = x {
x
} else {
return Err("some error".to_string());
};
// issue #7859
// no warning
let _ = if let Ok(x) = func_returning_result() {
x
} else {
return Err("some error".to_string());
};
if func_returning_result().is_err() {
return func_returning_result();
}
Ok(y)
}
fn main() {}
I saw this happen:
This likely indicates a bug in either rustc or cargo itself,
and we would appreciate a bug report! You're likely to see
a number of compiler warnings after this message which cargo
attempted to fix but failed. If you could open an issue at
https://github.com/rust-lang/rust/issues
quoting the full output of this command we'd be very appreciative!
Note that you may be able to make some more progress in the near-term
fixing code with the `--broken-code` flag
The following errors were reported:
error[E0382]: use of moved value: `x`
--> src/main.rs:118:23
|
112 | fn result_func(x: Result<i32, String>) -> Result<i32, String> {
| - move occurs because `x` has type `std::result::Result<i32, std::string::String>`, which does not implement the `Copy` trait
113 | let _ = x?;
| -- `x` moved due to this method call
...
118 | let y = if let Ok(x) = x {
| ^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
113 | let _ = x.clone()?;
| ++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.
Original diagnostics will follow.
Version
rustc 1.67.0-nightly (c97b539e4 2022-11-30)
binary: rustc
commit-hash: c97b539e408ea353f4fde2f9251d598291fec421
commit-date: 2022-11-30
host: x86_64-unknown-linux-gnu
release: 1.67.0-nightly
LLVM version: 15.0.4
Additional Labels
No response