...
 
Commits (6)
...@@ -23,7 +23,10 @@ use crate::{ ...@@ -23,7 +23,10 @@ use crate::{
use core::convert::TryFrom; use core::convert::TryFrom;
use either::Either; use either::Either;
use itertools::Itertools as _; use itertools::Itertools as _;
use proc_macro2::{Span, Ident}; use proc_macro2::{
Ident,
Span,
};
use std::collections::HashSet; use std::collections::HashSet;
use syn::{ use syn::{
parse::{ parse::{
...@@ -587,24 +590,63 @@ impl TryFrom<syn::Item> for ir::Item { ...@@ -587,24 +590,63 @@ impl TryFrom<syn::Item> for ir::Item {
} }
} }
syn::Item::Struct(item_struct) => { syn::Item::Struct(item_struct) => {
let ink_markers = item_struct let markers = utils::filter_map_ink_attributes(&item_struct.attrs)
.attrs
.iter()
.cloned()
.filter_map(|attr| ir::Marker::try_from(attr).ok())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if ink_markers.is_empty() { if markers.is_empty() {
Ok(ir::RustItem::from(syn::Item::Struct(item_struct)).into()) return Ok(ir::RustItem::from(syn::Item::Struct(item_struct)).into())
} else if ink_markers.iter().any(|marker| marker.is_simple("storage")) { }
ir::ItemStorage::try_from(item_struct) let event_marker =
.map(Into::into) markers.iter().position(|marker| marker.is_simple("event"));
.map(ir::Item::Ink) let storage_marker =
} else if ink_markers.iter().any(|marker| marker.is_simple("event")) { markers.iter().position(|marker| marker.is_simple("storage"));
ir::ItemEvent::try_from(item_struct)
.map(Into::into) match (storage_marker, event_marker) {
.map(ir::Item::Ink) (Some(_storage_marker), None) => {
} else { ir::ItemStorage::try_from(item_struct)
bail!(item_struct, "found invalid `#[ink(..)]` marker") .map(Into::into)
.map(ir::Item::Ink)
},
(None, Some(_event_marker)) => {
ir::ItemEvent::try_from(item_struct)
.map(Into::into)
.map(ir::Item::Ink)
},
(None, None) => {
Err(markers
.iter()
.map(|marker| {
format_err_span!(
marker.span(),
"unsupported ink! marker for struct")
})
.fold(
format_err!(
item_struct,
"encountered unsupported ink! markers for struct",
),
|mut err1, err2| {
err1.combine(err2);
err1
})
)
}
(Some(storage_marker), Some(event_marker)) => {
// Special case: We have both #[ink(storage)] and #[ink(event)].
// This is treated as error but depending on the
// order in which the markers have been provided
// we either treat it as storage or event definition.
//
// We take whatever ink! marker was provided first.
if storage_marker < event_marker {
ir::ItemStorage::try_from(item_struct)
.map(Into::into)
.map(ir::Item::Ink)
} else {
ir::ItemEvent::try_from(item_struct)
.map(Into::into)
.map(ir::Item::Ink)
}
}
} }
} }
rust_item => Ok(ir::Item::Rust(rust_item.into())), rust_item => Ok(ir::Item::Rust(rust_item.into())),
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
//! Contains general utilities for the ink! IR module. //! Contains general utilities for the ink! IR module.
use crate::ir;
use proc_macro2::Span; use proc_macro2::Span;
use syn::{ use syn::{
parse::{ parse::{
...@@ -73,6 +74,18 @@ where ...@@ -73,6 +74,18 @@ where
attrs.into_iter().filter(|attr| is_ink_attribute(attr)) attrs.into_iter().filter(|attr| is_ink_attribute(attr))
} }
/// Yields back the filtered `#[ink(..)]` markers converted into their ink! form if any.
pub fn filter_map_ink_attributes<'a, I>(attrs: I) -> impl Iterator<Item = ir::Marker>
where
I: IntoIterator<Item = &'a syn::Attribute> + 'a,
{
use core::convert::TryFrom as _;
attrs
.into_iter()
.cloned()
.filter_map(|attr| ir::Marker::try_from(attr).ok())
}
/// Returns `true` if the attributes contain any `#[ink(..)]` markers. /// Returns `true` if the attributes contain any `#[ink(..)]` markers.
pub fn has_ink_attributes<'a, I>(attrs: I) -> bool pub fn has_ink_attributes<'a, I>(attrs: I) -> bool
where where
......
...@@ -40,4 +40,7 @@ fn compile_tests() { ...@@ -40,4 +40,7 @@ fn compile_tests() {
t.compile_fail("tests/ui/fail/14-missing-storage-struct.rs"); t.compile_fail("tests/ui/fail/14-missing-storage-struct.rs");
t.compile_fail("tests/ui/fail/15-multiple-storage-structs.rs"); t.compile_fail("tests/ui/fail/15-multiple-storage-structs.rs");
t.compile_fail("tests/ui/fail/16-storage-impl-ident-conflict.rs"); t.compile_fail("tests/ui/fail/16-storage-impl-ident-conflict.rs");
t.compile_fail("tests/ui/fail/17-conflicting-ink-markers.rs");
t.compile_fail("tests/ui/fail/18-conflicting-ink-markers-2.rs");
t.compile_fail("tests/ui/fail/19-unknown-struct-ink-marker.rs");
} }
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
#[ink(event)] // We cannot have #[ink(event)] if we already have #[ink(storage)]
struct Noop {}
impl Noop {
#[ink(constructor)]
fn new(&mut self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: invalid ink! attribute found for `#[ink(storage)]` struct
--> $DIR/17-conflicting-ink-markers.rs:8:10
|
8 | #[ink(event)] // We cannot have #[ink(event)] if we already have #[ink(storage)]
| ^^^^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
#[ink(event)]
#[ink(storage)] // We cannot have #[ink(event)] if we already have #[ink(storage)]
struct Event {}
impl Noop {
#[ink(constructor)]
fn new(&mut self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: invalid ink! attribute found for `#[ink(event)]` struct
--> $DIR/18-conflicting-ink-markers-2.rs:11:10
|
11 | #[ink(storage)] // We cannot have #[ink(event)] if we already have #[ink(storage)]
| ^^^^^^^^^
#![feature(proc_macro_hygiene)]
use ink_lang2 as ink;
#[ink::contract(version = "0.1.0")]
mod noop {
#[ink(storage)]
struct Noop {}
#[ink(unknown_or_unsupported)]
struct HasUnknownMarker {}
impl Noop {
#[ink(constructor)]
fn new(&mut self) {}
#[ink(message)]
fn noop(&self) {}
}
}
fn main() {}
error: encountered unsupported ink! markers for struct
--> $DIR/19-unknown-struct-ink-marker.rs:10:5
|
10 | / #[ink(unknown_or_unsupported)]
11 | | struct HasUnknownMarker {}
| |______________________________^
error: unsupported ink! marker for struct
--> $DIR/19-unknown-struct-ink-marker.rs:10:10
|
10 | #[ink(unknown_or_unsupported)]
| ^^^^^^^^^^^^^^^^^^^^^^^^