Skip to content

Commit

Permalink
fix: Prevent zero-argument functions from being created in Rust
Browse files Browse the repository at this point in the history
These cannot be called from the gluon side, instead a one argument
function that takes `()` should be used.

Fixes gluon-lang#873
  • Loading branch information
Marwes committed Sep 13, 2020
1 parent 1c8a1c0 commit c467d45
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 14 deletions.
47 changes: 47 additions & 0 deletions check/tests/pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1135,3 +1135,50 @@ match writer with
"#,
"test.List String"
}

test_check! {
issue_842,
r#"
type Digit a =
| One a
| Two a a
| Three a a a
| Four a a a a
type Node b =
| Node2 b b
| Node3 b b b
type FingerTree c =
| Empty
| Single c
| Deep (Digit c) (FingerTree (Node c)) (Digit c)
type View d =
| Nil
| View d (FingerTree d)
rec
let viewl xs : FingerTree e -> View e =
match xs with
| Empty -> Nil
| Single x -> View x Empty
| Deep (One a) deeper suffix ->
match viewl deeper with
| View (Node2 b c) rest -> View a (Deep (Two b c) rest suffix)
| View (Node3 b c d) rest -> View a (Deep (Three b c d) rest suffix)
| Nil ->
match suffix with
| One w -> View a (Single w)
| Two w x -> View a (Deep (One w) Empty (One x))
| Three w x y -> View a (Deep (Two w x) Empty (One y))
| Four w x y z -> View a (Deep (Three w x y) Empty (One z))
| Deep (Two a b) deeper suffix -> View a (Deep (One b) deeper suffix)
| Deep (Three a b c) deeper suffix -> View a (Deep (Two b c) deeper suffix)
| Deep (Four a b c d) deeper suffix -> View a (Deep (Three b c d) deeper suffix)
in
viewl
"#,
"test.List String"
}
36 changes: 22 additions & 14 deletions vm/src/api/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,11 @@ where
}

macro_rules! vm_function_impl {
([$($f:tt)*] $($args:ident),*) => {
([$($f:tt)*] $($args:ident),* -> $ret: ident, $ret_ty: ty) => {

impl <'vm, $($args,)* R> VmFunction<'vm> for $($f)* ($($args),*) -> R
impl <'vm, $($args,)* $ret> VmFunction<'vm> for $($f)* ($($args),*) -> $ret_ty
where $($args: Getable<'vm, 'vm> + 'vm,)*
R: AsyncPushable<'vm> + VmType + 'vm
$ret: AsyncPushable<'vm> + VmType + 'vm
{
#[allow(non_snake_case, unused_mut, unused_assignments, unused_variables, unused_unsafe)]
fn unpack_and_call(&self, vm: &'vm Thread) -> Status {
Expand Down Expand Up @@ -341,35 +341,43 @@ where
}

macro_rules! make_vm_function {
($($args:ident),*) => (
impl <$($args: VmType,)* R: VmType> VmType for fn ($($args),*) -> R {
($($args:ident),*) => {
make_vm_function_inner!($($args),* -> R, R);
}
}
macro_rules! make_vm_function_inner {
($($args:ident),* -> $ret: ident, $ret_ty: ty) => (
impl <$($args: VmType,)* $ret: VmType> VmType for fn ($($args),*) -> $ret_ty
where
<$ret_ty as VmType>::Type: Sized,
{
#[allow(non_snake_case)]
type Type = fn ($($args::Type),*) -> R::Type;
type Type = fn ($($args::Type),*) -> <$ret_ty as VmType>::Type;

#[allow(non_snake_case)]
fn make_type(vm: &Thread) -> ArcType {
let args = vec![$(make_type::<$args>(vm)),*];
vm.global_env().type_cache().function(args, make_type::<R>(vm))
vm.global_env().type_cache().function(args, make_type::<$ret_ty>(vm))
}
}

vm_function_impl!([fn] $($args),*);
vm_function_impl!([dyn Fn] $($args),*);
vm_function_impl!([fn] $($args),* -> $ret, $ret_ty);
vm_function_impl!([dyn Fn] $($args),* -> $ret, $ret_ty);

impl <'vm, $($args,)* R: VmType> FunctionType for fn ($($args),*) -> R {
impl <'vm, $($args,)* $ret: VmType> FunctionType for fn ($($args),*) -> R {
fn arguments() -> VmIndex {
count!($($args),*) + R::EXTRA_ARGS
}
}

impl <'s, $($args,)* R: VmType> FunctionType for dyn Fn($($args),*) -> R + 's {
impl <'s, $($args,)* $ret: VmType> FunctionType for dyn Fn($($args),*) -> R + 's {
fn arguments() -> VmIndex {
count!($($args),*) + R::EXTRA_ARGS
}
}

impl <'s, $($args: VmType,)* R: VmType> VmType for dyn Fn($($args),*) -> R + 's {
type Type = fn ($($args::Type),*) -> R::Type;
impl <'s, $($args: VmType,)* $ret: VmType> VmType for dyn Fn($($args),*) -> R + 's {
type Type = fn ($($args::Type),*) -> $ret::Type;

#[allow(non_snake_case)]
fn make_type(vm: &Thread) -> ArcType {
Expand Down Expand Up @@ -444,7 +452,7 @@ impl<T, $($args,)* R> Function<T, fn($($args),*) -> R>
)
}

make_vm_function!();
make_vm_function_inner!( -> R, crate::api::IO<R>);
make_vm_function!(A);
make_vm_function!(A, B);
make_vm_function!(A, B, C);
Expand Down

0 comments on commit c467d45

Please sign in to comment.