[default_constructed_unit_structs]: do not lint type aliases

This commit is contained in:
y21 2023-05-22 16:13:23 +02:00
parent 435a8ad86c
commit 8c82486ea9
5 changed files with 62 additions and 7 deletions

View file

@ -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)

View file

@ -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,
}

View file

@ -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>;

View file

@ -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();

View file

@ -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`