diff options
| author | bors <bors@rust-lang.org> | 2023-05-26 15:20:21 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-05-26 15:20:21 +0000 |
| commit | f1fd4673bc997164efbf0ba30cef01ffba24a43f (patch) | |
| tree | 3e25bb771f2c291b523acab5f42061e9ee836775 | |
| parent | 2422594f8c457d0a6870af09922698548e3816a3 (diff) | |
| parent | 8c82486ea92219d1c0c720fc598abac27c81a966 (diff) | |
| download | rust-f1fd4673bc997164efbf0ba30cef01ffba24a43f.tar.gz rust-f1fd4673bc997164efbf0ba30cef01ffba24a43f.zip | |
Auto merge of #10813 - y21:issue10755, r=xFrednet
[`default_constructed_unit_structs`]: do not lint on type alias paths Fixes #10755. Type aliases cannot be used as a constructor, so this lint should not trigger in those cases. I also changed `clippy_utils::is_ty_alias` to also consider associated types since [they kinda are type aliases too](https://github.com/rust-lang/rust/blob/48ec50ae39d0ca0baa0e78f56c395dcc6d7ebd65/compiler/rustc_resolve/src/late/diagnostics.rs#L1520). changelog: [`default_constructed_unit_structs`]: do not lint on type alias paths
| -rw-r--r-- | clippy_lints/src/default_constructed_unit_structs.rs | 15 | ||||
| -rw-r--r-- | clippy_utils/src/lib.rs | 2 | ||||
| -rw-r--r-- | tests/ui/default_constructed_unit_structs.fixed | 22 | ||||
| -rw-r--r-- | tests/ui/default_constructed_unit_structs.rs | 22 | ||||
| -rw-r--r-- | tests/ui/default_constructed_unit_structs.stderr | 8 |
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` |
