mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 03:38:29 +00:00
Add basic checks for well-formedness of fn
/fn_mut
lang items
This commit is contained in:
parent
a0648eab36
commit
4337089098
@ -246,12 +246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
if borrow {
|
if borrow {
|
||||||
// Check for &self vs &mut self in the method signature. Since this is either
|
// Check for &self vs &mut self in the method signature. Since this is either
|
||||||
// the Fn or FnMut trait, it should be one of those.
|
// the Fn or FnMut trait, it should be one of those.
|
||||||
let (region, mutbl) =
|
let (region, mutbl) = if let ty::Ref(r, _, mutbl) =
|
||||||
if let ty::Ref(r, _, mutbl) = method.sig.inputs()[0].kind() {
|
method.sig.inputs()[0].kind()
|
||||||
(r, mutbl)
|
{
|
||||||
} else {
|
(r, mutbl)
|
||||||
span_bug!(call_expr.span, "input to call/call_mut is not a ref?");
|
} else {
|
||||||
};
|
// The `fn`/`fn_mut` lang item is ill-formed, which should have
|
||||||
|
// caused an error elsewhere.
|
||||||
|
self.tcx
|
||||||
|
.sess
|
||||||
|
.delay_span_bug(call_expr.span, "input to call/call_mut is not a ref?");
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
let mutbl = match mutbl {
|
let mutbl = match mutbl {
|
||||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
hir::Mutability::Not => AutoBorrowMutability::Not,
|
||||||
|
@ -200,6 +200,40 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||||||
};
|
};
|
||||||
check_object_unsafe_self_trait_by_name(tcx, &trait_item);
|
check_object_unsafe_self_trait_by_name(tcx, &trait_item);
|
||||||
check_associated_item(tcx, trait_item.hir_id(), span, method_sig);
|
check_associated_item(tcx, trait_item.hir_id(), span, method_sig);
|
||||||
|
|
||||||
|
let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
|
||||||
|
let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
|
||||||
|
if [tcx.lang_items().fn_trait(), tcx.lang_items().fn_mut_trait()]
|
||||||
|
.contains(&Some(encl_trait.def_id.to_def_id()))
|
||||||
|
&& trait_item.ident.name.to_ident_string() == "call"
|
||||||
|
{
|
||||||
|
// We are looking at the `call` function of the `fn` or `fn_mut` lang item.
|
||||||
|
// Do some rudimentary sanity checking to avoid an ICE later (issue #83471).
|
||||||
|
if let Some(method_sig @ hir::FnSig { decl, .. }) = method_sig {
|
||||||
|
if let &[self_ty, _] = &decl.inputs {
|
||||||
|
if !matches!(self_ty.kind, hir::TyKind::Rptr(_, _)) {
|
||||||
|
tcx.sess.struct_span_err(
|
||||||
|
self_ty.span,
|
||||||
|
"first argument of `call` in `fn`/`fn_mut` lang item must be a reference",
|
||||||
|
).emit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tcx.sess
|
||||||
|
.struct_span_err(
|
||||||
|
method_sig.span,
|
||||||
|
"`call` function in `fn`/`fn_mut` lang item takes exactly two arguments",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tcx.sess
|
||||||
|
.struct_span_err(
|
||||||
|
trait_item.span,
|
||||||
|
"`call` trait item in `fn`/`fn_mut` lang item must be a function",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
|
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
|
||||||
|
27
src/test/ui/lang-items/fn-fn_mut-call-ill-formed.rs
Normal file
27
src/test/ui/lang-items/fn-fn_mut-call-ill-formed.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Make sure that an error is reported if the `call` function of the
|
||||||
|
// `fn`/`fn_mut` lang item is grossly ill-formed.
|
||||||
|
|
||||||
|
#![feature(lang_items)]
|
||||||
|
#![feature(no_core)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "fn"]
|
||||||
|
trait MyFn<T> {
|
||||||
|
const call: i32 = 42;
|
||||||
|
//~^ ERROR: `call` trait item in `fn`/`fn_mut` lang item must be a function
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "fn_mut"]
|
||||||
|
trait MyFnMut<T> {
|
||||||
|
fn call(i: i32, j: i32) -> i32 { i + j }
|
||||||
|
//~^ ERROR: first argument of `call` in `fn`/`fn_mut` lang item must be a reference
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = || 42;
|
||||||
|
a();
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
let mut b = || { i += 1; };
|
||||||
|
b();
|
||||||
|
}
|
14
src/test/ui/lang-items/fn-fn_mut-call-ill-formed.stderr
Normal file
14
src/test/ui/lang-items/fn-fn_mut-call-ill-formed.stderr
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
error: `call` trait item in `fn`/`fn_mut` lang item must be a function
|
||||||
|
--> $DIR/fn-fn_mut-call-ill-formed.rs:10:5
|
||||||
|
|
|
||||||
|
LL | const call: i32 = 42;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: first argument of `call` in `fn`/`fn_mut` lang item must be a reference
|
||||||
|
--> $DIR/fn-fn_mut-call-ill-formed.rs:16:16
|
||||||
|
|
|
||||||
|
LL | fn call(i: i32, j: i32) -> i32 { i + j }
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
23
src/test/ui/lang-items/issue-83471.rs
Normal file
23
src/test/ui/lang-items/issue-83471.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Regression test for the ICE reported in issue #83471.
|
||||||
|
|
||||||
|
#![crate_type="lib"]
|
||||||
|
#![feature(no_core)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
//~^ ERROR: language items are subject to change [E0658]
|
||||||
|
trait Sized {}
|
||||||
|
|
||||||
|
#[lang = "fn"]
|
||||||
|
//~^ ERROR: language items are subject to change [E0658]
|
||||||
|
//~| ERROR: `fn` language item must be applied to a trait with 1 generic argument
|
||||||
|
trait Fn {
|
||||||
|
fn call(export_name);
|
||||||
|
//~^ ERROR: expected type
|
||||||
|
//~| WARNING: anonymous parameters are deprecated
|
||||||
|
//~| WARNING: this is accepted in the current edition
|
||||||
|
}
|
||||||
|
fn call_through_fn_trait() {
|
||||||
|
a()
|
||||||
|
//~^ ERROR: cannot find function
|
||||||
|
}
|
51
src/test/ui/lang-items/issue-83471.stderr
Normal file
51
src/test/ui/lang-items/issue-83471.stderr
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
error[E0573]: expected type, found built-in attribute `export_name`
|
||||||
|
--> $DIR/issue-83471.rs:15:13
|
||||||
|
|
|
||||||
|
LL | fn call(export_name);
|
||||||
|
| ^^^^^^^^^^^ not a type
|
||||||
|
|
||||||
|
error[E0425]: cannot find function `a` in this scope
|
||||||
|
--> $DIR/issue-83471.rs:21:5
|
||||||
|
|
|
||||||
|
LL | a()
|
||||||
|
| ^ not found in this scope
|
||||||
|
|
||||||
|
error[E0658]: language items are subject to change
|
||||||
|
--> $DIR/issue-83471.rs:7:1
|
||||||
|
|
|
||||||
|
LL | #[lang = "sized"]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(lang_items)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: language items are subject to change
|
||||||
|
--> $DIR/issue-83471.rs:11:1
|
||||||
|
|
|
||||||
|
LL | #[lang = "fn"]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(lang_items)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
warning: anonymous parameters are deprecated and will be removed in the next edition.
|
||||||
|
--> $DIR/issue-83471.rs:15:13
|
||||||
|
|
|
||||||
|
LL | fn call(export_name);
|
||||||
|
| ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name`
|
||||||
|
|
|
||||||
|
= note: `#[warn(anonymous_parameters)]` on by default
|
||||||
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||||
|
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
|
||||||
|
|
||||||
|
error[E0718]: `fn` language item must be applied to a trait with 1 generic argument
|
||||||
|
--> $DIR/issue-83471.rs:11:1
|
||||||
|
|
|
||||||
|
LL | #[lang = "fn"]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | trait Fn {
|
||||||
|
| - this trait has 0 generic arguments
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0425, E0573, E0658, E0718.
|
||||||
|
For more information about an error, try `rustc --explain E0425`.
|
Loading…
Reference in New Issue
Block a user