about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/default_constructed_unit_structs.rs15
-rw-r--r--clippy_utils/src/lib.rs2
-rw-r--r--tests/ui/default_constructed_unit_structs.fixed22
-rw-r--r--tests/ui/default_constructed_unit_structs.rs22
-rw-r--r--tests/ui/default_constructed_unit_structs.stderr8
5 files changed, 62 insertions, 7 deletions
diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs
index 9bd7a0dc0f3..fb037bbcbf3 100644
--- a/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,4 +1,4 @@
-use clippy_utils::{diagnostics::span_lint_and_sugg, match_def_path, paths};
+use clippy_utils::{diagnostics::span_lint_and_sugg, is_ty_alias, match_def_path, paths};
 use hir::{def::Res, ExprKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -43,12 +43,23 @@ declare_clippy_lint! {
 }
 declare_lint_pass!(DefaultConstructedUnitStructs => [DEFAULT_CONSTRUCTED_UNIT_STRUCTS]);
 
+fn is_alias(ty: hir::Ty<'_>) -> bool {
+    if let hir::TyKind::Path(ref qpath) = ty.kind {
+        is_ty_alias(qpath)
+    } else {
+        false
+    }
+}
+
 impl LateLintPass<'_> for DefaultConstructedUnitStructs {
     fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         if_chain!(
             // make sure we have a call to `Default::default`
             if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind;
-            if let ExprKind::Path(ref qpath@ hir::QPath::TypeRelative(_,_)) = fn_expr.kind;
+            if let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind;
+            // make sure this isn't a type alias:
+            // `<Foo as Bar>::Assoc` cannot be used as a constructor
+            if !is_alias(*base);
             if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
             if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
             // make sure we have a struct with no fields (unit struct)
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 575c29a6b6f..8c883445a79 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -287,7 +287,7 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
 /// Checks if the given `QPath` belongs to a type alias.
 pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
     match *qpath {
-        QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias, ..)),
+        QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias | DefKind::AssocTy, ..)),
         QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) },
         _ => false,
     }
diff --git a/tests/ui/default_constructed_unit_structs.fixed b/tests/ui/default_constructed_unit_structs.fixed
index e1012f38bba..ac5fe38ff44 100644
--- a/tests/ui/default_constructed_unit_structs.fixed
+++ b/tests/ui/default_constructed_unit_structs.fixed
@@ -101,6 +101,28 @@ struct EmptyStruct {}
 #[non_exhaustive]
 struct NonExhaustiveStruct;
 
+mod issue_10755 {
+    struct Sqlite {}
+
+    trait HasArguments<'q> {
+        type Arguments;
+    }
+
+    impl<'q> HasArguments<'q> for Sqlite {
+        type Arguments = std::marker::PhantomData<&'q ()>;
+    }
+
+    type SqliteArguments<'q> = <Sqlite as HasArguments<'q>>::Arguments;
+
+    fn foo() {
+        // should not lint
+        // type alias cannot be used as a constructor
+        let _ = <Sqlite as HasArguments>::Arguments::default();
+
+        let _ = SqliteArguments::default();
+    }
+}
+
 fn main() {
     // should lint
     let _ = PhantomData::<usize>;
diff --git a/tests/ui/default_constructed_unit_structs.rs b/tests/ui/default_constructed_unit_structs.rs
index c7b4313dbf0..de7f14ffbd9 100644
--- a/tests/ui/default_constructed_unit_structs.rs
+++ b/tests/ui/default_constructed_unit_structs.rs
@@ -101,6 +101,28 @@ struct EmptyStruct {}
 #[non_exhaustive]
 struct NonExhaustiveStruct;
 
+mod issue_10755 {
+    struct Sqlite {}
+
+    trait HasArguments<'q> {
+        type Arguments;
+    }
+
+    impl<'q> HasArguments<'q> for Sqlite {
+        type Arguments = std::marker::PhantomData<&'q ()>;
+    }
+
+    type SqliteArguments<'q> = <Sqlite as HasArguments<'q>>::Arguments;
+
+    fn foo() {
+        // should not lint
+        // type alias cannot be used as a constructor
+        let _ = <Sqlite as HasArguments>::Arguments::default();
+
+        let _ = SqliteArguments::default();
+    }
+}
+
 fn main() {
     // should lint
     let _ = PhantomData::<usize>::default();
diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr
index 61a32fb10e5..13abb9149da 100644
--- a/tests/ui/default_constructed_unit_structs.stderr
+++ b/tests/ui/default_constructed_unit_structs.stderr
@@ -13,25 +13,25 @@ LL |             inner: PhantomData::default(),
    |                               ^^^^^^^^^^^ help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> $DIR/default_constructed_unit_structs.rs:106:33
+  --> $DIR/default_constructed_unit_structs.rs:128:33
    |
 LL |     let _ = PhantomData::<usize>::default();
    |                                 ^^^^^^^^^^^ help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> $DIR/default_constructed_unit_structs.rs:107:42
+  --> $DIR/default_constructed_unit_structs.rs:129:42
    |
 LL |     let _: PhantomData<i32> = PhantomData::default();
    |                                          ^^^^^^^^^^^ help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> $DIR/default_constructed_unit_structs.rs:108:55
+  --> $DIR/default_constructed_unit_structs.rs:130:55
    |
 LL |     let _: PhantomData<i32> = std::marker::PhantomData::default();
    |                                                       ^^^^^^^^^^^ help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> $DIR/default_constructed_unit_structs.rs:109:23
+  --> $DIR/default_constructed_unit_structs.rs:131:23
    |
 LL |     let _ = UnitStruct::default();
    |                       ^^^^^^^^^^^ help: remove this call to `default`