1
Fork 0

rustc_pass_by_value lint: add test on custom types

This commit is contained in:
Mahdi Dibaiee 2022-01-10 08:54:42 +00:00
parent 4c3e330a8c
commit 91ed6892f7
No known key found for this signature in database
GPG key ID: BABA115BDF0C598A
4 changed files with 82 additions and 22 deletions

View file

@ -11,6 +11,7 @@ declare_tool_lint! {
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to always be passed by value. /// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to always be passed by value.
/// This is usually used for types that are thin wrappers around references, so there is no benefit to an extra /// This is usually used for types that are thin wrappers around references, so there is no benefit to an extra
/// layer of indirection. (Example: `Ty` which is a reference to a `TyS`) /// layer of indirection. (Example: `Ty` which is a reference to a `TyS`)
/// This lint relies on `#[rustc_diagnostic_item]` being available for the target.
pub rustc::PASS_BY_VALUE, pub rustc::PASS_BY_VALUE,
Warn, Warn,
"pass by reference of a type flagged as `#[rustc_pass_by_value]`", "pass by reference of a type flagged as `#[rustc_pass_by_value]`",

View file

@ -1070,20 +1070,15 @@ impl CheckAttrVisitor<'_> {
/// Warns against some misuses of `#[pass_by_value]` /// Warns against some misuses of `#[pass_by_value]`
fn check_pass_by_value(&self, attr: &Attribute, span: &Span, target: Target) -> bool { fn check_pass_by_value(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
match target { match target {
Target::Struct Target::Struct | Target::Enum | Target::TyAlias => true,
| Target::Enum
| Target::Union
| Target::Trait
| Target::TraitAlias
| Target::TyAlias => true,
_ => { _ => {
self.tcx self.tcx
.sess .sess
.struct_span_err( .struct_span_err(
attr.span, attr.span,
"`pass_by_value` attribute should be applied to a struct, enum, trait or type alias.", "`pass_by_value` attribute should be applied to a struct, enum or type alias.",
) )
.span_label(*span, "is not a struct, enum, trait or type alias") .span_label(*span, "is not a struct, enum or type alias")
.emit(); .emit();
false false
} }

View file

@ -1,5 +1,6 @@
// compile-flags: -Z unstable-options // compile-flags: -Z unstable-options
#![feature(rustc_attrs)]
#![feature(rustc_private)] #![feature(rustc_private)]
#![deny(rustc::pass_by_value)] #![deny(rustc::pass_by_value)]
#![allow(unused)] #![allow(unused)]
@ -61,4 +62,43 @@ impl Foo {
//~^^ ERROR passing `TyCtxt<'_>` by reference //~^^ ERROR passing `TyCtxt<'_>` by reference
} }
#[rustc_diagnostic_item = "CustomEnum"]
#[rustc_pass_by_value]
enum CustomEnum {
A,
B,
}
impl CustomEnum {
fn test(
value: CustomEnum,
reference: &CustomEnum, //~ ERROR passing `CustomEnum` by reference
) {
}
}
#[rustc_diagnostic_item = "CustomStruct"]
#[rustc_pass_by_value]
struct CustomStruct {
s: u8,
}
#[rustc_diagnostic_item = "CustomAlias"]
#[rustc_pass_by_value]
type CustomAlias<'a> = &'a CustomStruct; //~ ERROR passing `CustomStruct` by reference
impl CustomStruct {
fn test(
value: CustomStruct,
reference: &CustomStruct, //~ ERROR passing `CustomStruct` by reference
) {
}
fn test_alias(
value: CustomAlias,
reference: &CustomAlias, //~ ERROR passing `CustomAlias<>` by reference
) {
}
}
fn main() {} fn main() {}

View file

@ -1,80 +1,104 @@
error: passing `Ty<'_>` by reference error: passing `Ty<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:13:13 --> $DIR/rustc_pass_by_value.rs:14:13
| |
LL | ty_ref: &Ty<'_>, LL | ty_ref: &Ty<'_>,
| ^^^^^^^ help: try passing by value: `Ty<'_>` | ^^^^^^^ help: try passing by value: `Ty<'_>`
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/rustc_pass_by_value.rs:4:9 --> $DIR/rustc_pass_by_value.rs:5:9
| |
LL | #![deny(rustc::pass_by_value)] LL | #![deny(rustc::pass_by_value)]
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
error: passing `TyCtxt<'_>` by reference error: passing `TyCtxt<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:15:18 --> $DIR/rustc_pass_by_value.rs:16:18
| |
LL | ty_ctxt_ref: &TyCtxt<'_>, LL | ty_ctxt_ref: &TyCtxt<'_>,
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>` | ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
error: passing `Ty<'_>` by reference error: passing `Ty<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:19:28 --> $DIR/rustc_pass_by_value.rs:20:28
| |
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {} LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^ help: try passing by value: `Ty<'_>` | ^^^^^^^ help: try passing by value: `Ty<'_>`
error: passing `TyCtxt<'_>` by reference error: passing `TyCtxt<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:19:55 --> $DIR/rustc_pass_by_value.rs:20:55
| |
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {} LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>` | ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
error: passing `Ty<'_>` by reference error: passing `Ty<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:26:17 --> $DIR/rustc_pass_by_value.rs:27:17
| |
LL | ty_ref: &Ty<'_>, LL | ty_ref: &Ty<'_>,
| ^^^^^^^ help: try passing by value: `Ty<'_>` | ^^^^^^^ help: try passing by value: `Ty<'_>`
error: passing `TyCtxt<'_>` by reference error: passing `TyCtxt<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:28:22 --> $DIR/rustc_pass_by_value.rs:29:22
| |
LL | ty_ctxt_ref: &TyCtxt<'_>, LL | ty_ctxt_ref: &TyCtxt<'_>,
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>` | ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
error: passing `Ty<'_>` by reference error: passing `Ty<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:31:41 --> $DIR/rustc_pass_by_value.rs:32:41
| |
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>); LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
| ^^^^^^^ help: try passing by value: `Ty<'_>` | ^^^^^^^ help: try passing by value: `Ty<'_>`
error: passing `TyCtxt<'_>` by reference error: passing `TyCtxt<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:31:68 --> $DIR/rustc_pass_by_value.rs:32:68
| |
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>); LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>` | ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
error: passing `Ty<'_>` by reference error: passing `Ty<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:53:17 --> $DIR/rustc_pass_by_value.rs:54:17
| |
LL | ty_ref: &Ty<'_>, LL | ty_ref: &Ty<'_>,
| ^^^^^^^ help: try passing by value: `Ty<'_>` | ^^^^^^^ help: try passing by value: `Ty<'_>`
error: passing `TyCtxt<'_>` by reference error: passing `TyCtxt<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:55:22 --> $DIR/rustc_pass_by_value.rs:56:22
| |
LL | ty_ctxt_ref: &TyCtxt<'_>, LL | ty_ctxt_ref: &TyCtxt<'_>,
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>` | ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
error: passing `Ty<'_>` by reference error: passing `Ty<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:59:38 --> $DIR/rustc_pass_by_value.rs:60:38
| |
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {} LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^ help: try passing by value: `Ty<'_>` | ^^^^^^^ help: try passing by value: `Ty<'_>`
error: passing `TyCtxt<'_>` by reference error: passing `TyCtxt<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:59:65 --> $DIR/rustc_pass_by_value.rs:60:65
| |
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {} LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>` | ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
error: aborting due to 12 previous errors error: passing `CustomEnum` by reference
--> $DIR/rustc_pass_by_value.rs:75:20
|
LL | reference: &CustomEnum,
| ^^^^^^^^^^^ help: try passing by value: `CustomEnum`
error: passing `CustomStruct` by reference
--> $DIR/rustc_pass_by_value.rs:88:24
|
LL | type CustomAlias<'a> = &'a CustomStruct;
| ^^^^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
error: passing `CustomStruct` by reference
--> $DIR/rustc_pass_by_value.rs:93:20
|
LL | reference: &CustomStruct,
| ^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
error: passing `CustomAlias<>` by reference
--> $DIR/rustc_pass_by_value.rs:99:20
|
LL | reference: &CustomAlias,
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<>`
error: aborting due to 16 previous errors