Commit 4613943a authored by Hero Bird's avatar Hero Bird Committed by GitHub

improve some diagnostics for ink! lang (#225)

* [cli] fix bugs in the template

* [lang2/macro] improve some diagnostics for #[ink(constructor|message)]

* [lang2/macro] add a decent ton of new failure tests
parent fe093478
Pipeline #56444 failed with stages
in 27 seconds
......@@ -422,16 +422,17 @@ impl TryFrom<syn::ImplItemMethod> for ir::Function {
// Followed by some checks that are depending on the given function kind:
match kind {
ir::FunctionKind::Constructor(_) => {
let self_arg = sig.self_arg();
if !sig.is_mut() {
bail_span!(
sig.span(),
"constructors in ink! must always be `&mut self`",
bail!(
self_arg,
"#[ink(constructor)] functions must have a `&mut self` receiver",
)
}
if sig.output != syn::ReturnType::Default {
bail!(
sig.output,
"constructors in ink! must have no specified return type",
"#[ink(constructor)] functions must not have a return type",
)
}
}
......@@ -485,7 +486,7 @@ impl TryFrom<syn::Signature> for ir::Signature {
}
if sig.inputs.is_empty() {
bail!(
sig.inputs,
sig,
"`&self` or `&mut self` is mandatory for ink! functions",
)
}
......
......@@ -30,4 +30,11 @@ fn compile_tests() {
t.compile_fail("tests/ui/fail/04-missing-message.rs");
t.compile_fail("tests/ui/fail/05-forbidden-idents.rs");
t.compile_fail("tests/ui/fail/06-access-generated-fields.rs");
t.compile_fail("tests/ui/fail/07-constructor-missing-self.rs");
t.compile_fail("tests/ui/fail/08-constructor-self-ref.rs");
t.compile_fail("tests/ui/fail/09-constructor-self-val.rs");
t.compile_fail("tests/ui/fail/10-async-constructor.rs");
t.compile_fail("tests/ui/fail/11-unsafe-constructor.rs");
t.compile_fail("tests/ui/fail/12-const-constructor.rs");
t.compile_fail("tests/ui/fail/13-abi-constructor.rs");
}
......@@ -2,17 +2,14 @@
use ink_lang2 as ink;
#[ink::contract(
env = DefaultSrmlTypes,
version = "0.1.0",
)]
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
fn new(&mut self) -> Self {}
fn invalid_return(&mut self) -> Self {}
#[ink(message)]
fn noop(&self) {}
......
error: constructors in ink! must have no specified return type
--> $DIR/01-constructor-returns.rs:15:27
error: #[ink(constructor)] functions must not have a return type
--> $DIR/01-constructor-returns.rs:12:38
|
15 | fn new(&mut self) -> Self {}
12 | fn invalid_return(&mut self) -> Self {}
| ^^^^^^^
......@@ -2,10 +2,7 @@
use ink_lang2 as ink;
#[ink::contract(
env = DefaultSrmlTypes,
version = "0.1.0",
)]
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
......
error: ink! contracts require at least one `#[ink(constructor)]`
--> $DIR/02-missing-constructor.rs:9:1
--> $DIR/02-missing-constructor.rs:6:1
|
9 | / mod noop {
10 | | #[ink(storage)]
11 | | struct Noop {}
12 | |
6 | / mod noop {
7 | | #[ink(storage)]
8 | | struct Noop {}
9 | |
... |
16 | | }
17 | | }
13 | | }
14 | | }
| |_^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
fn invalid_self_val() {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: `&self` or `&mut self` is mandatory for ink! functions
--> $DIR/07-constructor-missing-self.rs:12:9
|
12 | fn invalid_self_val() {}
| ^^^^^^^^^^^^^^^^^^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
fn invalid_self_ref(&self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: #[ink(constructor)] functions must have a `&mut self` receiver
--> $DIR/08-constructor-self-ref.rs:12:29
|
12 | fn invalid_self_ref(&self) {}
| ^^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
fn invalid_self_val(self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: #[ink(constructor)] functions must have a `&mut self` receiver
--> $DIR/09-constructor-self-val.rs:12:29
|
12 | fn invalid_self_val(self) {}
| ^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
async fn invalid_return(&mut self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: `async fn` is not supported for ink! functions
--> $DIR/10-async-constructor.rs:12:9
|
12 | async fn invalid_return(&mut self) {}
| ^^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
unsafe fn invalid_return(&mut self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: `unsafe fn` is not supported for ink! functions
--> $DIR/11-unsafe-constructor.rs:12:9
|
12 | unsafe fn invalid_return(&mut self) {}
| ^^^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
const fn invalid_return(&mut self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: `const fn` is not supported for ink! functions
--> $DIR/12-const-constructor.rs:12:9
|
12 | const fn invalid_return(&mut self) {}
| ^^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
extern "C" fn invalid_return(&mut self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: specifying ABI is not allowed in ink! functions
--> $DIR/13-abi-constructor.rs:12:9
|
12 | extern "C" fn invalid_return(&mut self) {}
| ^^^^^^^^^^
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment