From 8ebbd94a83fcd4708bff898767686f27fdcc203a Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Fri, 2 Jul 2021 02:01:58 +0200 Subject: [PATCH] fix slurping into function definition (#40738) Discovered while working on #40737. Currently, this throws an unintuitive error: ```julia julia> a, f()... = 1, 2, 3 ERROR: syntax: ssavalue with no def Stacktrace: [1] top-level scope @ REPL[1]:1 ``` Might as well fix this properly - Why not allow function definitions to slurp a little from time to time? ;) (cherry picked from commit 5c49a0d4890e4cd63931718797adbb8143155e75) --- src/julia-syntax.scm | 12 ++++++++---- test/syntax.jl | 12 ++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 420eeaf51f747..f00ea0c9ba6d9 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1456,7 +1456,7 @@ (cons R elts))) ((vararg? L) (if (null? (cdr lhss)) - (let ((temp (make-ssavalue))) + (let ((temp (if (eventually-call? (cadr L)) (gensy) (make-ssavalue)))) `(block ,@(reverse stmts) (= ,temp (tuple ,@rhss)) ,@(reverse after) @@ -2155,9 +2155,13 @@ ((eq? l x) #t) (else (in-lhs? x (cdr lhss))))))) ;; in-lhs? also checks for invalid syntax, so always call it first - (let* ((xx (if (or (and (not (in-lhs? x lhss)) (symbol? x)) - (ssavalue? x)) - x (make-ssavalue))) + (let* ((xx (cond ((or (and (not (in-lhs? x lhss)) (symbol? x)) + (ssavalue? x)) + x) + ((and (pair? lhss) (vararg? (last lhss)) + (eventually-call? (cadr (last lhss)))) + (gensy)) + (else (make-ssavalue)))) (ini (if (eq? x xx) '() (list (sink-assignment xx (expand-forms x))))) (n (length lhss)) ;; skip last assignment if it is an all-underscore vararg diff --git a/test/syntax.jl b/test/syntax.jl index 707437096ef14..19f692baec95c 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2937,3 +2937,15 @@ end @test eval(Meta.parse("`a\\\r\nb`")) == `ab` @test eval(Meta.parse("`a\\\rb`")) == `ab` end + +@testset "slurping into function def" begin + x, f()... = [1, 2, 3] + @test x == 1 + @test f() == [2, 3] + # test that call to `Base.rest` is outside the definition of `f` + @test f() === f() + + x, f()... = 1, 2, 3 + @test x == 1 + @test f() == (2, 3) +end