smarter E0390
This commit is contained in:
parent
5957f208a5
commit
0c13a9c020
6 changed files with 148 additions and 7 deletions
|
@ -1,4 +1,4 @@
|
||||||
A method was implemented on a primitive type.
|
A method or constant was implemented on a primitive type.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ impl *mut Foo {}
|
||||||
// `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
|
// `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
|
||||||
```
|
```
|
||||||
|
|
||||||
This isn't allowed, but using a trait to implement a method is a good solution.
|
This isn't allowed, but using a trait to implement a method or constant
|
||||||
|
is a good solution.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -44,8 +44,8 @@ struct InherentCollect<'tcx> {
|
||||||
|
|
||||||
impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
||||||
let ty = match item.kind {
|
let (ty, assoc_items) = match item.kind {
|
||||||
hir::ItemKind::Impl { of_trait: None, ref self_ty, .. } => self_ty,
|
hir::ItemKind::Impl { of_trait: None, ref self_ty, items, .. } => (self_ty, items),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"bool",
|
"bool",
|
||||||
"bool",
|
"bool",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Char => {
|
ty::Char => {
|
||||||
|
@ -80,6 +81,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"char",
|
"char",
|
||||||
"char",
|
"char",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Str => {
|
ty::Str => {
|
||||||
|
@ -90,6 +92,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"str",
|
"str",
|
||||||
"str",
|
"str",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
|
ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
|
||||||
|
@ -100,6 +103,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"slice_u8",
|
"slice_u8",
|
||||||
"[u8]",
|
"[u8]",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Slice(_) => {
|
ty::Slice(_) => {
|
||||||
|
@ -110,6 +114,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"slice",
|
"slice",
|
||||||
"[T]",
|
"[T]",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Array(_, _) => {
|
ty::Array(_, _) => {
|
||||||
|
@ -120,6 +125,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"array",
|
"array",
|
||||||
"[T; N]",
|
"[T; N]",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
|
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
|
||||||
|
@ -132,6 +138,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"const_slice_ptr",
|
"const_slice_ptr",
|
||||||
"*const [T]",
|
"*const [T]",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
|
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
|
||||||
|
@ -144,6 +151,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"mut_slice_ptr",
|
"mut_slice_ptr",
|
||||||
"*mut [T]",
|
"*mut [T]",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
|
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
|
||||||
|
@ -154,6 +162,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"const_ptr",
|
"const_ptr",
|
||||||
"*const T",
|
"*const T",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
|
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
|
||||||
|
@ -164,6 +173,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"mut_ptr",
|
"mut_ptr",
|
||||||
"*mut T",
|
"*mut T",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Int(ast::IntTy::I8) => {
|
ty::Int(ast::IntTy::I8) => {
|
||||||
|
@ -174,6 +184,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"i8",
|
"i8",
|
||||||
"i8",
|
"i8",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Int(ast::IntTy::I16) => {
|
ty::Int(ast::IntTy::I16) => {
|
||||||
|
@ -184,6 +195,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"i16",
|
"i16",
|
||||||
"i16",
|
"i16",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Int(ast::IntTy::I32) => {
|
ty::Int(ast::IntTy::I32) => {
|
||||||
|
@ -194,6 +206,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"i32",
|
"i32",
|
||||||
"i32",
|
"i32",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Int(ast::IntTy::I64) => {
|
ty::Int(ast::IntTy::I64) => {
|
||||||
|
@ -204,6 +217,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"i64",
|
"i64",
|
||||||
"i64",
|
"i64",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Int(ast::IntTy::I128) => {
|
ty::Int(ast::IntTy::I128) => {
|
||||||
|
@ -214,6 +228,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"i128",
|
"i128",
|
||||||
"i128",
|
"i128",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Int(ast::IntTy::Isize) => {
|
ty::Int(ast::IntTy::Isize) => {
|
||||||
|
@ -224,6 +239,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"isize",
|
"isize",
|
||||||
"isize",
|
"isize",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Uint(ast::UintTy::U8) => {
|
ty::Uint(ast::UintTy::U8) => {
|
||||||
|
@ -234,6 +250,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"u8",
|
"u8",
|
||||||
"u8",
|
"u8",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Uint(ast::UintTy::U16) => {
|
ty::Uint(ast::UintTy::U16) => {
|
||||||
|
@ -244,6 +261,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"u16",
|
"u16",
|
||||||
"u16",
|
"u16",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Uint(ast::UintTy::U32) => {
|
ty::Uint(ast::UintTy::U32) => {
|
||||||
|
@ -254,6 +272,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"u32",
|
"u32",
|
||||||
"u32",
|
"u32",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Uint(ast::UintTy::U64) => {
|
ty::Uint(ast::UintTy::U64) => {
|
||||||
|
@ -264,6 +283,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"u64",
|
"u64",
|
||||||
"u64",
|
"u64",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Uint(ast::UintTy::U128) => {
|
ty::Uint(ast::UintTy::U128) => {
|
||||||
|
@ -274,6 +294,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"u128",
|
"u128",
|
||||||
"u128",
|
"u128",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Uint(ast::UintTy::Usize) => {
|
ty::Uint(ast::UintTy::Usize) => {
|
||||||
|
@ -284,6 +305,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"usize",
|
"usize",
|
||||||
"usize",
|
"usize",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Float(ast::FloatTy::F32) => {
|
ty::Float(ast::FloatTy::F32) => {
|
||||||
|
@ -294,6 +316,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"f32",
|
"f32",
|
||||||
"f32",
|
"f32",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Float(ast::FloatTy::F64) => {
|
ty::Float(ast::FloatTy::F64) => {
|
||||||
|
@ -304,6 +327,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
|
||||||
"f64",
|
"f64",
|
||||||
"f64",
|
"f64",
|
||||||
item.span,
|
item.span,
|
||||||
|
assoc_items,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Error(_) => {}
|
ty::Error(_) => {}
|
||||||
|
@ -369,6 +393,7 @@ impl InherentCollect<'tcx> {
|
||||||
lang: &str,
|
lang: &str,
|
||||||
ty: &str,
|
ty: &str,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
assoc_items: &[hir::ImplItemRef<'_>],
|
||||||
) {
|
) {
|
||||||
match (lang_def_id, lang_def_id2) {
|
match (lang_def_id, lang_def_id2) {
|
||||||
(Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
|
(Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
|
||||||
|
@ -387,7 +412,34 @@ impl InherentCollect<'tcx> {
|
||||||
lang,
|
lang,
|
||||||
ty
|
ty
|
||||||
)
|
)
|
||||||
.span_help(span, "consider using a trait to implement these methods")
|
.span_help(
|
||||||
|
span,
|
||||||
|
&format!("consider using a trait{}", {
|
||||||
|
if assoc_items.len() == 0 {
|
||||||
|
String::new()
|
||||||
|
} else {
|
||||||
|
let plural = assoc_items.len() > 1;
|
||||||
|
format!(
|
||||||
|
" to implement {} {}{}",
|
||||||
|
if plural { "these" } else { "this" },
|
||||||
|
{
|
||||||
|
let item_types = assoc_items.iter().map(|x| x.kind);
|
||||||
|
if item_types.clone().all(|x| x == hir::AssocItemKind::Const) {
|
||||||
|
"constant"
|
||||||
|
} else if item_types
|
||||||
|
.clone()
|
||||||
|
.all(|x| matches! {x, hir::AssocItemKind::Fn{ .. } })
|
||||||
|
{
|
||||||
|
"method"
|
||||||
|
} else {
|
||||||
|
"associated item"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
if plural { "s" } else { "" }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0390]: only a single inherent implementation marked with `#[lang = "mut_p
|
||||||
LL | impl *mut Foo {}
|
LL | impl *mut Foo {}
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider using a trait to implement these methods
|
help: consider using a trait
|
||||||
--> $DIR/E0390.rs:5:1
|
--> $DIR/E0390.rs:5:1
|
||||||
|
|
|
|
||||||
LL | impl *mut Foo {}
|
LL | impl *mut Foo {}
|
||||||
|
|
23
src/test/ui/kinds-of-primitive-impl.rs
Normal file
23
src/test/ui/kinds-of-primitive-impl.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
|
||||||
|
impl u8 {
|
||||||
|
//~^ error: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive
|
||||||
|
pub const B: u8 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl str {
|
||||||
|
//~^ error: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive
|
||||||
|
fn foo() {}
|
||||||
|
fn bar(self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl char {
|
||||||
|
//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive
|
||||||
|
pub const B: u8 = 0;
|
||||||
|
pub const C: u8 = 0;
|
||||||
|
fn foo() {}
|
||||||
|
fn bar(self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
65
src/test/ui/kinds-of-primitive-impl.stderr
Normal file
65
src/test/ui/kinds-of-primitive-impl.stderr
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
error[E0390]: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive
|
||||||
|
--> $DIR/kinds-of-primitive-impl.rs:4:1
|
||||||
|
|
|
||||||
|
LL | / impl u8 {
|
||||||
|
LL | |
|
||||||
|
LL | | pub const B: u8 = 0;
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: consider using a trait to implement this constant
|
||||||
|
--> $DIR/kinds-of-primitive-impl.rs:4:1
|
||||||
|
|
|
||||||
|
LL | / impl u8 {
|
||||||
|
LL | |
|
||||||
|
LL | | pub const B: u8 = 0;
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
||||||
|
error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive
|
||||||
|
--> $DIR/kinds-of-primitive-impl.rs:9:1
|
||||||
|
|
|
||||||
|
LL | / impl str {
|
||||||
|
LL | |
|
||||||
|
LL | | fn foo() {}
|
||||||
|
LL | | fn bar(self) {}
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: consider using a trait to implement these methods
|
||||||
|
--> $DIR/kinds-of-primitive-impl.rs:9:1
|
||||||
|
|
|
||||||
|
LL | / impl str {
|
||||||
|
LL | |
|
||||||
|
LL | | fn foo() {}
|
||||||
|
LL | | fn bar(self) {}
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
||||||
|
error[E0390]: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive
|
||||||
|
--> $DIR/kinds-of-primitive-impl.rs:15:1
|
||||||
|
|
|
||||||
|
LL | / impl char {
|
||||||
|
LL | |
|
||||||
|
LL | | pub const B: u8 = 0;
|
||||||
|
LL | | pub const C: u8 = 0;
|
||||||
|
LL | | fn foo() {}
|
||||||
|
LL | | fn bar(self) {}
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: consider using a trait to implement these associated items
|
||||||
|
--> $DIR/kinds-of-primitive-impl.rs:15:1
|
||||||
|
|
|
||||||
|
LL | / impl char {
|
||||||
|
LL | |
|
||||||
|
LL | | pub const B: u8 = 0;
|
||||||
|
LL | | pub const C: u8 = 0;
|
||||||
|
LL | | fn foo() {}
|
||||||
|
LL | | fn bar(self) {}
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0390`.
|
|
@ -6,7 +6,7 @@ LL | |
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
|
|
||||||
help: consider using a trait to implement these methods
|
help: consider using a trait
|
||||||
--> $DIR/single-primitive-inherent-impl.rs:11:1
|
--> $DIR/single-primitive-inherent-impl.rs:11:1
|
||||||
|
|
|
|
||||||
LL | / impl str {
|
LL | / impl str {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue