1
Fork 0

Added suggestion to function_item_references lint and fixed warning message

Also updated tests accordingly and tweaked some wording in the lint declaration.
This commit is contained in:
Ayrton 2020-10-27 09:00:19 -04:00
parent 935fc3642a
commit c791c64e84
4 changed files with 102 additions and 95 deletions

View file

@ -1,3 +1,4 @@
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*; use rustc_middle::mir::*;
@ -183,15 +184,21 @@ impl<'a, 'tcx> FunctionItemRefChecker<'a, 'tcx> {
let variadic = if fn_sig.c_variadic() { ", ..." } else { "" }; let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" }; let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" };
self.tcx.struct_span_lint_hir(FUNCTION_ITEM_REFERENCES, lint_root, span, |lint| { self.tcx.struct_span_lint_hir(FUNCTION_ITEM_REFERENCES, lint_root, span, |lint| {
lint.build(&format!( lint.build("taking a reference to a function item does not give a function pointer")
"cast `{}` with `as {}{}fn({}{}){}` to obtain a function pointer", .span_suggestion(
span,
&format!("cast `{}` to obtain a function pointer", ident),
format!(
"{} as {}{}fn({}{}){}",
ident, ident,
unsafety, unsafety,
abi, abi,
vec!["_"; num_args].join(", "), vec!["_"; num_args].join(", "),
variadic, variadic,
ret, ret,
)) ),
Applicability::Unspecified,
)
.emit(); .emit();
}); });
} }

View file

@ -2674,7 +2674,7 @@ declare_lint! {
/// arguments bound by [`fmt::Pointer`] or transmuted. /// arguments bound by [`fmt::Pointer`] or transmuted.
pub FUNCTION_ITEM_REFERENCES, pub FUNCTION_ITEM_REFERENCES,
Warn, Warn,
"suggest casting functions to pointers when attempting to take references", "suggest casting to a function pointer when attempting to take references to function items",
} }
declare_lint! { declare_lint! {

View file

@ -38,7 +38,7 @@ fn _format_assoc_item<T: HasItem>(data: T, f: &mut Formatter) -> std::fmt::Resul
fn _call_pointer_fmt(f: &mut Formatter) -> std::fmt::Result { fn _call_pointer_fmt(f: &mut Formatter) -> std::fmt::Result {
let zst_ref = &foo; let zst_ref = &foo;
Pointer::fmt(&zst_ref, f) Pointer::fmt(&zst_ref, f)
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
} }
fn main() { fn main() {
@ -75,47 +75,47 @@ fn main() {
//potential ways to incorrectly try printing function pointers //potential ways to incorrectly try printing function pointers
println!("{:p}", &foo); println!("{:p}", &foo);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
print!("{:p}", &foo); print!("{:p}", &foo);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
format!("{:p}", &foo); format!("{:p}", &foo);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &foo as *const _); println!("{:p}", &foo as *const _);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", zst_ref); println!("{:p}", zst_ref);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", cast_zst_ptr); println!("{:p}", cast_zst_ptr);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", coerced_zst_ptr); println!("{:p}", coerced_zst_ptr);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &fn_item); println!("{:p}", &fn_item);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", indirect_ref); println!("{:p}", indirect_ref);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &nop); println!("{:p}", &nop);
//~^ WARNING cast `nop` with `as fn()` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &bar); println!("{:p}", &bar);
//~^ WARNING cast `bar` with `as fn(_) -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &baz); println!("{:p}", &baz);
//~^ WARNING cast `baz` with `as fn(_, _) -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &unsafe_fn); println!("{:p}", &unsafe_fn);
//~^ WARNING cast `unsafe_fn` with `as unsafe fn()` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &c_fn); println!("{:p}", &c_fn);
//~^ WARNING cast `c_fn` with `as extern "C" fn()` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &unsafe_c_fn); println!("{:p}", &unsafe_c_fn);
//~^ WARNING cast `unsafe_c_fn` with `as unsafe extern "C" fn()` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &variadic); println!("{:p}", &variadic);
//~^ WARNING cast `variadic` with `as unsafe extern "C" fn(_, ...)` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p}", &std::env::var::<String>); println!("{:p}", &std::env::var::<String>);
//~^ WARNING cast `var` with `as fn(_) -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
println!("{:p} {:p} {:p}", &nop, &foo, &bar); println!("{:p} {:p} {:p}", &nop, &foo, &bar);
//~^ WARNING cast `nop` with `as fn()` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
//~^^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer
//~^^^ WARNING cast `bar` with `as fn(_) -> _` to obtain a function pointer //~^^^ WARNING taking a reference to a function item does not give a function pointer
//using a function reference to call a function shouldn't lint //using a function reference to call a function shouldn't lint
(&bar)(1); (&bar)(1);
@ -128,10 +128,10 @@ fn main() {
unsafe { unsafe {
//potential ways to incorrectly try transmuting function pointers //potential ways to incorrectly try transmuting function pointers
std::mem::transmute::<_, usize>(&foo); std::mem::transmute::<_, usize>(&foo);
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); std::mem::transmute::<_, (usize, usize)>((&foo, &bar));
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
//~^^ WARNING cast `bar` with `as fn(_) -> _` to obtain a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer
//the correct way to transmute function pointers //the correct way to transmute function pointers
std::mem::transmute::<_, usize>(foo as fn() -> u32); std::mem::transmute::<_, usize>(foo as fn() -> u32);
@ -140,12 +140,12 @@ fn main() {
//function references as arguments required to be bound by std::fmt::Pointer should lint //function references as arguments required to be bound by std::fmt::Pointer should lint
print_ptr(&bar); print_ptr(&bar);
//~^ WARNING cast `bar` with `as fn(_) -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
bound_by_ptr_trait(&bar); bound_by_ptr_trait(&bar);
//~^ WARNING cast `bar` with `as fn(_) -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
bound_by_ptr_trait_tuple((&foo, &bar)); bound_by_ptr_trait_tuple((&foo, &bar));
//~^ WARNING cast `foo` with `as fn() -> _` to obtain a function pointer //~^ WARNING taking a reference to a function item does not give a function pointer
//~^^ WARNING cast `bar` with `as fn(_) -> _` to obtain a function pointer //~^^ WARNING taking a reference to a function item does not give a function pointer
implicit_ptr_trait(&bar); // ignore implicit_ptr_trait(&bar); // ignore
//correct ways to pass function pointers as arguments bound by std::fmt::Pointer //correct ways to pass function pointers as arguments bound by std::fmt::Pointer

View file

@ -1,8 +1,8 @@
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:40:18 --> $DIR/function-item-references.rs:40:18
| |
LL | Pointer::fmt(&zst_ref, f) LL | Pointer::fmt(&zst_ref, f)
| ^^^^^^^^ | ^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/function-item-references.rs:3:9 --> $DIR/function-item-references.rs:3:9
@ -10,167 +10,167 @@ note: the lint level is defined here
LL | #![warn(function_item_references)] LL | #![warn(function_item_references)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:77:22 --> $DIR/function-item-references.rs:77:22
| |
LL | println!("{:p}", &foo); LL | println!("{:p}", &foo);
| ^^^^ | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:79:20 --> $DIR/function-item-references.rs:79:20
| |
LL | print!("{:p}", &foo); LL | print!("{:p}", &foo);
| ^^^^ | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:81:21 --> $DIR/function-item-references.rs:81:21
| |
LL | format!("{:p}", &foo); LL | format!("{:p}", &foo);
| ^^^^ | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:84:22 --> $DIR/function-item-references.rs:84:22
| |
LL | println!("{:p}", &foo as *const _); LL | println!("{:p}", &foo as *const _);
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:86:22 --> $DIR/function-item-references.rs:86:22
| |
LL | println!("{:p}", zst_ref); LL | println!("{:p}", zst_ref);
| ^^^^^^^ | ^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:88:22 --> $DIR/function-item-references.rs:88:22
| |
LL | println!("{:p}", cast_zst_ptr); LL | println!("{:p}", cast_zst_ptr);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:90:22 --> $DIR/function-item-references.rs:90:22
| |
LL | println!("{:p}", coerced_zst_ptr); LL | println!("{:p}", coerced_zst_ptr);
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:93:22 --> $DIR/function-item-references.rs:93:22
| |
LL | println!("{:p}", &fn_item); LL | println!("{:p}", &fn_item);
| ^^^^^^^^ | ^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:95:22 --> $DIR/function-item-references.rs:95:22
| |
LL | println!("{:p}", indirect_ref); LL | println!("{:p}", indirect_ref);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `nop` with `as fn()` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:98:22 --> $DIR/function-item-references.rs:98:22
| |
LL | println!("{:p}", &nop); LL | println!("{:p}", &nop);
| ^^^^ | ^^^^ help: cast `nop` to obtain a function pointer: `nop as fn()`
warning: cast `bar` with `as fn(_) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:100:22 --> $DIR/function-item-references.rs:100:22
| |
LL | println!("{:p}", &bar); LL | println!("{:p}", &bar);
| ^^^^ | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _`
warning: cast `baz` with `as fn(_, _) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:102:22 --> $DIR/function-item-references.rs:102:22
| |
LL | println!("{:p}", &baz); LL | println!("{:p}", &baz);
| ^^^^ | ^^^^ help: cast `baz` to obtain a function pointer: `baz as fn(_, _) -> _`
warning: cast `unsafe_fn` with `as unsafe fn()` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:104:22 --> $DIR/function-item-references.rs:104:22
| |
LL | println!("{:p}", &unsafe_fn); LL | println!("{:p}", &unsafe_fn);
| ^^^^^^^^^^ | ^^^^^^^^^^ help: cast `unsafe_fn` to obtain a function pointer: `unsafe_fn as unsafe fn()`
warning: cast `c_fn` with `as extern "C" fn()` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:106:22 --> $DIR/function-item-references.rs:106:22
| |
LL | println!("{:p}", &c_fn); LL | println!("{:p}", &c_fn);
| ^^^^^ | ^^^^^ help: cast `c_fn` to obtain a function pointer: `c_fn as extern "C" fn()`
warning: cast `unsafe_c_fn` with `as unsafe extern "C" fn()` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:108:22 --> $DIR/function-item-references.rs:108:22
| |
LL | println!("{:p}", &unsafe_c_fn); LL | println!("{:p}", &unsafe_c_fn);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: cast `unsafe_c_fn` to obtain a function pointer: `unsafe_c_fn as unsafe extern "C" fn()`
warning: cast `variadic` with `as unsafe extern "C" fn(_, ...)` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:110:22 --> $DIR/function-item-references.rs:110:22
| |
LL | println!("{:p}", &variadic); LL | println!("{:p}", &variadic);
| ^^^^^^^^^ | ^^^^^^^^^ help: cast `variadic` to obtain a function pointer: `variadic as unsafe extern "C" fn(_, ...)`
warning: cast `var` with `as fn(_) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:112:22 --> $DIR/function-item-references.rs:112:22
| |
LL | println!("{:p}", &std::env::var::<String>); LL | println!("{:p}", &std::env::var::<String>);
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `var` to obtain a function pointer: `var as fn(_) -> _`
warning: cast `nop` with `as fn()` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:115:32 --> $DIR/function-item-references.rs:115:32
| |
LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar);
| ^^^^ | ^^^^ help: cast `nop` to obtain a function pointer: `nop as fn()`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:115:38 --> $DIR/function-item-references.rs:115:38
| |
LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar);
| ^^^^ | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `bar` with `as fn(_) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:115:44 --> $DIR/function-item-references.rs:115:44
| |
LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar);
| ^^^^ | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:130:41 --> $DIR/function-item-references.rs:130:41
| |
LL | std::mem::transmute::<_, usize>(&foo); LL | std::mem::transmute::<_, usize>(&foo);
| ^^^^ | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:132:50 --> $DIR/function-item-references.rs:132:50
| |
LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar));
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: cast `bar` with `as fn(_) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:132:50 --> $DIR/function-item-references.rs:132:50
| |
LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar));
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _`
warning: cast `bar` with `as fn(_) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:142:15 --> $DIR/function-item-references.rs:142:15
| |
LL | print_ptr(&bar); LL | print_ptr(&bar);
| ^^^^ | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _`
warning: cast `bar` with `as fn(_) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:144:24 --> $DIR/function-item-references.rs:144:24
| |
LL | bound_by_ptr_trait(&bar); LL | bound_by_ptr_trait(&bar);
| ^^^^ | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _`
warning: cast `bar` with `as fn(_) -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:146:30 --> $DIR/function-item-references.rs:146:30
| |
LL | bound_by_ptr_trait_tuple((&foo, &bar)); LL | bound_by_ptr_trait_tuple((&foo, &bar));
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _`
warning: cast `foo` with `as fn() -> _` to obtain a function pointer warning: taking a reference to a function item does not give a function pointer
--> $DIR/function-item-references.rs:146:30 --> $DIR/function-item-references.rs:146:30
| |
LL | bound_by_ptr_trait_tuple((&foo, &bar)); LL | bound_by_ptr_trait_tuple((&foo, &bar));
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _`
warning: 28 warnings emitted warning: 28 warnings emitted