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 { ...@@ -422,16 +422,17 @@ impl TryFrom<syn::ImplItemMethod> for ir::Function {
// Followed by some checks that are depending on the given function kind: // Followed by some checks that are depending on the given function kind:
match kind { match kind {
ir::FunctionKind::Constructor(_) => { ir::FunctionKind::Constructor(_) => {
let self_arg = sig.self_arg();
if !sig.is_mut() { if !sig.is_mut() {
bail_span!( bail!(
sig.span(), self_arg,
"constructors in ink! must always be `&mut self`", "#[ink(constructor)] functions must have a `&mut self` receiver",
) )
} }
if sig.output != syn::ReturnType::Default { if sig.output != syn::ReturnType::Default {
bail!( bail!(
sig.output, 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 { ...@@ -485,7 +486,7 @@ impl TryFrom<syn::Signature> for ir::Signature {
} }
if sig.inputs.is_empty() { if sig.inputs.is_empty() {
bail!( bail!(
sig.inputs, sig,
"`&self` or `&mut self` is mandatory for ink! functions", "`&self` or `&mut self` is mandatory for ink! functions",
) )
} }
......
...@@ -30,4 +30,11 @@ fn compile_tests() { ...@@ -30,4 +30,11 @@ fn compile_tests() {
t.compile_fail("tests/ui/fail/04-missing-message.rs"); 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/05-forbidden-idents.rs");
t.compile_fail("tests/ui/fail/06-access-generated-fields.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 @@ ...@@ -2,17 +2,14 @@
use ink_lang2 as ink; use ink_lang2 as ink;
#[ink::contract( #[ink::contract(version = "0.1.0")]
env = DefaultSrmlTypes,
version = "0.1.0",
)]
mod noop { mod noop {
#[ink(storage)] #[ink(storage)]
struct Noop {} struct Noop {}
impl Noop { impl Noop {
#[ink(constructor)] #[ink(constructor)]
fn new(&mut self) -> Self {} fn invalid_return(&mut self) -> Self {}
#[ink(message)] #[ink(message)]
fn noop(&self) {} fn noop(&self) {}
......
error: constructors in ink! must have no specified return type error: #[ink(constructor)] functions must not have a return type
--> $DIR/01-constructor-returns.rs:15:27 --> $DIR/01-constructor-returns.rs:12:38
| |
15 | fn new(&mut self) -> Self {} 12 | fn invalid_return(&mut self) -> Self {}
| ^^^^^^^ | ^^^^^^^
...@@ -2,10 +2,7 @@ ...@@ -2,10 +2,7 @@
use ink_lang2 as ink; use ink_lang2 as ink;
#[ink::contract( #[ink::contract(version = "0.1.0")]
env = DefaultSrmlTypes,
version = "0.1.0",
)]
mod noop { mod noop {
#[ink(storage)] #[ink(storage)]
struct Noop {} struct Noop {}
......
error: ink! contracts require at least one `#[ink(constructor)]` 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 { 6 | / mod noop {
10 | | #[ink(storage)] 7 | | #[ink(storage)]
11 | | struct Noop {} 8 | | struct Noop {}
12 | | 9 | |
... | ... |
16 | | } 13 | | }
17 | | } 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