mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-01 02:14:20 +00:00
Don't suggest restricting bound with unstable traits on stable
On nightly, we mention the trait is unstable ``` error[E0277]: the trait bound `T: Unstable` is not satisfied --> $DIR/unstable-trait-suggestion.rs:13:9 | LL | foo(t) | --- ^ the trait `Unstable` is not implemented for `T` | | | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/unstable-trait-suggestion.rs:9:11 | LL | fn foo<T: Unstable>(_: T) {} | ^^^^^^^^ required by this bound in `foo` help: consider restricting type parameter `T` but it is an `unstable` trait | LL | pub fn demo<T: Unstable>(t: T) { | ++++++++++ ``` On stable, we don't suggest the trait at all ``` error[E0277]: the trait bound `T: Unstable` is not satisfied --> $DIR/unstable-trait-suggestion.rs:13:9 | LL | foo(t) | --- ^ the trait `Unstable` is not implemented for `T` | | | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/unstable-trait-suggestion.rs:9:11 | LL | fn foo<T: Unstable>(_: T) {} | ^^^^^^^^ required by this bound in `foo` ```
This commit is contained in:
parent
9c707a8b76
commit
68253e14ee
@ -1,6 +1,5 @@
|
||||
//! Diagnostics related methods for `Ty`.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
@ -278,8 +277,21 @@ pub fn suggest_constraining_type_params<'a>(
|
||||
span_to_replace: Option<Span>,
|
||||
) -> bool {
|
||||
let mut grouped = FxHashMap::default();
|
||||
let mut unstable_suggestion = false;
|
||||
param_names_and_constraints.for_each(|(param_name, constraint, def_id)| {
|
||||
grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id))
|
||||
let stable = match def_id {
|
||||
Some(def_id) => match tcx.lookup_stability(def_id) {
|
||||
Some(s) => s.level.is_stable(),
|
||||
None => true,
|
||||
},
|
||||
None => true,
|
||||
};
|
||||
if stable || tcx.sess.is_nightly_build() {
|
||||
grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id));
|
||||
if !stable {
|
||||
unstable_suggestion = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
@ -464,28 +476,32 @@ pub fn suggest_constraining_type_params<'a>(
|
||||
|
||||
if suggestions.len() == 1 {
|
||||
let (span, suggestion, msg) = suggestions.pop().unwrap();
|
||||
let post = if unstable_suggestion { " but it is an `unstable` trait" } else { "" };
|
||||
let msg = match msg {
|
||||
SuggestChangingConstraintsMessage::RestrictBoundFurther => {
|
||||
Cow::from("consider further restricting this bound")
|
||||
format!("consider further restricting this bound{post}")
|
||||
}
|
||||
SuggestChangingConstraintsMessage::RestrictType { ty } => {
|
||||
Cow::from(format!("consider restricting type parameter `{ty}`"))
|
||||
format!("consider restricting type parameter `{ty}`{post}")
|
||||
}
|
||||
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
|
||||
Cow::from(format!("consider further restricting type parameter `{ty}`"))
|
||||
format!("consider further restricting type parameter `{ty}`{post}")
|
||||
}
|
||||
SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
|
||||
Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
|
||||
format!(
|
||||
"consider removing the `?Sized` bound to make the type parameter `Sized`{post}"
|
||||
)
|
||||
}
|
||||
SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => {
|
||||
Cow::from("consider replacing `?Sized` with `Sized`")
|
||||
format!("consider replacing `?Sized` with `Sized`{post}")
|
||||
}
|
||||
};
|
||||
|
||||
err.span_suggestion_verbose(span, msg, suggestion, applicability);
|
||||
} else if suggestions.len() > 1 {
|
||||
let post = if unstable_suggestion { " but some of them are `unstable` traits" } else { "" };
|
||||
err.multipart_suggestion_verbose(
|
||||
"consider restricting type parameters",
|
||||
format!("consider restricting type parameters{post}"),
|
||||
suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(),
|
||||
applicability,
|
||||
);
|
||||
|
@ -6,7 +6,7 @@ LL | impl<A, B> FnOnce<A> for CachedFun<A, B>
|
||||
|
|
||||
note: required by a bound in `FnOnce`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
help: consider further restricting this bound
|
||||
help: consider further restricting this bound but it is an `unstable` trait
|
||||
|
|
||||
LL | A: Eq + Hash + Clone + std::marker::Tuple,
|
||||
| ++++++++++++++++++++
|
||||
@ -19,7 +19,7 @@ LL | impl<A, B> FnMut<A> for CachedFun<A, B>
|
||||
|
|
||||
note: required by a bound in `FnMut`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
help: consider further restricting this bound
|
||||
help: consider further restricting this bound but it is an `unstable` trait
|
||||
|
|
||||
LL | A: Eq + Hash + Clone + std::marker::Tuple,
|
||||
| ++++++++++++++++++++
|
||||
@ -30,7 +30,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
|
||||
LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
|
||||
|
|
||||
help: consider further restricting this bound
|
||||
help: consider further restricting this bound but it is an `unstable` trait
|
||||
|
|
||||
LL | A: Eq + Hash + Clone + std::marker::Tuple,
|
||||
| ++++++++++++++++++++
|
||||
@ -41,7 +41,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup
|
||||
LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
|
||||
|
|
||||
help: consider further restricting this bound
|
||||
help: consider further restricting this bound but it is an `unstable` trait
|
||||
|
|
||||
LL | A: Eq + Hash + Clone + std::marker::Tuple,
|
||||
| ++++++++++++++++++++
|
||||
@ -56,7 +56,7 @@ LL | self.call_mut(a)
|
||||
|
|
||||
note: required by a bound in `call_mut`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
help: consider further restricting this bound
|
||||
help: consider further restricting this bound but it is an `unstable` trait
|
||||
|
|
||||
LL | A: Eq + Hash + Clone + std::marker::Tuple,
|
||||
| ++++++++++++++++++++
|
||||
|
@ -10,7 +10,7 @@ note: required by a bound in `CastTo`
|
||||
|
|
||||
LL | pub trait CastTo<U: ?Sized>: Unsize<U> {}
|
||||
| ^^^^^^^^^ required by this bound in `CastTo`
|
||||
help: consider further restricting this bound
|
||||
help: consider further restricting this bound but it is an `unstable` trait
|
||||
|
|
||||
LL | impl<T: ?Sized + std::marker::Unsize<U>, U: ?Sized> CastTo<U> for T {}
|
||||
| ++++++++++++++++++++++++
|
||||
|
15
tests/ui/trait-bounds/unstable-trait-suggestion.rs
Normal file
15
tests/ui/trait-bounds/unstable-trait-suggestion.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#![feature(staged_api)]
|
||||
#![allow(internal_features)]
|
||||
#![stable(feature = "unit_test", since = "1.0.0")]
|
||||
|
||||
#[unstable(feature = "step_trait", issue = "42168")]
|
||||
pub trait Unstable {}
|
||||
|
||||
#[stable(feature = "unit_test", since = "1.0.0")]
|
||||
fn foo<T: Unstable>(_: T) {}
|
||||
|
||||
#[stable(feature = "unit_test", since = "1.0.0")]
|
||||
pub fn demo<T>(t: T) { //~ HELP consider restricting type parameter `T` but it is an `unstable` trait
|
||||
foo(t) //~ ERROR E0277
|
||||
}
|
||||
fn main() {}
|
21
tests/ui/trait-bounds/unstable-trait-suggestion.stderr
Normal file
21
tests/ui/trait-bounds/unstable-trait-suggestion.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0277]: the trait bound `T: Unstable` is not satisfied
|
||||
--> $DIR/unstable-trait-suggestion.rs:13:9
|
||||
|
|
||||
LL | foo(t)
|
||||
| --- ^ the trait `Unstable` is not implemented for `T`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/unstable-trait-suggestion.rs:9:11
|
||||
|
|
||||
LL | fn foo<T: Unstable>(_: T) {}
|
||||
| ^^^^^^^^ required by this bound in `foo`
|
||||
help: consider restricting type parameter `T` but it is an `unstable` trait
|
||||
|
|
||||
LL | pub fn demo<T: Unstable>(t: T) {
|
||||
| ++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -9,7 +9,7 @@ note: required by a bound in `assert_is_tuple`
|
||||
|
|
||||
LL | fn assert_is_tuple<T: std::marker::Tuple + ?Sized>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple`
|
||||
help: consider restricting type parameter `T`
|
||||
help: consider restricting type parameter `T` but it is an `unstable` trait
|
||||
|
|
||||
LL | fn from_param_env<T: std::marker::Tuple>() {
|
||||
| ++++++++++++++++++++
|
||||
|
Loading…
Reference in New Issue
Block a user