From 975547d475fcb3a7c6e440be5f8de3bf0497d383 Mon Sep 17 00:00:00 2001 From: Ayrton Date: Fri, 4 Sep 2020 09:45:09 -0400 Subject: [PATCH] changed lint to suggest casting to the proper function type and added a test --- compiler/rustc_lint/src/builtin.rs | 10 ++++++---- src/test/ui/lint/function-references.rs | 22 +++++++++++++++++++++ src/test/ui/lint/function-references.stderr | 22 +++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/lint/function-references.rs create mode 100644 src/test/ui/lint/function-references.stderr diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b089d4dcfba4e..86cf4ebb18743 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2957,17 +2957,19 @@ impl<'tcx> LateLintPass<'tcx> for FunctionReferences { if let hir::ExprKind::Path(qpath) = &referent.kind { if let Some(def_id) = cx.qpath_res(qpath, referent.hir_id).opt_def_id() { cx.tcx.hir().get_if_local(def_id).map(|node| { - if node.fn_decl().is_some() { + node.fn_decl().map(|decl| { if let Some(ident) = node.ident() { cx.struct_span_lint(FUNCTION_REFERENCES, referent.span, |lint| { + let num_args = decl.inputs.len(); lint.build(&format!( - "cast {} with `as *const ()` to use it as a pointer", - ident.to_string() + "cast `{}` with `as *const fn({}) -> _` to use it as a pointer", + ident.to_string(), + vec!["_"; num_args].join(", ") )) .emit() }); } - } + }); }); } } diff --git a/src/test/ui/lint/function-references.rs b/src/test/ui/lint/function-references.rs new file mode 100644 index 0000000000000..748f2560caa3a --- /dev/null +++ b/src/test/ui/lint/function-references.rs @@ -0,0 +1,22 @@ +// check-pass +fn foo() -> usize { 42 } +fn bar(x: usize) -> usize { x } +fn baz(x: usize, y: usize) -> usize { x + y } + +fn main() { + println!("{:p}", &foo); + //~^ WARN cast `foo` with `as *const fn() -> _` to use it as a pointer + println!("{:p}", &bar); + //~^ WARN cast `bar` with `as *const fn(_) -> _` to use it as a pointer + println!("{:p}", &baz); + //~^ WARN cast `baz` with `as *const fn(_, _) -> _` to use it as a pointer + + //should not produce any warnings + println!("{:p}", foo as *const fn() -> usize); + println!("{:p}", bar as *const fn(usize) -> usize); + println!("{:p}", baz as *const fn(usize, usize) -> usize); + + //should not produce any warnings + let fn_thing = foo; + println!("{:p}", &fn_thing); +} diff --git a/src/test/ui/lint/function-references.stderr b/src/test/ui/lint/function-references.stderr new file mode 100644 index 0000000000000..bd2da6e1167a7 --- /dev/null +++ b/src/test/ui/lint/function-references.stderr @@ -0,0 +1,22 @@ +warning: cast `foo` with `as *const fn() -> _` to use it as a pointer + --> $DIR/function-references.rs:7:23 + | +LL | println!("{:p}", &foo); + | ^^^ + | + = note: `#[warn(function_references)]` on by default + +warning: cast `bar` with `as *const fn(_) -> _` to use it as a pointer + --> $DIR/function-references.rs:9:23 + | +LL | println!("{:p}", &bar); + | ^^^ + +warning: cast `baz` with `as *const fn(_, _) -> _` to use it as a pointer + --> $DIR/function-references.rs:11:23 + | +LL | println!("{:p}", &baz); + | ^^^ + +warning: 3 warnings emitted +