mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 23:22:58 +00:00
Rollup merge of #82194 - estebank:arbitrary-bounds-suggestion, r=petrochenkov
In some limited cases, suggest `where` bounds for non-type params Partially address #81971.
This commit is contained in:
commit
f01b339dae
@ -75,6 +75,36 @@ impl<'tcx> TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn suggest_arbitrary_trait_bound(
|
||||||
|
generics: &hir::Generics<'_>,
|
||||||
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
param_name: &str,
|
||||||
|
constraint: &str,
|
||||||
|
) -> bool {
|
||||||
|
let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
|
||||||
|
match (param, param_name) {
|
||||||
|
(Some(_), "Self") => return false,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
// Suggest a where clause bound for a non-type paremeter.
|
||||||
|
let (action, prefix) = if generics.where_clause.predicates.is_empty() {
|
||||||
|
("introducing a", " where ")
|
||||||
|
} else {
|
||||||
|
("extending the", ", ")
|
||||||
|
};
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
generics.where_clause.tail_span_for_suggestion(),
|
||||||
|
&format!(
|
||||||
|
"consider {} `where` bound, but there might be an alternative better way to express \
|
||||||
|
this requirement",
|
||||||
|
action,
|
||||||
|
),
|
||||||
|
format!("{}{}: {}", prefix, param_name, constraint),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Suggest restricting a type param with a new bound.
|
/// Suggest restricting a type param with a new bound.
|
||||||
pub fn suggest_constraining_type_param(
|
pub fn suggest_constraining_type_param(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
|
@ -17,8 +17,8 @@ use rustc_hir::intravisit::Visitor;
|
|||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
|
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty,
|
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
|
||||||
TyCtxt, TypeFoldable, WithConstness,
|
Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{TypeAndMut, TypeckResults};
|
use rustc_middle::ty::{TypeAndMut, TypeckResults};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
@ -334,7 +334,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
let (param_ty, projection) = match self_ty.kind() {
|
let (param_ty, projection) = match self_ty.kind() {
|
||||||
ty::Param(_) => (true, None),
|
ty::Param(_) => (true, None),
|
||||||
ty::Projection(projection) => (false, Some(projection)),
|
ty::Projection(projection) => (false, Some(projection)),
|
||||||
_ => return,
|
_ => (false, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
|
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
|
||||||
@ -453,6 +453,26 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hir::Node::Item(hir::Item {
|
||||||
|
kind:
|
||||||
|
hir::ItemKind::Struct(_, generics)
|
||||||
|
| hir::ItemKind::Enum(_, generics)
|
||||||
|
| hir::ItemKind::Union(_, generics)
|
||||||
|
| hir::ItemKind::Trait(_, _, generics, ..)
|
||||||
|
| hir::ItemKind::Impl(hir::Impl { generics, .. })
|
||||||
|
| hir::ItemKind::Fn(_, generics, _)
|
||||||
|
| hir::ItemKind::TyAlias(_, generics)
|
||||||
|
| hir::ItemKind::TraitAlias(generics, _)
|
||||||
|
| hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
|
||||||
|
..
|
||||||
|
}) if !param_ty => {
|
||||||
|
// Missing generic type parameter bound.
|
||||||
|
let param_name = self_ty.to_string();
|
||||||
|
let constraint = trait_ref.print_only_trait_path().to_string();
|
||||||
|
if suggest_arbitrary_trait_bound(generics, &mut err, ¶m_name, &constraint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
hir::Node::Crate(..) => return,
|
hir::Node::Crate(..) => return,
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -5,6 +5,10 @@ LL | a == b;
|
|||||||
| ^^ no implementation for `&T == T`
|
| ^^ no implementation for `&T == T`
|
||||||
|
|
|
|
||||||
= help: the trait `PartialEq<T>` is not implemented for `&T`
|
= help: the trait `PartialEq<T>` is not implemented for `&T`
|
||||||
|
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
||||||
|
|
|
||||||
|
LL | fn foo<T: PartialEq>(a: &T, b: T) where &T: PartialEq<T> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@ LL | default type U = &'static B;
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
|
||||||
|
|
|
|
||||||
= help: the trait `PartialEq<B>` is not implemented for `&'static B`
|
= help: the trait `PartialEq<B>` is not implemented for `&'static B`
|
||||||
|
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
||||||
|
|
|
||||||
|
LL | impl<B: 'static, T> X<B> for T where &'static B: PartialEq<B> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::io::{BufRead, BufReader, Read, Write};
|
use std::io::{BufRead, BufReader, Read, Write};
|
||||||
|
|
||||||
fn issue_81421<T: Read + Write>(mut stream: T) {
|
fn issue_81421<T: Read + Write>(mut stream: T) { //~ HELP consider introducing a `where` bound
|
||||||
let initial_message = format!("Hello world");
|
let initial_message = format!("Hello world");
|
||||||
let mut buffer: Vec<u8> = Vec::new();
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
let bytes_written = stream.write_all(initial_message.as_bytes());
|
let bytes_written = stream.write_all(initial_message.as_bytes());
|
||||||
|
@ -9,6 +9,10 @@ help: consider removing the leading `&`-reference
|
|||||||
|
|
|
|
||||||
LL | let mut stream_reader = BufReader::new(stream);
|
LL | let mut stream_reader = BufReader::new(stream);
|
||||||
| --
|
| --
|
||||||
|
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
||||||
|
|
|
||||||
|
LL | fn issue_81421<T: Read + Write>(mut stream: T) where &T: std::io::Read {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider changing this borrow's mutability
|
help: consider changing this borrow's mutability
|
||||||
|
|
|
|
||||||
LL | let mut stream_reader = BufReader::new(&mut stream);
|
LL | let mut stream_reader = BufReader::new(&mut stream);
|
||||||
|
@ -35,6 +35,10 @@ LL | <u64 as From<T>>::from;
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64`
|
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64`
|
||||||
|
|
|
|
||||||
= note: required by `from`
|
= note: required by `from`
|
||||||
|
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
||||||
|
|
|
||||||
|
LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied
|
error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied
|
||||||
--> $DIR/suggest-where-clause.rs:18:5
|
--> $DIR/suggest-where-clause.rs:18:5
|
||||||
@ -43,6 +47,10 @@ LL | <u64 as From<<T as Iterator>::Item>>::from;
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64`
|
||||||
|
|
|
|
||||||
= note: required by `from`
|
= note: required by `from`
|
||||||
|
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
||||||
|
|
|
||||||
|
LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied
|
error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied
|
||||||
--> $DIR/suggest-where-clause.rs:23:5
|
--> $DIR/suggest-where-clause.rs:23:5
|
||||||
|
Loading…
Reference in New Issue
Block a user