Skip to content
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

Stabilize some Result methods as const #76136

Merged
merged 5 commits into from
Sep 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
#![feature(const_ptr_offset)]
#![feature(const_ptr_offset_from)]
#![feature(const_raw_ptr_comparison)]
#![feature(const_result)]
#![feature(const_slice_from_raw_parts)]
#![feature(const_slice_ptr_len)]
#![feature(const_size_of_val)]
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ impl<T, E> Result<T, E> {
/// assert_eq!(x.is_ok(), false);
/// ```
#[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
#[rustc_const_unstable(feature = "const_result", issue = "67520")]
#[rustc_const_stable(feature = "const_result", since = "1.48.0")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub const fn is_ok(&self) -> bool {
Expand All @@ -294,7 +294,7 @@ impl<T, E> Result<T, E> {
/// assert_eq!(x.is_err(), true);
/// ```
#[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
#[rustc_const_unstable(feature = "const_result", issue = "67520")]
#[rustc_const_stable(feature = "const_result", since = "1.48.0")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub const fn is_err(&self) -> bool {
Expand Down Expand Up @@ -438,7 +438,7 @@ impl<T, E> Result<T, E> {
/// assert_eq!(x.as_ref(), Err(&"Error"));
/// ```
#[inline]
#[rustc_const_unstable(feature = "const_result", issue = "67520")]
#[rustc_const_stable(feature = "const_result", since = "1.48.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub const fn as_ref(&self) -> Result<&T, &E> {
match *self {
Expand Down
16 changes: 16 additions & 0 deletions library/core/tests/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,19 @@ fn test_result_as_deref_mut() {
let expected_result = Result::Err::<&mut u32, &mut Vec<i32>>(&mut expected_vec);
assert_eq!(mut_err.as_deref_mut(), expected_result);
}

#[test]
fn result_const() {
// test that the methods of `Result` are usable in a const context

const RESULT: Result<usize, bool> = Ok(32);

const REF: Result<&usize, &bool> = RESULT.as_ref();
assert_eq!(REF, Ok(&32));

const IS_OK: bool = RESULT.is_ok();
assert!(IS_OK);

const IS_ERR: bool = RESULT.is_err();
assert!(!IS_ERR)
}
8 changes: 4 additions & 4 deletions src/tools/clippy/clippy_lints/src/matches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1469,10 +1469,10 @@ mod redundant_pattern_match {
keyword: &'static str,
) {
fn find_suggestion(cx: &LateContext<'_>, hir_id: HirId, path: &QPath<'_>) -> Option<&'static str> {
if match_qpath(path, &paths::RESULT_OK) && can_suggest(cx, hir_id, sym!(result_type), "is_ok") {
if match_qpath(path, &paths::RESULT_OK) {
return Some("is_ok()");
}
if match_qpath(path, &paths::RESULT_ERR) && can_suggest(cx, hir_id, sym!(result_type), "is_err") {
if match_qpath(path, &paths::RESULT_ERR) {
return Some("is_err()");
}
if match_qpath(path, &paths::OPTION_SOME) && can_suggest(cx, hir_id, sym!(option_type), "is_some") {
Expand Down Expand Up @@ -1562,8 +1562,8 @@ mod redundant_pattern_match {
&paths::RESULT_ERR,
"is_ok()",
"is_err()",
|| can_suggest(cx, hir_id, sym!(result_type), "is_ok"),
|| can_suggest(cx, hir_id, sym!(result_type), "is_err"),
|| true,
|| true,
)
} else {
None
Expand Down
35 changes: 18 additions & 17 deletions src/tools/clippy/tests/ui/redundant_pattern_matching.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ fn main() {

issue5504();
issue5697();
issue6067();

let _ = if gen_opt().is_some() {
1
Expand Down Expand Up @@ -131,31 +132,14 @@ fn issue5504() {
// None of these should be linted because none of the suggested methods
// are `const fn` without toggling a feature.
const fn issue5697() {
if let Ok(_) = Ok::<i32, i32>(42) {}

if let Err(_) = Err::<i32, i32>(42) {}

if let Some(_) = Some(42) {}

if let None = None::<()> {}

while let Ok(_) = Ok::<i32, i32>(10) {}

while let Err(_) = Ok::<i32, i32>(10) {}

while let Some(_) = Some(42) {}

while let None = None::<()> {}

match Ok::<i32, i32>(42) {
Ok(_) => true,
Err(_) => false,
};

match Err::<i32, i32>(42) {
Ok(_) => false,
Err(_) => true,
};
match Some(42) {
Some(_) => true,
None => false,
Expand All @@ -166,3 +150,20 @@ const fn issue5697() {
None => true,
};
}

// Methods that are unstable const should not be suggested within a const context, see issue #5697.
// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const,
// so the following should be linted.
const fn issue6067() {
if Ok::<i32, i32>(42).is_ok() {}

if Err::<i32, i32>(42).is_err() {}

while Ok::<i32, i32>(10).is_ok() {}

while Ok::<i32, i32>(10).is_err() {}

Ok::<i32, i32>(42).is_ok();

Err::<i32, i32>(42).is_err();
}
41 changes: 24 additions & 17 deletions src/tools/clippy/tests/ui/redundant_pattern_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ fn main() {

issue5504();
issue5697();
issue6067();

let _ = if let Some(_) = gen_opt() {
1
Expand Down Expand Up @@ -152,31 +153,14 @@ fn issue5504() {
// None of these should be linted because none of the suggested methods
// are `const fn` without toggling a feature.
const fn issue5697() {
if let Ok(_) = Ok::<i32, i32>(42) {}

if let Err(_) = Err::<i32, i32>(42) {}

if let Some(_) = Some(42) {}

if let None = None::<()> {}

while let Ok(_) = Ok::<i32, i32>(10) {}

while let Err(_) = Ok::<i32, i32>(10) {}

while let Some(_) = Some(42) {}

while let None = None::<()> {}

match Ok::<i32, i32>(42) {
Ok(_) => true,
Err(_) => false,
};

match Err::<i32, i32>(42) {
Ok(_) => false,
Err(_) => true,
};
match Some(42) {
Some(_) => true,
None => false,
Expand All @@ -187,3 +171,26 @@ const fn issue5697() {
None => true,
};
}

// Methods that are unstable const should not be suggested within a const context, see issue #5697.
// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const,
// so the following should be linted.
const fn issue6067() {
if let Ok(_) = Ok::<i32, i32>(42) {}

if let Err(_) = Err::<i32, i32>(42) {}

while let Ok(_) = Ok::<i32, i32>(10) {}

while let Err(_) = Ok::<i32, i32>(10) {}

match Ok::<i32, i32>(42) {
Ok(_) => true,
Err(_) => false,
};

match Err::<i32, i32>(42) {
Ok(_) => false,
Err(_) => true,
};
}
60 changes: 51 additions & 9 deletions src/tools/clippy/tests/ui/redundant_pattern_matching.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -149,52 +149,94 @@ LL | let x = if let Some(_) = opt { true } else { false };
| -------^^^^^^^------ help: try this: `if opt.is_some()`

error: redundant pattern matching, consider using `is_some()`
--> $DIR/redundant_pattern_matching.rs:102:20
--> $DIR/redundant_pattern_matching.rs:103:20
|
LL | let _ = if let Some(_) = gen_opt() {
| -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`

error: redundant pattern matching, consider using `is_none()`
--> $DIR/redundant_pattern_matching.rs:104:19
--> $DIR/redundant_pattern_matching.rs:105:19
|
LL | } else if let None = gen_opt() {
| -------^^^^------------ help: try this: `if gen_opt().is_none()`

error: redundant pattern matching, consider using `is_ok()`
--> $DIR/redundant_pattern_matching.rs:106:19
--> $DIR/redundant_pattern_matching.rs:107:19
|
LL | } else if let Ok(_) = gen_res() {
| -------^^^^^------------ help: try this: `if gen_res().is_ok()`

error: redundant pattern matching, consider using `is_err()`
--> $DIR/redundant_pattern_matching.rs:108:19
--> $DIR/redundant_pattern_matching.rs:109:19
|
LL | } else if let Err(_) = gen_res() {
| -------^^^^^^------------ help: try this: `if gen_res().is_err()`

error: redundant pattern matching, consider using `is_some()`
--> $DIR/redundant_pattern_matching.rs:141:19
--> $DIR/redundant_pattern_matching.rs:142:19
|
LL | while let Some(_) = r#try!(result_opt()) {}
| ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`

error: redundant pattern matching, consider using `is_some()`
--> $DIR/redundant_pattern_matching.rs:142:16
--> $DIR/redundant_pattern_matching.rs:143:16
|
LL | if let Some(_) = r#try!(result_opt()) {}
| -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`

error: redundant pattern matching, consider using `is_some()`
--> $DIR/redundant_pattern_matching.rs:148:12
--> $DIR/redundant_pattern_matching.rs:149:12
|
LL | if let Some(_) = m!() {}
| -------^^^^^^^------- help: try this: `if m!().is_some()`

error: redundant pattern matching, consider using `is_some()`
--> $DIR/redundant_pattern_matching.rs:149:15
--> $DIR/redundant_pattern_matching.rs:150:15
|
LL | while let Some(_) = m!() {}
| ----------^^^^^^^------- help: try this: `while m!().is_some()`

error: aborting due to 29 previous errors
error: redundant pattern matching, consider using `is_ok()`
--> $DIR/redundant_pattern_matching.rs:179:12
|
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`

error: redundant pattern matching, consider using `is_err()`
--> $DIR/redundant_pattern_matching.rs:181:12
|
LL | if let Err(_) = Err::<i32, i32>(42) {}
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`

error: redundant pattern matching, consider using `is_ok()`
--> $DIR/redundant_pattern_matching.rs:183:15
|
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`

error: redundant pattern matching, consider using `is_err()`
--> $DIR/redundant_pattern_matching.rs:185:15
|
LL | while let Err(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`

error: redundant pattern matching, consider using `is_ok()`
--> $DIR/redundant_pattern_matching.rs:187:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => true,
LL | | Err(_) => false,
LL | | };
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`

error: redundant pattern matching, consider using `is_err()`
--> $DIR/redundant_pattern_matching.rs:192:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => false,
LL | | Err(_) => true,
LL | | };
| |_____^ help: try this: `Err::<i32, i32>(42).is_err()`

error: aborting due to 35 previous errors

This file was deleted.

Loading