}
}
-pub trait NextTypeParamName {
- fn next_type_param_name(&self, name: Option<&str>) -> String;
-}
-
-impl NextTypeParamName for &[GenericParam<'_>] {
- fn next_type_param_name(&self, name: Option<&str>) -> String {
- // This is the whitelist of possible parameter names that we might suggest.
- let name = name.and_then(|n| n.chars().next()).map(|c| c.to_string().to_uppercase());
- let name = name.as_ref().map(|s| s.as_str());
- let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"];
- 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")
- .to_string()
- }
-}
-
#[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::{NextTypeParamName, Node};
+use rustc_hir::Node;
use rustc_middle::ty::TypeckTables;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
};
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{MultiSpan, Span, DUMMY_SP};
use std::fmt;
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`.
+ // FIXME: once `#![feature(associated_type_bounds)]` is stabilized, we should suggest
+ // `fn foo(t: impl Trait<A: Bound>)` instead.
err.multipart_suggestion(
"introduce a type parameter with a trait bound instead of using `impl Trait`",
sugg,
hir::intravisit::walk_body(self, body);
}
}
+
+pub trait NextTypeParamName {
+ fn next_type_param_name(&self, name: Option<&str>) -> String;
+}
+
+impl NextTypeParamName for &[hir::GenericParam<'_>] {
+ fn next_type_param_name(&self, name: Option<&str>) -> String {
+ // This is the whitelist of possible parameter names that we might suggest.
+ let name = name.and_then(|n| n.chars().next()).map(|c| c.to_string().to_uppercase());
+ let name = name.as_ref().map(|s| s.as_str());
+ let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"];
+ let used_names = self
+ .iter()
+ .filter_map(|p| match p.name {
+ hir::ParamName::Plain(ident) => Some(ident.name),
+ _ => None,
+ })
+ .collect::<Vec<_>>();
+
+ possible_names
+ .iter()
+ .find(|n| !used_names.contains(&Symbol::intern(n)))
+ .unwrap_or(&"ParamName")
+ .to_string()
+ }
+}
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, NextTypeParamName, Node, Unsafety};
+use rustc_hir::{GenericParamKind, Node, Unsafety};
use rustc_middle::hir::map::blocks::FnLikeNode;
use rustc_middle::hir::map::Map;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi;
+use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
mod type_of;