}
}
+pub trait NextTypeParamName {
+ fn next_type_param_name(&self) -> &'static str;
+}
+
+impl NextTypeParamName for &[GenericParam<'_>] {
+ fn next_type_param_name(&self) -> &'static str {
+ // This is the whitelist of possible parameter names that we might suggest.
+ let possible_names = ["T", "U", "V", "X", "Y", "Z", "A", "B", "C", "D", "E", "F", "G"];
+ let used_names = self
+ .iter()
+ .filter_map(|p| match p.name {
+ ParamName::Plain(ident) => Some(ident.name),
+ _ => None,
+ })
+ .collect::<Vec<_>>();
+
+ possible_names
+ .iter()
+ .find(|n| !used_names.contains(&Symbol::intern(n)))
+ .unwrap_or(&"ParamName")
+ }
+}
+
#[derive(Default)]
pub struct GenericParamCount {
pub lifetimes: usize,
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
-use rustc_hir::Node;
+use rustc_hir::{NextTypeParamName, Node};
use rustc_middle::ty::TypeckTables;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
}
}
+ let type_param_name = generics.params.next_type_param_name();
// The type param `T: Trait` we will suggest to introduce.
- let type_param = format!("{}: {}", "T", name);
+ let type_param = format!("{}: {}", type_param_name, name);
// FIXME: modify the `trait_ref` instead of string shenanigans.
// Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
let pred = trait_ref.without_const().to_predicate().to_string();
- let pred = pred.replace(&impl_name, "T");
+ let pred = pred.replace(&impl_name, type_param_name);
let mut sugg = vec![
match generics
.params
// ^ suggest `where <T as Trait>::A: Bound`
predicate_constraint(generics, pred),
];
- sugg.extend(ty_spans.into_iter().map(|s| (s, "T".to_string())));
+ sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string())));
// Suggest `fn foo<T: Trait>(t: T) where <T as Trait>::A: Bound`.
err.multipart_suggestion(
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::weak_lang_items;
-use rustc_hir::{GenericParamKind, Node, Unsafety};
+use rustc_hir::{GenericParamKind, NextTypeParamName, Node, Unsafety};
use rustc_middle::hir::map::blocks::FnLikeNode;
use rustc_middle::hir::map::Map;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
if placeholder_types.is_empty() {
return;
}
- // This is the whitelist of possible parameter names that we might suggest.
- let possible_names = ["T", "K", "L", "A", "B", "C"];
- let used_names = generics
- .iter()
- .filter_map(|p| match p.name {
- hir::ParamName::Plain(ident) => Some(ident.name),
- _ => None,
- })
- .collect::<Vec<_>>();
-
- let type_name = possible_names
- .iter()
- .find(|n| !used_names.contains(&Symbol::intern(n)))
- .unwrap_or(&"ParamName");
+ let type_name = generics.next_type_param_name();
let mut sugg: Vec<_> =
placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
}
}
-fn bat<T: std::fmt::Debug>(t: T, constraints: impl Iterator) {
+fn bat<K, T: std::fmt::Debug>(t: T, constraints: impl Iterator, _: K) {
for constraint in constraints {
qux(t);
qux(constraint);
}
}
+fn bak(constraints: impl Iterator + std::fmt::Debug) {
+ for constraint in constraints {
+ qux(constraint);
+//~^ ERROR `<impl Iterator + std::fmt::Debug as std::iter::Iterator>::Item` doesn't implement
+ }
+}
+
fn qux(_: impl std::fmt::Debug) {}
fn main() {}
= help: the trait `std::fmt::Debug` is not implemented for `<impl Iterator as std::iter::Iterator>::Item`
help: introduce a type parameter with a trait bound instead of using `impl Trait`
|
-LL | fn bar<T, T: Iterator>(t: T, constraints: T) where T: std::fmt::Debug, <T as std::iter::Iterator>::Item: std::fmt::Debug {
+LL | fn bar<T, U: Iterator>(t: T, constraints: U) where T: std::fmt::Debug, <U as std::iter::Iterator>::Item: std::fmt::Debug {
| ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: `<impl Iterator as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug`
= help: the trait `std::fmt::Debug` is not implemented for `<impl Iterator as std::iter::Iterator>::Item`
help: introduce a type parameter with a trait bound instead of using `impl Trait`
|
-LL | fn bat<T: std::fmt::Debug, T: Iterator>(t: T, constraints: T) where <T as std::iter::Iterator>::Item: std::fmt::Debug {
- | ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn bat<K, T: std::fmt::Debug, U: Iterator>(t: T, constraints: U, _: K) where <U as std::iter::Iterator>::Item: std::fmt::Debug {
+ | ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 4 previous errors
+error[E0277]: `<impl Iterator + std::fmt::Debug as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug`
+ --> $DIR/impl-trait-with-missing-bounds.rs:37:13
+ |
+LL | qux(constraint);
+ | ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as std::iter::Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+...
+LL | fn qux(_: impl std::fmt::Debug) {}
+ | --- --------------- required by this bound in `qux`
+ |
+ = help: the trait `std::fmt::Debug` is not implemented for `<impl Iterator + std::fmt::Debug as std::iter::Iterator>::Item`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+ |
+LL | fn bak<T: Iterator + std::fmt::Debug>(constraints: T) where <T as std::iter::Iterator>::Item: std::fmt::Debug {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.
|
help: use type parameters instead
|
-LL | fn test6_b<T, K>(_: K, _: T) { }
+LL | fn test6_b<T, U>(_: U, _: T) { }
| ^^^ ^
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
|
help: use type parameters instead
|
-LL | fn test6_c<T, K, L, A, B, C>(_: C, _: (T, K, L, A, B)) { }
+LL | fn test6_c<T, K, L, A, B, U>(_: U, _: (T, K, L, A, B)) { }
| ^^^ ^
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
|
help: use type parameters instead
|
-LL | struct BadStruct2<K, T>(K, T);
+LL | struct BadStruct2<U, T>(U, T);
| ^ ^
error[E0121]: the type placeholder `_` is not allowed within types on item signatures