use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::PredicateOrigin;
use rustc_index::vec::{Idx, IndexVec};
use rustc_session::utils::NtToTokenstream;
use rustc_session::Session;
let mut predicates = SmallVec::new();
predicates.extend(generics.params.iter().filter_map(|param| {
let bounds = self.lower_param_bounds(¶m.bounds, itctx.reborrow());
- self.lower_generic_bound_predicate(param.ident, param.id, ¶m.kind, bounds)
+ self.lower_generic_bound_predicate(
+ param.ident,
+ param.id,
+ ¶m.kind,
+ bounds,
+ PredicateOrigin::GenericParam,
+ )
}));
predicates.extend(
generics
id: NodeId,
kind: &GenericParamKind,
bounds: &'hir [hir::GenericBound<'hir>],
+ origin: PredicateOrigin,
) -> Option<hir::WherePredicate<'hir>> {
// Do not create a clause if we do not have anything inside it.
if bounds.is_empty() {
bounds,
span,
bound_generic_params: &[],
- in_where_clause: false,
+ origin,
}))
}
GenericParamKind::Lifetime => {
)
})),
span: self.lower_span(span),
- in_where_clause: true,
+ origin: PredicateOrigin::WhereClause,
}),
WherePredicate::RegionPredicate(WhereRegionPredicate {
ref lifetime,
def_node_id,
&GenericParamKind::Type { default: None },
hir_bounds,
+ hir::PredicateOrigin::ImplTrait,
) {
in_band_ty_bounds.push(preds)
}
pub fn in_where_clause(&self) -> bool {
match self {
- WherePredicate::BoundPredicate(p) => p.in_where_clause,
+ WherePredicate::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause,
WherePredicate::RegionPredicate(p) => p.in_where_clause,
WherePredicate::EqPredicate(_) => false,
}
}
}
+#[derive(Debug, HashStable_Generic, PartialEq, Eq)]
+pub enum PredicateOrigin {
+ WhereClause,
+ GenericParam,
+ ImplTrait,
+}
+
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
#[derive(Debug, HashStable_Generic)]
pub struct WhereBoundPredicate<'hir> {
pub span: Span,
- pub in_where_clause: bool,
+ /// Origin of the predicate.
+ pub origin: PredicateOrigin,
/// Any generics from a `for` binding.
pub bound_generic_params: &'hir [GenericParam<'hir>],
/// The type being bounded.
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
-use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind};
+use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind, PredicateOrigin};
use rustc_index::vec::Idx;
use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
Self::lifetimes_outliving_type(inferred_outlives, index),
&predicate.bounds,
predicate.span,
- predicate.in_where_clause,
+ predicate.origin == PredicateOrigin::WhereClause,
)
}
_ => {
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::PredicateOrigin;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder;
let bounds = if let Some(generics) = generics {
generics
.bounds_for_param(did)
- .filter(|bp| !bp.in_where_clause)
+ .filter(|bp| bp.origin != PredicateOrigin::WhereClause)
.flat_map(|bp| bp.bounds)
.filter_map(|x| x.clean(cx))
.collect()
LintId::of(strings::STRING_LIT_AS_BYTES),
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY),
- LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
- LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
LintId::of(transmute::USELESS_TRANSMUTE),
LintId::of(use_self::USE_SELF),
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
LintId::of(strings::STRING_ADD_ASSIGN),
+ LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
+ LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
LintId::of(types::LINKEDLIST),
LintId::of(types::OPTION_OPTION),
use rustc_hir::FnRetTy::Return;
use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
- ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier,
- TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+ ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin,
+ TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
.filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
for typ in types {
for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
- if pred.in_where_clause {
+ if pred.origin == PredicateOrigin::WhereClause {
// has_where_lifetimes checked that this predicate contains no lifetime.
continue;
}
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{
- GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, QPath, TraitItem, Ty, TyKind, WherePredicate,
+ GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, TraitItem, Ty, TyKind,
+ WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
/// ```
#[clippy::version = "1.38.0"]
pub TYPE_REPETITION_IN_BOUNDS,
- nursery,
+ pedantic,
"Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
}
/// ```
#[clippy::version = "1.47.0"]
pub TRAIT_DUPLICATION_IN_BOUNDS,
- nursery,
+ pedantic,
"Check if the same trait bounds are specified twice during a function declaration"
}
for predicate in item.generics.predicates {
if_chain! {
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
+ if bound_predicate.origin != PredicateOrigin::ImplTrait;
if !bound_predicate.span.from_expansion();
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
if let Some(PathSegment {
for bound in gen.predicates {
if_chain! {
if let WherePredicate::BoundPredicate(ref p) = bound;
+ if p.origin != PredicateOrigin::ImplTrait;
if p.bounds.len() as u64 <= self.max_trait_bounds;
if !p.span.from_expansion();
if let Some(ref v) = map.insert(
for predicate in gen.predicates {
if_chain! {
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
+ if bound_predicate.origin != PredicateOrigin::ImplTrait;
if !bound_predicate.span.from_expansion();
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
if let Some(segment) = segments.first();
|
= help: consider removing this trait bound
-error: this trait bound is already specified in the where clause
- --> $DIR/trait_duplication_in_bounds.rs:99:23
- |
-LL | fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
- | ^^^^^^^^^^
- |
- = help: consider removing this trait bound
-
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
|
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
-error: this type has already been used as a bound predicate
- --> $DIR/type_repetition_in_bounds.rs:83:43
- |
-LL | fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
- | ^^^^^^^^^^
- |
- = help: consider combining the bounds: `impl AsRef<str>: AsRef<str> + AsRef<str>`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors