diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 5e75bc10bca1c..8b7888e8c2dcc 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2293,7 +2293,9 @@ (return (expand-forms `(call transpose ,(cadr e)))))) 'generator - (lambda (e) (expand-generator e #f '())) + (lambda (e) + (check-no-return e) + (expand-generator e #f '())) 'flatten (lambda (e) (expand-generator (cadr e) #t '())) @@ -2317,7 +2319,6 @@ (error "comprehension syntax with `:` ranges has been removed")) (and (every (lambda (x) (and (pair? x) (eq? (car x) '=))) ranges) - (not (has-return? (cadr (caddr e)))) ;; TODO: this is a hack to lower simple comprehensions to loops very ;; early, to greatly reduce the # of functions and load on the compiler (lower-comprehension (cadr e) (cadr (caddr e)) ranges)))) @@ -2326,6 +2327,10 @@ (define (has-return? e) (expr-contains-p return? e (lambda (x) (not (function-def? x))))) +(define (check-no-return e) + (if (has-return? e) + (error "\"return\" not allowed inside comprehension or generator"))) + (define (has-break-or-continue? e) (expr-contains-p (lambda (x) (and (pair? x) (memq (car x) '(break continue)))) e @@ -2333,6 +2338,7 @@ (memq (car x) '(for while))))))) (define (lower-comprehension ty expr itrs) + (check-no-return expr) (if (has-break-or-continue? expr) (error "break or continue outside loop")) (let ((result (gensy)) diff --git a/test/functional.jl b/test/functional.jl index 6d7b64fbead87..7c7b2477a9fd8 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -220,10 +220,3 @@ end let (:)(a,b) = (i for i in Base.:(:)(1,10) if i%2==0) @test Int8[ i for i = 1:2 ] == [2,4,6,8,10] end - -# comprehensions with `return` -let f() = [ return 2 for i=1:2 ], - g() = Int[return 2 for i=1:2 ] - @test f() == [2, 2] - @test g() == [2, 2] -end diff --git a/test/syntax.jl b/test/syntax.jl index b552ae18a3daf..f95ce4a25f860 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1438,3 +1438,9 @@ end @test Meta.lower(@__MODULE__, :(Int[if true; break; end for i = 1:1])) == Expr(:error, "break or continue outside loop") @test Meta.lower(@__MODULE__, :([if true; continue; end for i = 1:1])) == Expr(:error, "break or continue outside loop") @test Meta.lower(@__MODULE__, :(Int[if true; continue; end for i = 1:1])) == Expr(:error, "break or continue outside loop") + +@test Meta.lower(@__MODULE__, :(return 0 for i=1:2)) == Expr(:error, "\"return\" not allowed inside comprehension or generator") +@test Meta.lower(@__MODULE__, :([ return 0 for i=1:2 ])) == Expr(:error, "\"return\" not allowed inside comprehension or generator") +@test Meta.lower(@__MODULE__, :(Int[ return 0 for i=1:2 ])) == Expr(:error, "\"return\" not allowed inside comprehension or generator") +@test [ ()->return 42 for i = 1:1 ][1]() == 42 +@test Function[ identity() do x; return 2x; end for i = 1:1 ][1](21) == 42