Skip to content

Commit

Permalink
Auto merge of rust-lang#76136 - CDirkx:const-result, r=dtolnay
Browse files Browse the repository at this point in the history
Stabilize some Result methods as const

Stabilize the following methods of Result as const:
 - `is_ok`
 - `is_err`
 - `as_ref`

A test is also included, analogous to the test for `const_option`.

These methods are currently const under the unstable feature `const_result` (tracking issue: rust-lang#67520).
I believe these methods to be eligible for stabilization because of the stabilization of rust-lang#49146 (Allow if and match in constants) and the trivial implementations, see also: [PR#75463](rust-lang#75463) and [PR#76135](rust-lang#76135).

Note: these methods are the only methods currently under the `const_result` feature, thus this PR results in the removal of the feature.

Related: rust-lang#76225
  • Loading branch information
bors committed Sep 20, 2020
2 parents 41507ed + bf70e21 commit b873fa6
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 191 deletions.
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 @@ -304,3 +304,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

0 comments on commit b873fa6

Please sign in to comment.