]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #96770 - flip1995:fix-trait-type-in-bounds, r=cjgillot
authorbors <bors@rust-lang.org>
Sun, 8 May 2022 14:10:12 +0000 (14:10 +0000)
committerbors <bors@rust-lang.org>
Sun, 8 May 2022 14:10:12 +0000 (14:10 +0000)
Track if a where bound comes from a impl Trait desugar

With https://github.com/rust-lang/rust/pull/93803 `impl Trait` function arguments get desugared to hidden where bounds. However, Clippy needs to know if a bound was originally a `impl Trait` or an actual bound. This adds a field to the `WhereBoundPredicate` struct to keep track of this information during AST->HIR lowering.

r? `@cjgillot`

cc `@estebank` (as the reviewer of #93803)

compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_lint/src/builtin.rs
src/librustdoc/clean/mod.rs
src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
src/tools/clippy/clippy_lints/src/lifetimes.rs
src/tools/clippy/clippy_lints/src/trait_bounds.rs
src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr

index 5a95e5b084ad42b8ab9daf89c70527bde997dbae..cf97b270ed8f9779fb7d3c001b6ef3d5b0197abe 100644 (file)
@@ -11,6 +11,7 @@
 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;
@@ -1346,7 +1347,13 @@ pub(super) fn lower_generics_mut(
         let mut predicates = SmallVec::new();
         predicates.extend(generics.params.iter().filter_map(|param| {
             let bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
-            self.lower_generic_bound_predicate(param.ident, param.id, &param.kind, bounds)
+            self.lower_generic_bound_predicate(
+                param.ident,
+                param.id,
+                &param.kind,
+                bounds,
+                PredicateOrigin::GenericParam,
+            )
         }));
         predicates.extend(
             generics
@@ -1380,6 +1387,7 @@ pub(super) fn lower_generic_bound_predicate(
         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() {
@@ -1419,7 +1427,7 @@ pub(super) fn lower_generic_bound_predicate(
                     bounds,
                     span,
                     bound_generic_params: &[],
-                    in_where_clause: false,
+                    origin,
                 }))
             }
             GenericParamKind::Lifetime => {
@@ -1458,7 +1466,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                     )
                 })),
                 span: self.lower_span(span),
-                in_where_clause: true,
+                origin: PredicateOrigin::WhereClause,
             }),
             WherePredicate::RegionPredicate(WhereRegionPredicate {
                 ref lifetime,
index 54b081085cdd7b497d5868d8a471dc2990586f73..c143266f6c1de7921a52101ee312e2a243f041db 100644 (file)
@@ -1298,6 +1298,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                             def_node_id,
                             &GenericParamKind::Type { default: None },
                             hir_bounds,
+                            hir::PredicateOrigin::ImplTrait,
                         ) {
                             in_band_ty_bounds.push(preds)
                         }
index 2f379b85b92c7bbb1d6043d9f878b49808e1c94f..4d4d4a28499af439e1a881202a6b305a2a1f4993 100644 (file)
@@ -706,7 +706,7 @@ pub fn span(&self) -> Span {
 
     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,
         }
@@ -721,11 +721,19 @@ pub fn bounds(&self) -> GenericBounds<'hir> {
     }
 }
 
+#[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.
index 3564f15e210ad74efa7a99aa7dcf71fcbca60719..524fb6556b99546c5e3b8595c69e0fb88eec284f 100644 (file)
@@ -36,7 +36,7 @@
 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};
@@ -2226,7 +2226,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
                                     Self::lifetimes_outliving_type(inferred_outlives, index),
                                     &predicate.bounds,
                                     predicate.span,
-                                    predicate.in_where_clause,
+                                    predicate.origin == PredicateOrigin::WhereClause,
                                 )
                             }
                             _ => {
index eea4eef90654796db86af4b8fc1bc8e741ffdff5..7cc96183d6da48cb4eb6bc41b946023b29a66133 100644 (file)
@@ -16,6 +16,7 @@
 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;
@@ -493,7 +494,7 @@ fn clean_generic_param(
             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()
index d43c7e03533c72182092c58336a3509abdb806bf..34d1555049da58bbe21e562bec1cd0b3c123a9a6 100644 (file)
@@ -29,8 +29,6 @@
     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),
index 2ee2c6e3358cd030ffd32a1b8287fc379932e348..63232fd41130538765c6b4f547c8c9ba7e9d9ab8 100644 (file)
@@ -84,6 +84,8 @@
     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),
index ab5d3fa7b6d9c98b55a5c82c0a192e75f68dde13..51d5b510ab93053e155d1b6ec3cbb0ade5ceb101 100644 (file)
@@ -9,8 +9,8 @@
 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;
@@ -145,7 +145,7 @@ fn check_fn_inner<'tcx>(
         .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;
             }
index 78e388a49af1d470291e93a36958e66e6c2c6572..911da3997ae451160af7106915e89e3a1243c093 100644 (file)
@@ -8,7 +8,8 @@
 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};
@@ -35,7 +36,7 @@
     /// ```
     #[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: _`"
 }
 
@@ -65,7 +66,7 @@
     /// ```
     #[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"
 }
 
@@ -95,6 +96,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tc
         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 {
@@ -168,6 +170,7 @@ impl Eq for SpanlessTy<'_, '_> {}
         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(
@@ -223,6 +226,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
     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();
index d0a4cfb88370e2060620137f7e015632a96ff3e7..6f8c8e47dfbf1fe56589a06f80017513e69167e8 100644 (file)
@@ -67,13 +67,5 @@ LL |         Self: Iterator<Item = Foo>,
    |
    = 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
 
index abc25e59496bfa13262c3a5b938ce282a7b25edb..148c19c7d0701dc2910de718d175a03122d26e03 100644 (file)
@@ -19,13 +19,5 @@ LL |     Self: Copy + Default + Ord,
    |
    = 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