diff --git a/crates/rune/src/ast/item_fn.rs b/crates/rune/src/ast/item_fn.rs index f49306d01..59a8012ea 100644 --- a/crates/rune/src/ast/item_fn.rs +++ b/crates/rune/src/ast/item_fn.rs @@ -36,6 +36,9 @@ fn ast_parse() { assert_eq!(item.attributes.len(), 1); assert!(item.async_token.is_none()); assert!(item.const_token.is_some()); + + let item_with_type = rt::("pub async fn hello(foo, bar) -> Type {}"); + assert!(item_with_type.output.is_some()); } /// A function item. @@ -61,6 +64,9 @@ pub struct ItemFn { pub name: ast::Ident, /// The arguments of the function. pub args: ast::Parenthesized, + /// The function type. + #[rune(option)] + pub output: Option<(T![->], ast::Type)>, /// The body of the function. pub body: ast::Block, /// Opaque identifier for fn item. diff --git a/crates/rune/src/ast/item_struct.rs b/crates/rune/src/ast/item_struct.rs index 456b12d58..9b3f43652 100644 --- a/crates/rune/src/ast/item_struct.rs +++ b/crates/rune/src/ast/item_struct.rs @@ -23,6 +23,15 @@ fn ast_parse() { rt::("a"); rt::("#[x] a"); + + rt::( + r" + struct Foo { + a: i32, + b: f64, + c: CustomType, + }", + ); } /// A struct item. @@ -69,4 +78,7 @@ pub struct Field { pub visibility: ast::Visibility, /// Name of the field. pub name: ast::Ident, + /// The type. + #[rune(option)] + pub ty: Option<(T![:], ast::Type)>, } diff --git a/crates/rune/src/ast/mod.rs b/crates/rune/src/ast/mod.rs index a91394d32..24402531e 100644 --- a/crates/rune/src/ast/mod.rs +++ b/crates/rune/src/ast/mod.rs @@ -160,6 +160,7 @@ mod macro_utils; mod pat; mod path; mod prelude; +mod rn_type; mod span; pub(crate) mod spanned; mod stmt; @@ -230,6 +231,7 @@ pub use self::pat::{ }; pub use self::path::{Path, PathKind, PathSegment, PathSegmentExpr}; use self::prelude::*; +pub use self::rn_type::Type; pub use self::span::{ByteIndex, Span}; pub use self::spanned::{OptionSpanned, Spanned}; pub use self::stmt::{ItemOrExpr, Stmt, StmtSemi, StmtSortKey}; diff --git a/crates/rune/src/ast/rn_type.rs b/crates/rune/src/ast/rn_type.rs new file mode 100644 index 000000000..759965c43 --- /dev/null +++ b/crates/rune/src/ast/rn_type.rs @@ -0,0 +1,35 @@ +use crate::ast::prelude::*; + +#[test] +#[cfg(not(miri))] +fn ast_parse() { + rt::("Bar"); + rt::("one::two::three::four::Five"); + rt::("Self"); + rt::("(one::One, two::Two)"); + rt::("(one::One, (two::Two, three::Three))"); +} + +/// A type, used for static typing. +#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)] +#[non_exhaustive] +pub enum Type { + /// If the type is an identifier or a path. + Path(ast::Path), + /// If the type should return nothing (a.k.a the "never" type in Rust). + Bang(T![!]), + /// If the type is a tuple. + Tuple(ast::Parenthesized, T![,]>), +} + +impl Parse for Type { + fn parse(p: &mut Parser<'_>) -> Result { + let segment = match p.nth(0)? { + K![!] => Self::Bang(p.parse()?), + K!['('] => Self::Tuple(p.parse()?), + _ => Self::Path(p.parse()?), + }; + + Ok(segment) + } +} diff --git a/crates/rune/src/indexing/index.rs b/crates/rune/src/indexing/index.rs index 1a40e5e9b..53278ccf8 100644 --- a/crates/rune/src/indexing/index.rs +++ b/crates/rune/src/indexing/index.rs @@ -317,6 +317,13 @@ pub(crate) fn item_fn(idx: &mut Indexer<'_, '_>, mut ast: ast::ItemFn) -> compil )); } + if ast.output.is_some() { + return Err(compile::Error::msg( + &ast, + "Adding a return type in functions is not supported", + )); + } + let is_instance = ast.is_instance(); if is_instance { @@ -952,6 +959,13 @@ fn item_struct(idx: &mut Indexer<'_, '_>, mut ast: ast::ItemStruct) -> compile:: )); } + if field.ty.is_some() { + return Err(compile::Error::msg( + field, + "Static typing on fields is not supported", + )); + } + let name = field.name.resolve(cx)?; for doc in docs { diff --git a/crates/rune/src/tests.rs b/crates/rune/src/tests.rs index 792b27d5c..4ef3ffd6e 100644 --- a/crates/rune/src/tests.rs +++ b/crates/rune/src/tests.rs @@ -504,6 +504,8 @@ mod rename_type; #[cfg(not(miri))] mod result; #[cfg(not(miri))] +mod static_typing; +#[cfg(not(miri))] mod tuple; #[cfg(not(miri))] mod type_name_native; diff --git a/crates/rune/src/tests/static_typing.rs b/crates/rune/src/tests/static_typing.rs new file mode 100644 index 000000000..5b4d8001c --- /dev/null +++ b/crates/rune/src/tests/static_typing.rs @@ -0,0 +1,23 @@ +prelude!(); + +use ErrorKind::*; + +#[test] +fn deny_static_typing_function() { + assert_errors! { + "fn foo() -> Bar {}", + span!(0, 18), Custom { error } => { + assert_eq!(error.to_string(), "Adding a return type in functions is not supported"); + } + } +} + +#[test] +fn deny_static_typing_field() { + assert_errors! { + "struct Struct { foo: Bar }", + span!(16, 24), Custom { error } => { + assert_eq!(error.to_string(), "Static typing on fields is not supported"); + } + } +}