Auto merge of #76136 - CDirkx:const-result, r=dtolnay

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: #67520).
I believe these methods to be eligible for stabilization because of the stabilization of #49146 (Allow if and match in constants) and the trivial implementations, see also: [PR#75463](https://github.com/rust-lang/rust/pull/75463) and [PR#76135](https://github.com/rust-lang/rust/pull/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: #76225
This commit is contained in:
bors 2020-09-20 13:07:11 +00:00
commit b873fa6d42
10 changed files with 116 additions and 191 deletions

View File

@ -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)]

View File

@ -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 {
@ -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 {
@ -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 {

View File

@ -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)
}

View File

@ -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") {
@ -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

View File

@ -77,6 +77,7 @@ fn main() {
issue5504();
issue5697();
issue6067();
let _ = if gen_opt().is_some() {
1
@ -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,
@ -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();
}

View File

@ -98,6 +98,7 @@ fn main() {
issue5504();
issue5697();
issue6067();
let _ = if let Some(_) = gen_opt() {
1
@ -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,
@ -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,
};
}

View File

@ -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

View File

@ -1,44 +0,0 @@
// run-rustfix
#![feature(const_result)]
#![warn(clippy::redundant_pattern_matching)]
#![allow(clippy::match_like_matches_macro, unused)]
// Test that results are linted with the feature enabled.
const fn issue_5697() {
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();
// These should not be linted until `const_option` is implemented.
// See https://github.com/rust-lang/rust/issues/67441
if let Some(_) = Some(42) {}
if let None = None::<()> {}
while let Some(_) = Some(42) {}
while let None = None::<()> {}
match Some(42) {
Some(_) => true,
None => false,
};
match None::<()> {
Some(_) => false,
None => true,
};
}
fn main() {}

View File

@ -1,50 +0,0 @@
// run-rustfix
#![feature(const_result)]
#![warn(clippy::redundant_pattern_matching)]
#![allow(clippy::match_like_matches_macro, unused)]
// Test that results are linted with the feature enabled.
const fn issue_5697() {
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,
};
// These should not be linted until `const_option` is implemented.
// See https://github.com/rust-lang/rust/issues/67441
if let Some(_) = Some(42) {}
if let None = None::<()> {}
while let Some(_) = Some(42) {}
while let None = None::<()> {}
match Some(42) {
Some(_) => true,
None => false,
};
match None::<()> {
Some(_) => false,
None => true,
};
}
fn main() {}

View File

@ -1,46 +0,0 @@
error: redundant pattern matching, consider using `is_ok()`
--> $DIR/redundant_pattern_matching_const_result.rs:10:12
|
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
|
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_err()`
--> $DIR/redundant_pattern_matching_const_result.rs:12: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_const_result.rs:14: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_const_result.rs:16: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_const_result.rs:18: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_const_result.rs:23: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 6 previous errors