Rollup merge of #92646 - mdibaiee:76935/pass-by-value, r=lcnr
feat: rustc_pass_by_value lint attribute Useful for thin wrapper attributes that are best passed as value instead of reference. Fixes #76935
This commit is contained in:
commit
c5041f88ea
14 changed files with 372 additions and 138 deletions
|
@ -623,6 +623,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
|
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
|
||||||
"language items are subject to change",
|
"language items are subject to change",
|
||||||
),
|
),
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_pass_by_value, Normal,
|
||||||
|
template!(Word), WarnFollowing,
|
||||||
|
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
|
||||||
|
),
|
||||||
BuiltinAttribute {
|
BuiltinAttribute {
|
||||||
name: sym::rustc_diagnostic_item,
|
name: sym::rustc_diagnostic_item,
|
||||||
type_: Normal,
|
type_: Normal,
|
||||||
|
|
|
@ -5,10 +5,7 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::{
|
use rustc_hir::{GenericArg, HirId, Item, ItemKind, Node, Path, PathSegment, QPath, Ty, TyKind};
|
||||||
GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty,
|
|
||||||
TyKind,
|
|
||||||
};
|
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||||
|
@ -58,13 +55,6 @@ declare_tool_lint! {
|
||||||
report_in_external_macro: true
|
report_in_external_macro: true
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_tool_lint! {
|
|
||||||
pub rustc::TY_PASS_BY_REFERENCE,
|
|
||||||
Allow,
|
|
||||||
"passing `Ty` or `TyCtxt` by reference",
|
|
||||||
report_in_external_macro: true
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub rustc::USAGE_OF_QUALIFIED_TY,
|
pub rustc::USAGE_OF_QUALIFIED_TY,
|
||||||
Allow,
|
Allow,
|
||||||
|
@ -74,7 +64,6 @@ declare_tool_lint! {
|
||||||
|
|
||||||
declare_lint_pass!(TyTyKind => [
|
declare_lint_pass!(TyTyKind => [
|
||||||
USAGE_OF_TY_TYKIND,
|
USAGE_OF_TY_TYKIND,
|
||||||
TY_PASS_BY_REFERENCE,
|
|
||||||
USAGE_OF_QUALIFIED_TY,
|
USAGE_OF_QUALIFIED_TY,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -131,26 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => {
|
|
||||||
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
|
|
||||||
if cx.tcx.impl_trait_ref(impl_did).is_some() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(t) = is_ty_or_ty_ctxt(cx, &inner_ty) {
|
|
||||||
cx.struct_span_lint(TY_PASS_BY_REFERENCE, ty.span, |lint| {
|
|
||||||
lint.build(&format!("passing `{}` by reference", t))
|
|
||||||
.span_suggestion(
|
|
||||||
ty.span,
|
|
||||||
"try passing by value",
|
|
||||||
t,
|
|
||||||
// Changing type of function argument
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ mod non_ascii_idents;
|
||||||
mod non_fmt_panic;
|
mod non_fmt_panic;
|
||||||
mod nonstandard_style;
|
mod nonstandard_style;
|
||||||
mod noop_method_call;
|
mod noop_method_call;
|
||||||
|
mod pass_by_value;
|
||||||
mod passes;
|
mod passes;
|
||||||
mod redundant_semicolon;
|
mod redundant_semicolon;
|
||||||
mod traits;
|
mod traits;
|
||||||
|
@ -85,6 +86,7 @@ use non_ascii_idents::*;
|
||||||
use non_fmt_panic::NonPanicFmt;
|
use non_fmt_panic::NonPanicFmt;
|
||||||
use nonstandard_style::*;
|
use nonstandard_style::*;
|
||||||
use noop_method_call::*;
|
use noop_method_call::*;
|
||||||
|
use pass_by_value::*;
|
||||||
use redundant_semicolon::*;
|
use redundant_semicolon::*;
|
||||||
use traits::*;
|
use traits::*;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
@ -490,6 +492,8 @@ fn register_internals(store: &mut LintStore) {
|
||||||
store.register_late_pass(|| Box::new(ExistingDocKeyword));
|
store.register_late_pass(|| Box::new(ExistingDocKeyword));
|
||||||
store.register_lints(&TyTyKind::get_lints());
|
store.register_lints(&TyTyKind::get_lints());
|
||||||
store.register_late_pass(|| Box::new(TyTyKind));
|
store.register_late_pass(|| Box::new(TyTyKind));
|
||||||
|
store.register_lints(&PassByValue::get_lints());
|
||||||
|
store.register_late_pass(|| Box::new(PassByValue));
|
||||||
store.register_group(
|
store.register_group(
|
||||||
false,
|
false,
|
||||||
"rustc::internal",
|
"rustc::internal",
|
||||||
|
@ -497,8 +501,8 @@ fn register_internals(store: &mut LintStore) {
|
||||||
vec![
|
vec![
|
||||||
LintId::of(DEFAULT_HASH_TYPES),
|
LintId::of(DEFAULT_HASH_TYPES),
|
||||||
LintId::of(USAGE_OF_TY_TYKIND),
|
LintId::of(USAGE_OF_TY_TYKIND),
|
||||||
|
LintId::of(PASS_BY_VALUE),
|
||||||
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
||||||
LintId::of(TY_PASS_BY_REFERENCE),
|
|
||||||
LintId::of(USAGE_OF_QUALIFIED_TY),
|
LintId::of(USAGE_OF_QUALIFIED_TY),
|
||||||
LintId::of(EXISTING_DOC_KEYWORD),
|
LintId::of(EXISTING_DOC_KEYWORD),
|
||||||
],
|
],
|
||||||
|
|
94
compiler/rustc_lint/src/pass_by_value.rs
Normal file
94
compiler/rustc_lint/src/pass_by_value.rs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
use crate::{LateContext, LateLintPass, LintContext};
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def::Res;
|
||||||
|
use rustc_hir::{GenericArg, PathSegment, QPath, TyKind};
|
||||||
|
use rustc_middle::ty;
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
|
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.
|
||||||
|
/// 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`)
|
||||||
|
pub rustc::PASS_BY_VALUE,
|
||||||
|
Warn,
|
||||||
|
"pass by reference of a type flagged as `#[rustc_pass_by_value]`",
|
||||||
|
report_in_external_macro: true
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(PassByValue => [PASS_BY_VALUE]);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for PassByValue {
|
||||||
|
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
|
||||||
|
match &ty.kind {
|
||||||
|
TyKind::Rptr(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => {
|
||||||
|
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {
|
||||||
|
if cx.tcx.impl_trait_ref(impl_did).is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
|
||||||
|
cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
|
||||||
|
lint.build(&format!("passing `{}` by reference", t))
|
||||||
|
.span_suggestion(
|
||||||
|
ty.span,
|
||||||
|
"try passing by value",
|
||||||
|
t,
|
||||||
|
// Changing type of function argument
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<String> {
|
||||||
|
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
|
||||||
|
match path.res {
|
||||||
|
Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => {
|
||||||
|
let name = cx.tcx.item_name(def_id).to_ident_string();
|
||||||
|
let path_segment = path.segments.last().unwrap();
|
||||||
|
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
|
||||||
|
}
|
||||||
|
Res::SelfTy(None, Some((did, _))) => {
|
||||||
|
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
|
||||||
|
if cx.tcx.has_attr(adt.did, sym::rustc_pass_by_value) {
|
||||||
|
return Some(cx.tcx.def_path_str_with_substs(adt.did, substs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
|
||||||
|
if let Some(args) = &segment.args {
|
||||||
|
let params = args
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|arg| match arg {
|
||||||
|
GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
|
||||||
|
GenericArg::Type(ty) => {
|
||||||
|
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_default()
|
||||||
|
}
|
||||||
|
GenericArg::Const(c) => {
|
||||||
|
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_default()
|
||||||
|
}
|
||||||
|
GenericArg::Infer(_) => String::from("_"),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if !params.is_empty() {
|
||||||
|
return format!("<{}>", params.join(", "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String::new()
|
||||||
|
}
|
|
@ -961,6 +961,7 @@ pub struct FreeRegionInfo {
|
||||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
|
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[rustc_diagnostic_item = "TyCtxt"]
|
#[rustc_diagnostic_item = "TyCtxt"]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
|
||||||
pub struct TyCtxt<'tcx> {
|
pub struct TyCtxt<'tcx> {
|
||||||
gcx: &'tcx GlobalCtxt<'tcx>,
|
gcx: &'tcx GlobalCtxt<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,6 +464,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_diagnostic_item = "Ty"]
|
#[rustc_diagnostic_item = "Ty"]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
|
||||||
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
||||||
|
|
||||||
impl ty::EarlyBoundRegion {
|
impl ty::EarlyBoundRegion {
|
||||||
|
|
|
@ -114,6 +114,7 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
|
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
|
||||||
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
|
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
|
||||||
|
sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
|
||||||
sym::rustc_const_unstable
|
sym::rustc_const_unstable
|
||||||
| sym::rustc_const_stable
|
| sym::rustc_const_stable
|
||||||
| sym::unstable
|
| sym::unstable
|
||||||
|
@ -1066,6 +1067,24 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid
|
is_valid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Warns against some misuses of `#[pass_by_value]`
|
||||||
|
fn check_pass_by_value(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
|
||||||
|
match target {
|
||||||
|
Target::Struct | Target::Enum | Target::TyAlias => true,
|
||||||
|
_ => {
|
||||||
|
self.tcx
|
||||||
|
.sess
|
||||||
|
.struct_span_err(
|
||||||
|
attr.span,
|
||||||
|
"`pass_by_value` attribute should be applied to a struct, enum or type alias.",
|
||||||
|
)
|
||||||
|
.span_label(*span, "is not a struct, enum or type alias")
|
||||||
|
.emit();
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Warns against some misuses of `#[must_use]`
|
/// Warns against some misuses of `#[must_use]`
|
||||||
fn check_must_use(
|
fn check_must_use(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -1170,6 +1170,7 @@ symbols! {
|
||||||
rustc_paren_sugar,
|
rustc_paren_sugar,
|
||||||
rustc_partition_codegened,
|
rustc_partition_codegened,
|
||||||
rustc_partition_reused,
|
rustc_partition_reused,
|
||||||
|
rustc_pass_by_value,
|
||||||
rustc_peek,
|
rustc_peek,
|
||||||
rustc_peek_definite_init,
|
rustc_peek_definite_init,
|
||||||
rustc_peek_liveness,
|
rustc_peek_liveness,
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:13:13
|
|
||||||
|
|
|
||||||
LL | ty_ref: &Ty<'_>,
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:4:9
|
|
||||||
|
|
|
||||||
LL | #![deny(rustc::ty_pass_by_reference)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:15:18
|
|
||||||
|
|
|
||||||
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:19:28
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:19:55
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:26:17
|
|
||||||
|
|
|
||||||
LL | ty_ref: &Ty<'_>,
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:28:22
|
|
||||||
|
|
|
||||||
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:31:41
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:31:68
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:53:17
|
|
||||||
|
|
|
||||||
LL | ty_ref: &Ty<'_>,
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:55:22
|
|
||||||
|
|
|
||||||
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: passing `Ty<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:59:38
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
|
||||||
|
|
||||||
error: passing `TyCtxt<'_>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref.rs:59:65
|
|
||||||
|
|
|
||||||
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
|
||||||
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
error: passing `TyCtxt<'tcx>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref_self.rs:18:15
|
|
||||||
|
|
|
||||||
LL | fn by_ref(&self) {}
|
|
||||||
| ^^^^^ help: try passing by value: `TyCtxt<'tcx>`
|
|
||||||
|
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/pass_ty_by_ref_self.rs:8:9
|
|
||||||
|
|
|
||||||
LL | #![deny(rustc::ty_pass_by_reference)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: passing `Ty<'tcx>` by reference
|
|
||||||
--> $DIR/pass_ty_by_ref_self.rs:31:21
|
|
||||||
|
|
|
||||||
LL | fn by_ref(self: &Ty<'tcx>) {}
|
|
||||||
| ^^^^^^^^^ help: try passing by value: `Ty<'tcx>`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// compile-flags: -Z unstable-options
|
// compile-flags: -Z unstable-options
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![deny(rustc::ty_pass_by_reference)]
|
#![deny(rustc::pass_by_value)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
@ -61,4 +62,57 @@ impl Foo {
|
||||||
//~^^ ERROR passing `TyCtxt<'_>` by reference
|
//~^^ ERROR passing `TyCtxt<'_>` by reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
enum CustomEnum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CustomEnum {
|
||||||
|
fn test(
|
||||||
|
value: CustomEnum,
|
||||||
|
reference: &CustomEnum, //~ ERROR passing `CustomEnum` by reference
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct CustomStruct {
|
||||||
|
s: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct WithParameters<T, const N: usize, M = u32> {
|
||||||
|
slice: [T; N],
|
||||||
|
m: M,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithParameters<T, 1> {
|
||||||
|
fn test<'a>(
|
||||||
|
value: WithParameters<T, 1>,
|
||||||
|
reference: &'a WithParameters<T, 1>, //~ ERROR passing `WithParameters<T, 1>` by reference
|
||||||
|
reference_with_m: &WithParameters<T, 1, u32>, //~ ERROR passing `WithParameters<T, 1, u32>` by reference
|
||||||
|
) -> &'a WithParameters<T, 1> {
|
||||||
|
//~^ ERROR passing `WithParameters<T, 1>` by reference
|
||||||
|
reference as &WithParameters<_, 1> //~ ERROR passing `WithParameters<_, 1>` by reference
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
128
src/test/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr
Normal file
128
src/test/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:14:13
|
||||||
|
|
|
||||||
|
LL | ty_ref: &Ty<'_>,
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:5:9
|
||||||
|
|
|
||||||
|
LL | #![deny(rustc::pass_by_value)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:16:18
|
||||||
|
|
|
||||||
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:20:28
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:20:55
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:27:17
|
||||||
|
|
|
||||||
|
LL | ty_ref: &Ty<'_>,
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:29:22
|
||||||
|
|
|
||||||
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:32:41
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:32:68
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_in_trait(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>);
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:54:17
|
||||||
|
|
|
||||||
|
LL | ty_ref: &Ty<'_>,
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:56:22
|
||||||
|
|
|
||||||
|
LL | ty_ctxt_ref: &TyCtxt<'_>,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `Ty<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:60:38
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^ help: try passing by value: `Ty<'_>`
|
||||||
|
|
||||||
|
error: passing `TyCtxt<'_>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:60:65
|
||||||
|
|
|
||||||
|
LL | fn ty_multi_ref_assoc(ty_multi: &&Ty<'_>, ty_ctxt_multi: &&&&TyCtxt<'_>) {}
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `TyCtxt<'_>`
|
||||||
|
|
||||||
|
error: passing `CustomEnum` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:74:20
|
||||||
|
|
|
||||||
|
LL | reference: &CustomEnum,
|
||||||
|
| ^^^^^^^^^^^ help: try passing by value: `CustomEnum`
|
||||||
|
|
||||||
|
error: passing `CustomStruct` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:85:24
|
||||||
|
|
|
||||||
|
LL | type CustomAlias<'a> = &'a CustomStruct;
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
|
||||||
|
|
||||||
|
error: passing `CustomStruct` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:90:20
|
||||||
|
|
|
||||||
|
LL | reference: &CustomStruct,
|
||||||
|
| ^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`
|
||||||
|
|
||||||
|
error: passing `CustomAlias<>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:96:20
|
||||||
|
|
|
||||||
|
LL | reference: &CustomAlias,
|
||||||
|
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:110:20
|
||||||
|
|
|
||||||
|
LL | reference: &'a WithParameters<T, 1>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1, u32>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:111:27
|
||||||
|
|
|
||||||
|
LL | reference_with_m: &WithParameters<T, 1, u32>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1, u32>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:112:10
|
||||||
|
|
|
||||||
|
LL | ) -> &'a WithParameters<T, 1> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<_, 1>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value.rs:114:22
|
||||||
|
|
|
||||||
|
LL | reference as &WithParameters<_, 1>
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<_, 1>`
|
||||||
|
|
||||||
|
error: aborting due to 20 previous errors
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
// Considering that all other `internal-lints` are tested here
|
// Considering that all other `internal-lints` are tested here
|
||||||
// this seems like the cleaner solution though.
|
// this seems like the cleaner solution though.
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![deny(rustc::ty_pass_by_reference)]
|
#![deny(rustc::pass_by_value)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
#[rustc_diagnostic_item = "TyCtxt"]
|
#[rustc_pass_by_value]
|
||||||
struct TyCtxt<'tcx> {
|
struct TyCtxt<'tcx> {
|
||||||
inner: &'tcx (),
|
inner: &'tcx (),
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
fn by_ref(&self) {} //~ ERROR passing `TyCtxt<'tcx>` by reference
|
fn by_ref(&self) {} //~ ERROR passing `TyCtxt<'tcx>` by reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct TyS<'tcx> {
|
struct TyS<'tcx> {
|
||||||
inner: &'tcx (),
|
inner: &'tcx (),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_diagnostic_item = "Ty"]
|
#[rustc_pass_by_value]
|
||||||
type Ty<'tcx> = &'tcx TyS<'tcx>;
|
type Ty<'tcx> = &'tcx TyS<'tcx>;
|
||||||
|
|
||||||
impl<'tcx> TyS<'tcx> {
|
impl<'tcx> TyS<'tcx> {
|
||||||
|
@ -31,4 +30,25 @@ impl<'tcx> TyS<'tcx> {
|
||||||
fn by_ref(self: &Ty<'tcx>) {} //~ ERROR passing `Ty<'tcx>` by reference
|
fn by_ref(self: &Ty<'tcx>) {} //~ ERROR passing `Ty<'tcx>` by reference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn with_ref(&self) {} //~ ERROR passing `Foo` by reference
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_pass_by_value]
|
||||||
|
struct WithParameters<T, const N: usize, M = u32> {
|
||||||
|
slice: [T; N],
|
||||||
|
m: M,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithParameters<T, 1> {
|
||||||
|
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize>` by reference
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithParameters<T, 1, u8> {
|
||||||
|
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize, u8>` by reference
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
|
@ -0,0 +1,38 @@
|
||||||
|
error: passing `TyCtxt<'tcx>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:18:15
|
||||||
|
|
|
||||||
|
LL | fn by_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `TyCtxt<'tcx>`
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:8:9
|
||||||
|
|
|
||||||
|
LL | #![deny(rustc::pass_by_value)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: passing `Ty<'tcx>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:30:21
|
||||||
|
|
|
||||||
|
LL | fn by_ref(self: &Ty<'tcx>) {}
|
||||||
|
| ^^^^^^^^^ help: try passing by value: `Ty<'tcx>`
|
||||||
|
|
||||||
|
error: passing `Foo` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:37:17
|
||||||
|
|
|
||||||
|
LL | fn with_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `Foo`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1_usize>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:47:17
|
||||||
|
|
|
||||||
|
LL | fn with_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize>`
|
||||||
|
|
||||||
|
error: passing `WithParameters<T, 1_usize, u8>` by reference
|
||||||
|
--> $DIR/rustc_pass_by_value_self.rs:51:17
|
||||||
|
|
|
||||||
|
LL | fn with_ref(&self) {}
|
||||||
|
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize, u8>`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue