Skip to content

Commit

Permalink
Add optional static typing to functions and structs (#904)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNachoBIT authored Jan 28, 2025
1 parent a833d25 commit 92e6230
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 0 deletions.
6 changes: 6 additions & 0 deletions crates/rune/src/ast/item_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<ast::ItemFn>("pub async fn hello(foo, bar) -> Type {}");
assert!(item_with_type.output.is_some());
}

/// A function item.
Expand All @@ -61,6 +64,9 @@ pub struct ItemFn {
pub name: ast::Ident,
/// The arguments of the function.
pub args: ast::Parenthesized<ast::FnArg, T![,]>,
/// 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.
Expand Down
12 changes: 12 additions & 0 deletions crates/rune/src/ast/item_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ fn ast_parse() {

rt::<ast::Field>("a");
rt::<ast::Field>("#[x] a");

rt::<ast::ItemStruct>(
r"
struct Foo {
a: i32,
b: f64,
c: CustomType,
}",
);
}

/// A struct item.
Expand Down Expand Up @@ -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)>,
}
2 changes: 2 additions & 0 deletions crates/rune/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ mod macro_utils;
mod pat;
mod path;
mod prelude;
mod rn_type;
mod span;
pub(crate) mod spanned;
mod stmt;
Expand Down Expand Up @@ -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};
Expand Down
35 changes: 35 additions & 0 deletions crates/rune/src/ast/rn_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::ast::prelude::*;

#[test]
#[cfg(not(miri))]
fn ast_parse() {
rt::<ast::Type>("Bar");
rt::<ast::Type>("one::two::three::four::Five");
rt::<ast::Type>("Self");
rt::<ast::Type>("(one::One, two::Two)");
rt::<ast::Type>("(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<Box<Type>, T![,]>),
}

impl Parse for Type {
fn parse(p: &mut Parser<'_>) -> Result<Self> {
let segment = match p.nth(0)? {
K![!] => Self::Bang(p.parse()?),
K!['('] => Self::Tuple(p.parse()?),
_ => Self::Path(p.parse()?),
};

Ok(segment)
}
}
14 changes: 14 additions & 0 deletions crates/rune/src/indexing/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions crates/rune/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
23 changes: 23 additions & 0 deletions crates/rune/src/tests/static_typing.rs
Original file line number Diff line number Diff line change
@@ -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");
}
}
}

0 comments on commit 92e6230

Please sign in to comment.