Skip to content

Commit 76b2b26

Browse files
committed
Permit declarations of the form f(x::Vararg{Any})
Fixes up the expanded ast so that jl_is_rest_arg, as called from emit_function (step 2), works properly and avoids a later segfault.
1 parent 07e8f7a commit 76b2b26

File tree

6 files changed

+38
-6
lines changed

6 files changed

+38
-6
lines changed

src/alloc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ jl_sym_t *boundscheck_sym; jl_sym_t *copyast_sym;
9696
jl_sym_t *fastmath_sym;
9797
jl_sym_t *simdloop_sym; jl_sym_t *meta_sym;
9898
jl_sym_t *arrow_sym; jl_sym_t *inert_sym;
99+
jl_sym_t *vararg_sym;
99100

100101
typedef struct {
101102
int64_t a;

src/ast.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,11 @@ int jl_is_rest_arg(jl_value_t *ex)
750750
if (((jl_expr_t*)ex)->head != colons_sym) return 0;
751751
jl_expr_t *atype = (jl_expr_t*)jl_exprarg(ex,1);
752752
if (!jl_is_expr(atype)) return 0;
753-
return ((jl_expr_t*)atype)->head == dots_sym;
753+
if (((jl_expr_t*)atype)->head == dots_sym)
754+
return 1;
755+
if (atype->head != call_sym || jl_array_len(atype->args) < 3 || jl_array_len(atype->args) > 4)
756+
return 0;
757+
return ((jl_sym_t*)jl_exprarg(atype,1)) == vararg_sym;
754758
}
755759

756760
static jl_value_t *copy_ast(jl_value_t *expr, jl_svec_t *sp, int do_sp)

src/jltypes.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3096,7 +3096,8 @@ void jl_init_types(void)
30963096

30973097
jl_svec_t *tv;
30983098
tv = jl_svec2(tvar("T"), tvar("N"));
3099-
jl_vararg_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Vararg"), jl_any_type, tv);
3099+
vararg_sym = jl_symbol("Vararg");
3100+
jl_vararg_type = jl_new_abstracttype((jl_value_t*)vararg_sym, jl_any_type, tv);
31003101

31013102
jl_anytuple_type = jl_new_datatype(jl_symbol("Tuple"), jl_any_type, jl_emptysvec,
31023103
jl_emptysvec, jl_emptysvec, 0, 0, 0);

src/julia-syntax.scm

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@
110110
(bad-formal-argument v))
111111
(else
112112
(case (car v)
113-
((...) `(... ,(decl-type (cadr v))))
113+
((...) (if (eq? (length v) 3)
114+
`(... ,(decl-type (cadr v)) ,(caddr v))
115+
`(... ,(decl-type (cadr v)))))
114116
((|::|)
115117
(if (not (symbol? (cadr v)))
116118
(bad-formal-argument (cadr v)))
@@ -399,9 +401,13 @@
399401
;; except for rest arg
400402
(define (method-lambda-expr argl body)
401403
(let ((argl (map (lambda (x)
402-
(if (and (pair? x) (eq? (car x) '...))
404+
(if (vararg? x)
403405
(make-decl (arg-name x) (arg-type x))
404-
(arg-name x)))
406+
(if (varargexpr? x)
407+
(if (pair? (caddr x))
408+
x
409+
`(|::| ,(arg-name x) (curly Vararg Any)))
410+
(arg-name x))))
405411
argl)))
406412
`(lambda ,argl
407413
(scope-block ,body))))
@@ -484,6 +490,15 @@
484490
,body ,isstaged))))))
485491

486492
(define (vararg? x) (and (pair? x) (eq? (car x) '...)))
493+
(define (varargexpr? x) (and
494+
(pair? x)
495+
(eq? (car x) '::)
496+
(or
497+
(eq? (caddr x) 'Vararg)
498+
(and
499+
(pair? (caddr x))
500+
(length> (caddr x) 1)
501+
(eq? (cadr (caddr x)) 'Vararg)))))
487502
(define (trans? x) (and (pair? x) (eq? (car x) '|.'|)))
488503
(define (ctrans? x) (and (pair? x) (eq? (car x) '|'|)))
489504

src/julia.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ DLLEXPORT extern jl_value_t *jl_nothing;
457457
// some important symbols
458458
extern jl_sym_t *call_sym;
459459
extern jl_sym_t *call1_sym;
460-
extern jl_sym_t *dots_sym;
460+
extern jl_sym_t *dots_sym; extern jl_sym_t *vararg_sym;
461461
extern jl_sym_t *quote_sym; extern jl_sym_t *newvar_sym;
462462
extern jl_sym_t *top_sym; extern jl_sym_t *dot_sym;
463463
extern jl_sym_t *line_sym; extern jl_sym_t *toplevel_sym;

test/core.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,17 @@ begin
518518
@test firstlast(Val{false}) == "Last"
519519
end
520520

521+
# x::Vararg{Any} declarations
522+
begin
523+
local f1, f2, f3
524+
f1(x...) = [x...]
525+
f2(x::Vararg{Any}) = [x...]
526+
f3(x::Vararg) = [x...]
527+
@test f1(1,2,3) == [1,2,3]
528+
@test f2(1,2,3) == [1,2,3]
529+
@test f3(1,2,3) == [1,2,3]
530+
end
531+
521532
# try/finally
522533
begin
523534
after = 0

0 commit comments

Comments
 (0)