Rollup merge of #105552 - mattjperez:add-incompatible-types-note, r=compiler-errors
Add help message about function pointers #102608
This commit is contained in:
commit
c0930c497c
@ -1613,12 +1613,14 @@ pub(crate) fn coerce_inner<'a>(
|
||||
if visitor.ret_exprs.len() > 0 && let Some(expr) = expression {
|
||||
self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
|
||||
}
|
||||
|
||||
let reported = err.emit_unless(unsized_return);
|
||||
|
||||
self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn note_unreachable_loop_return(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
|
@ -81,7 +81,6 @@ pub fn emit_coerce_suggestions(
|
||||
self.annotate_expected_due_to_let_ty(err, expr, error);
|
||||
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
|
||||
self.note_type_is_not_clone(err, expected, expr_ty, expr);
|
||||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
||||
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
|
||||
self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
|
||||
|
@ -926,43 +926,6 @@ pub(in super::super) fn note_internal_mutation_in_method(
|
||||
}
|
||||
}
|
||||
|
||||
pub(in super::super) fn note_need_for_fn_pointer(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) {
|
||||
let (sig, did, substs) = match (&expected.kind(), &found.kind()) {
|
||||
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
|
||||
let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
|
||||
let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
|
||||
if sig1 != sig2 {
|
||||
return;
|
||||
}
|
||||
err.note(
|
||||
"different `fn` items always have unique types, even if their signatures are \
|
||||
the same",
|
||||
);
|
||||
(sig1, *did1, substs1)
|
||||
}
|
||||
(ty::FnDef(did, substs), ty::FnPtr(sig2)) => {
|
||||
let sig1 = self.tcx.bound_fn_sig(*did).subst(self.tcx, substs);
|
||||
if sig1 != *sig2 {
|
||||
return;
|
||||
}
|
||||
(sig1, *did, substs)
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
err.help(&format!("change the expected type to be function pointer `{}`", sig));
|
||||
err.help(&format!(
|
||||
"if the expected type is due to type inference, cast the expected `fn` to a function \
|
||||
pointer: `{} as {}`",
|
||||
self.tcx.def_path_str_with_substs(did, substs),
|
||||
sig
|
||||
));
|
||||
}
|
||||
|
||||
// Instantiates the given path, which must refer to an item with the given
|
||||
// number of type parameters and type.
|
||||
#[instrument(skip(self, span), level = "debug")]
|
||||
|
@ -1841,6 +1841,7 @@ enum Similar<'tcx> {
|
||||
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
||||
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
|
||||
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
|
||||
self.suggest_function_pointers(cause, span, &exp_found, diag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2585,7 +2586,7 @@ pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool {
|
||||
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
|
||||
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
|
||||
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
|
||||
pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
||||
pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
|
||||
let (a, b) = self.resolve_vars_if_possible((a, b));
|
||||
SameTypeModuloInfer(self).relate(a, b).is_ok()
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
StatementAsExpression,
|
||||
};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self as ty, Ty, TypeVisitable};
|
||||
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
|
||||
use crate::errors::SuggAddLetForLetChains;
|
||||
@ -351,6 +351,82 @@ pub(super) fn suggest_as_ref_where_appropriate(
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn suggest_function_pointers(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
span: Span,
|
||||
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
|
||||
diag: &mut Diagnostic,
|
||||
) {
|
||||
debug!("suggest_function_pointers(cause={:?}, exp_found={:?})", cause, exp_found);
|
||||
let ty::error::ExpectedFound { expected, found } = exp_found;
|
||||
let expected_inner = expected.peel_refs();
|
||||
let found_inner = found.peel_refs();
|
||||
if !expected_inner.is_fn() || !found_inner.is_fn() {
|
||||
return;
|
||||
}
|
||||
match (&expected_inner.kind(), &found_inner.kind()) {
|
||||
(ty::FnPtr(sig), ty::FnDef(did, substs)) => {
|
||||
let expected_sig = &(self.normalize_fn_sig)(*sig);
|
||||
let found_sig =
|
||||
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did).subst(self.tcx, substs));
|
||||
|
||||
let fn_name = self.tcx.def_path_str_with_substs(*did, substs);
|
||||
|
||||
if !self.same_type_modulo_infer(*found_sig, *expected_sig)
|
||||
|| !sig.is_suggestable(self.tcx, true)
|
||||
|| ty::util::is_intrinsic(self.tcx, *did)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let (msg, sugg) = match (expected.is_ref(), found.is_ref()) {
|
||||
(true, false) => {
|
||||
let msg = "consider using a reference";
|
||||
let sug = format!("&{fn_name}");
|
||||
(msg, sug)
|
||||
}
|
||||
(false, true) => {
|
||||
let msg = "consider removing the reference";
|
||||
let sug = format!("{fn_name}");
|
||||
(msg, sug)
|
||||
}
|
||||
(true, true) => {
|
||||
diag.note("fn items are distinct from fn pointers");
|
||||
let msg = "consider casting to a fn pointer";
|
||||
let sug = format!("&({fn_name} as {sig})");
|
||||
(msg, sug)
|
||||
}
|
||||
(false, false) => {
|
||||
diag.note("fn items are distinct from fn pointers");
|
||||
let msg = "consider casting to a fn pointer";
|
||||
let sug = format!("{fn_name} as {sig}");
|
||||
(msg, sug)
|
||||
}
|
||||
};
|
||||
diag.span_suggestion(span, msg, &sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
|
||||
let expected_sig =
|
||||
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1));
|
||||
let found_sig =
|
||||
&(self.normalize_fn_sig)(self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2));
|
||||
|
||||
if self.same_type_modulo_infer(*found_sig, *expected_sig) {
|
||||
diag.note(
|
||||
"different fn items have unique types, even if their signatures are the same",
|
||||
);
|
||||
}
|
||||
}
|
||||
(ty::FnDef(_, _), ty::FnPtr(_)) => {
|
||||
diag.note("fn items are distinct from fn pointers");
|
||||
}
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
|
||||
if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
|
||||
(expected.kind(), found.kind())
|
||||
|
@ -19,6 +19,7 @@ LL | let x = f == g;
|
||||
|
|
||||
= note: expected fn item `fn() {f}`
|
||||
found fn item `fn() {g}`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,13 +1,22 @@
|
||||
// Test that the types of distinct fn items are not compatible by
|
||||
// default. See also `run-pass/fn-item-type-*.rs`.
|
||||
|
||||
fn foo<T>(x: isize) -> isize { x * 2 }
|
||||
fn bar<T>(x: isize) -> isize { x * 4 }
|
||||
fn foo<T>(x: isize) -> isize {
|
||||
x * 2
|
||||
}
|
||||
fn bar<T>(x: isize) -> isize {
|
||||
x * 4
|
||||
}
|
||||
|
||||
fn eq<T>(x: T, y: T) {}
|
||||
|
||||
trait Foo { fn foo() { /* this is a default fn */ } }
|
||||
impl<T> Foo for T { /* `foo` is still default here */ }
|
||||
trait Foo {
|
||||
fn foo() { /* this is a default fn */
|
||||
}
|
||||
}
|
||||
impl<T> Foo for T {
|
||||
/* `foo` is still default here */
|
||||
}
|
||||
|
||||
fn main() {
|
||||
eq(foo::<u8>, bar::<u8>);
|
||||
@ -15,39 +24,29 @@ fn main() {
|
||||
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
//~| found fn item `fn(_) -> _ {bar::<u8>}`
|
||||
//~| expected fn item, found a different fn item
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expected type to be function pointer
|
||||
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
|
||||
//~| different fn items have unique types, even if their signatures are the same
|
||||
|
||||
eq(foo::<u8>, foo::<i8>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `u8`, found `i8`
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expected type to be function pointer
|
||||
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
|
||||
//~| different fn items have unique types, even if their signatures are the same
|
||||
|
||||
eq(bar::<String>, bar::<Vec<u8>>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
|
||||
//~| expected struct `String`, found struct `Vec`
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expected type to be function pointer
|
||||
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
|
||||
//~| different fn items have unique types, even if their signatures are the same
|
||||
|
||||
// Make sure we distinguish between trait methods correctly.
|
||||
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `u8`, found `u16`
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expected type to be function pointer
|
||||
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
|
||||
//~| different fn items have unique types, even if their signatures are the same
|
||||
|
||||
eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
|
||||
//~^ ERROR mismatched types
|
||||
//~| found fn pointer `fn(_) -> _`
|
||||
//~| expected fn item, found fn pointer
|
||||
//~| change the expected type to be function pointer
|
||||
//~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
|
||||
|
||||
eq(foo::<u8> as fn(isize) -> isize, bar::<u8>); // ok!
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:13:19
|
||||
--> $DIR/fn-item-type.rs:22:19
|
||||
|
|
||||
LL | eq(foo::<u8>, bar::<u8>);
|
||||
| -- ^^^^^^^^^ expected fn item, found a different fn item
|
||||
@ -8,17 +8,15 @@ LL | eq(foo::<u8>, bar::<u8>);
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
found fn item `fn(_) -> _ {bar::<u8>}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expected type to be function pointer `fn(isize) -> isize`
|
||||
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
note: function defined here
|
||||
--> $DIR/fn-item-type.rs:7:4
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:22:19
|
||||
--> $DIR/fn-item-type.rs:29:19
|
||||
|
|
||||
LL | eq(foo::<u8>, foo::<i8>);
|
||||
| -- ^^^^^^^^^ expected `u8`, found `i8`
|
||||
@ -27,17 +25,15 @@ LL | eq(foo::<u8>, foo::<i8>);
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
found fn item `fn(_) -> _ {foo::<i8>}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expected type to be function pointer `fn(isize) -> isize`
|
||||
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
note: function defined here
|
||||
--> $DIR/fn-item-type.rs:7:4
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:29:23
|
||||
--> $DIR/fn-item-type.rs:34:23
|
||||
|
|
||||
LL | eq(bar::<String>, bar::<Vec<u8>>);
|
||||
| -- ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
|
||||
@ -46,17 +42,15 @@ LL | eq(bar::<String>, bar::<Vec<u8>>);
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {bar::<String>}`
|
||||
found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expected type to be function pointer `fn(isize) -> isize`
|
||||
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar::<String> as fn(isize) -> isize`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
note: function defined here
|
||||
--> $DIR/fn-item-type.rs:7:4
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:38:26
|
||||
--> $DIR/fn-item-type.rs:41:26
|
||||
|
|
||||
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||
| -- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
|
||||
@ -65,17 +59,15 @@ LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||
|
|
||||
= note: expected fn item `fn() {<u8 as Foo>::foo}`
|
||||
found fn item `fn() {<u16 as Foo>::foo}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expected type to be function pointer `fn()`
|
||||
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `<u8 as Foo>::foo as fn()`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
note: function defined here
|
||||
--> $DIR/fn-item-type.rs:7:4
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ ----
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:45:19
|
||||
--> $DIR/fn-item-type.rs:46:19
|
||||
|
|
||||
LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
|
||||
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
|
||||
@ -84,10 +76,9 @@ LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
found fn pointer `fn(_) -> _`
|
||||
= help: change the expected type to be function pointer `fn(isize) -> isize`
|
||||
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
|
||||
= note: fn items are distinct from fn pointers
|
||||
note: function defined here
|
||||
--> $DIR/fn-item-type.rs:7:4
|
||||
--> $DIR/fn-item-type.rs:11:4
|
||||
|
|
||||
LL | fn eq<T>(x: T, y: T) {}
|
||||
| ^^ ----
|
||||
|
56
tests/ui/fn/fn-pointer-mismatch.rs
Normal file
56
tests/ui/fn/fn-pointer-mismatch.rs
Normal file
@ -0,0 +1,56 @@
|
||||
fn foo(x: u32) -> u32 {
|
||||
x * 2
|
||||
}
|
||||
|
||||
fn bar(x: u32) -> u32 {
|
||||
x * 3
|
||||
}
|
||||
|
||||
// original example from Issue #102608
|
||||
fn foobar(n: u32) -> u32 {
|
||||
let g = if n % 2 == 0 { &foo } else { &bar };
|
||||
//~^ ERROR `if` and `else` have incompatible types
|
||||
//~| different fn items have unique types, even if their signatures are the same
|
||||
g(n)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(foobar(7), 21);
|
||||
assert_eq!(foobar(8), 16);
|
||||
|
||||
// general mismatch of fn item types
|
||||
let mut a = foo;
|
||||
a = bar;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected fn item `fn(_) -> _ {foo}`
|
||||
//~| found fn item `fn(_) -> _ {bar}`
|
||||
//~| different fn items have unique types, even if their signatures are the same
|
||||
|
||||
// display note even when boxed
|
||||
let mut b = Box::new(foo);
|
||||
b = Box::new(bar);
|
||||
//~^ ERROR mismatched types
|
||||
//~| different fn items have unique types, even if their signatures are the same
|
||||
|
||||
// suggest removing reference
|
||||
let c: fn(u32) -> u32 = &foo;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected fn pointer `fn(u32) -> u32`
|
||||
//~| found reference `&fn(u32) -> u32 {foo}`
|
||||
|
||||
// suggest using reference
|
||||
let d: &fn(u32) -> u32 = foo;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected reference `&fn(u32) -> u32`
|
||||
//~| found fn item `fn(u32) -> u32 {foo}`
|
||||
|
||||
// suggest casting with reference
|
||||
let e: &fn(u32) -> u32 = &foo;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected reference `&fn(u32) -> u32`
|
||||
//~| found reference `&fn(u32) -> u32 {foo}`
|
||||
|
||||
// OK
|
||||
let mut z: fn(u32) -> u32 = foo as fn(u32) -> u32;
|
||||
z = bar;
|
||||
}
|
81
tests/ui/fn/fn-pointer-mismatch.stderr
Normal file
81
tests/ui/fn/fn-pointer-mismatch.stderr
Normal file
@ -0,0 +1,81 @@
|
||||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/fn-pointer-mismatch.rs:11:43
|
||||
|
|
||||
LL | let g = if n % 2 == 0 { &foo } else { &bar };
|
||||
| ---- ^^^^ expected fn item, found a different fn item
|
||||
| |
|
||||
| expected because of this
|
||||
|
|
||||
= note: expected reference `&fn(u32) -> u32 {foo}`
|
||||
found reference `&fn(u32) -> u32 {bar}`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-pointer-mismatch.rs:23:9
|
||||
|
|
||||
LL | let mut a = foo;
|
||||
| --- expected due to this value
|
||||
LL | a = bar;
|
||||
| ^^^ expected fn item, found a different fn item
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo}`
|
||||
found fn item `fn(_) -> _ {bar}`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-pointer-mismatch.rs:31:18
|
||||
|
|
||||
LL | b = Box::new(bar);
|
||||
| -------- ^^^ expected fn item, found a different fn item
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo}`
|
||||
found fn item `fn(_) -> _ {bar}`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
note: associated function defined here
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-pointer-mismatch.rs:36:29
|
||||
|
|
||||
LL | let c: fn(u32) -> u32 = &foo;
|
||||
| -------------- ^^^^
|
||||
| | |
|
||||
| | expected fn pointer, found reference
|
||||
| | help: consider removing the reference: `foo`
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `fn(u32) -> u32`
|
||||
found reference `&fn(u32) -> u32 {foo}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-pointer-mismatch.rs:42:30
|
||||
|
|
||||
LL | let d: &fn(u32) -> u32 = foo;
|
||||
| --------------- ^^^
|
||||
| | |
|
||||
| | expected `&fn(u32) -> u32`, found fn item
|
||||
| | help: consider using a reference: `&foo`
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&fn(u32) -> u32`
|
||||
found fn item `fn(u32) -> u32 {foo}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-pointer-mismatch.rs:48:30
|
||||
|
|
||||
LL | let e: &fn(u32) -> u32 = &foo;
|
||||
| --------------- ^^^^
|
||||
| | |
|
||||
| | expected fn pointer, found fn item
|
||||
| | help: consider casting to a fn pointer: `&(foo as fn(u32) -> u32)`
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&fn(u32) -> u32`
|
||||
found reference `&fn(u32) -> u32 {foo}`
|
||||
= note: fn items are distinct from fn pointers
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -23,9 +23,7 @@ LL | std::intrinsics::unlikely,
|
||||
|
|
||||
= note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}`
|
||||
found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expected type to be function pointer `extern "rust-intrinsic" fn(bool) -> bool`
|
||||
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `likely as extern "rust-intrinsic" fn(bool) -> bool`
|
||||
= note: different fn items have unique types, even if their signatures are the same
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -5,12 +5,15 @@ LL | #[target_feature(enable = "sse2")]
|
||||
| ---------------------------------- `#[target_feature]` added here
|
||||
...
|
||||
LL | let foo: fn() = foo;
|
||||
| ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
|
||||
| |
|
||||
| ---- ^^^
|
||||
| | |
|
||||
| | cannot coerce functions with `#[target_feature]` to safe function pointers
|
||||
| | help: consider casting to a fn pointer: `foo as fn()`
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn item `fn() {foo}`
|
||||
= note: fn items are distinct from fn pointers
|
||||
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -5,12 +5,15 @@ LL | #[target_feature(enable = "sse2")]
|
||||
| ---------------------------------- `#[target_feature]` added here
|
||||
...
|
||||
LL | let foo: fn() = foo;
|
||||
| ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
|
||||
| |
|
||||
| ---- ^^^
|
||||
| | |
|
||||
| | cannot coerce functions with `#[target_feature]` to safe function pointers
|
||||
| | help: consider casting to a fn pointer: `foo as fn()`
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn item `fn() {foo}`
|
||||
= note: fn items are distinct from fn pointers
|
||||
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -2,10 +2,14 @@ error[E0308]: mismatched types
|
||||
--> $DIR/static-reference-to-fn-1.rs:17:15
|
||||
|
|
||||
LL | func: &foo,
|
||||
| ^^^^ expected fn pointer, found fn item
|
||||
| ^^^^
|
||||
| |
|
||||
| expected fn pointer, found fn item
|
||||
| help: consider casting to a fn pointer: `&(foo as fn() -> Option<isize>)`
|
||||
|
|
||||
= note: expected reference `&fn() -> Option<isize>`
|
||||
found reference `&fn() -> Option<isize> {foo}`
|
||||
= note: fn items are distinct from fn pointers
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user