Skip to content

Commit 959bf2b

Browse files
committed
rustc_pass_by_value: handle generic and const type parameters
1 parent a6762e9 commit 959bf2b

File tree

5 files changed

+74
-16
lines changed

5 files changed

+74
-16
lines changed

compiler/rustc_lint/src/pass_by_value.rs

+19-14
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,13 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
5151
match path.res {
5252
Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => {
5353
let name = cx.tcx.item_name(def_id).to_ident_string();
54-
return Some(format!("{}{}", name, gen_args(path.segments.last().unwrap())));
54+
let path_segment = path.segments.last().unwrap();
55+
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
5556
}
5657
Res::SelfTy(None, Some((did, _))) => {
5758
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
5859
if cx.tcx.has_attr(adt.did, sym::rustc_pass_by_value) {
59-
let name = cx.tcx.item_name(adt.did).to_ident_string();
60-
let param =
61-
substs.first().map(|s| format!("<{}>", s)).unwrap_or("".to_string());
62-
return Some(format!("{}{}", name, param));
60+
return Some(cx.tcx.def_path_str_with_substs(adt.did, substs));
6361
}
6462
}
6563
}
@@ -70,22 +68,29 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
7068
None
7169
}
7270

73-
fn gen_args(segment: &PathSegment<'_>) -> String {
71+
fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
7472
if let Some(args) = &segment.args {
75-
let lifetimes = args
73+
let params = args
7674
.args
7775
.iter()
78-
.filter_map(|arg| {
79-
if let GenericArg::Lifetime(lt) = arg {
80-
Some(lt.name.ident().to_string())
81-
} else {
82-
None
76+
.filter_map(|arg| match arg {
77+
GenericArg::Lifetime(lt) => Some(lt.name.ident().to_string()),
78+
GenericArg::Type(ty) => {
79+
let snippet =
80+
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_default();
81+
Some(snippet)
8382
}
83+
GenericArg::Const(c) => {
84+
let snippet =
85+
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_default();
86+
Some(snippet)
87+
}
88+
_ => None,
8489
})
8590
.collect::<Vec<_>>();
8691

87-
if !lifetimes.is_empty() {
88-
return format!("<{}>", lifetimes.join(", "));
92+
if !params.is_empty() {
93+
return format!("<{}>", params.join(", "));
8994
}
9095
}
9196

src/test/ui-fulldeps/internal-lints/rustc_pass_by_value.rs

+15
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,19 @@ impl CustomStruct {
9898
}
9999
}
100100

101+
#[rustc_pass_by_value]
102+
struct WithParameters<T, const N: usize, M = u32> {
103+
slice: [T; N],
104+
m: M,
105+
}
106+
107+
impl<T> WithParameters<T, 1> {
108+
fn test(
109+
value: WithParameters<T, 1>,
110+
reference: &WithParameters<T, 1>, //~ ERROR passing `WithParameters<T, 1>` by reference
111+
reference_with_m: &WithParameters<T, 1, u32>, //~ ERROR passing `WithParameters<T, 1, u32>` by reference
112+
) {
113+
}
114+
}
115+
101116
fn main() {}

src/test/ui-fulldeps/internal-lints/rustc_pass_by_value.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,17 @@ error: passing `CustomAlias<>` by reference
100100
LL | reference: &CustomAlias,
101101
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<>`
102102

103-
error: aborting due to 16 previous errors
103+
error: passing `WithParameters<T, 1>` by reference
104+
--> $DIR/rustc_pass_by_value.rs:110:20
105+
|
106+
LL | reference: &WithParameters<T, 1>,
107+
| ^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1>`
108+
109+
error: passing `WithParameters<T, 1, u32>` by reference
110+
--> $DIR/rustc_pass_by_value.rs:111:27
111+
|
112+
LL | reference_with_m: &WithParameters<T, 1, u32>,
113+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try passing by value: `WithParameters<T, 1, u32>`
114+
115+
error: aborting due to 18 previous errors
104116

src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.rs

+14
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,18 @@ impl Foo {
3737
fn with_ref(&self) {} //~ ERROR passing `Foo` by reference
3838
}
3939

40+
#[rustc_pass_by_value]
41+
struct WithParameters<T, const N: usize, M = u32> {
42+
slice: [T; N],
43+
m: M,
44+
}
45+
46+
impl<T> WithParameters<T, 1> {
47+
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize>` by reference
48+
}
49+
50+
impl<T> WithParameters<T, 1, u8> {
51+
fn with_ref(&self) {} //~ ERROR passing `WithParameters<T, 1_usize, u8>` by reference
52+
}
53+
4054
fn main() {}

src/test/ui-fulldeps/internal-lints/rustc_pass_by_value_self.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,17 @@ error: passing `Foo` by reference
2222
LL | fn with_ref(&self) {}
2323
| ^^^^^ help: try passing by value: `Foo`
2424

25-
error: aborting due to 3 previous errors
25+
error: passing `WithParameters<T, 1_usize>` by reference
26+
--> $DIR/rustc_pass_by_value_self.rs:47:17
27+
|
28+
LL | fn with_ref(&self) {}
29+
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize>`
30+
31+
error: passing `WithParameters<T, 1_usize, u8>` by reference
32+
--> $DIR/rustc_pass_by_value_self.rs:51:17
33+
|
34+
LL | fn with_ref(&self) {}
35+
| ^^^^^ help: try passing by value: `WithParameters<T, 1_usize, u8>`
36+
37+
error: aborting due to 5 previous errors
2638

0 commit comments

Comments
 (0)