Skip to content

Commit

Permalink
fix #24452, deprecate (x...) tuple syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Nov 20, 2017
1 parent 4f5e374 commit b6319d4
Show file tree
Hide file tree
Showing 16 changed files with 53 additions and 31 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ Language changes
backslashes and the end of the literal while 2n+1 backslashes followed by a quote encodes n
backslashes followed by a quote character ([#22926]).

* The syntax `(x...)` for constructing a tuple is deprecated; use `(x...,)` instead (#24452).

Breaking changes
----------------

Expand Down
2 changes: 1 addition & 1 deletion base/abstractarraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ function repeat(A::AbstractArray;
end

rep_kw2tup(n::Integer) = (n,)
rep_kw2tup(v::AbstractArray{<:Integer}) = (v...)
rep_kw2tup(v::AbstractArray{<:Integer}) = (v...,)
rep_kw2tup(t::Tuple) = t

rep_shapes(A, i, o) = _rshps((), (), size(A), i, o)
Expand Down
2 changes: 1 addition & 1 deletion base/dates/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ function DateFormat(f::AbstractString, locale::DateLocale=ENGLISH)
push!(tokens, Delim(length(tran) == 1 ? first(tran) : tran))
end

tokens_tuple = (tokens...)
tokens_tuple = (tokens...,)
return DateFormat{Symbol(f),typeof(tokens_tuple)}(tokens_tuple, locale)
end

Expand Down
2 changes: 1 addition & 1 deletion base/libgit2/gitcredential.jl
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ function Base.parse(::Type{GitCredentialHelper}, helper::AbstractString)
cmd_str = "git credential-$helper"
end

GitCredentialHelper(`$(Base.shell_split(cmd_str)...)`)
GitCredentialHelper(`$(Base.shell_split(cmd_str))`)
end

function Base.:(==)(a::GitCredentialHelper, b::GitCredentialHelper)
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/rowvector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ IndexStyle(::Type{<:RowVector}) = IndexLinear()
# helper function for below
@inline to_vec(rowvec::RowVector) = map(transpose, transpose(rowvec))
@inline to_vec(x::Number) = x
@inline to_vecs(rowvecs...) = (map(to_vec, rowvecs)...)
@inline to_vecs(rowvecs...) = (map(to_vec, rowvecs)...,)

# map: Preserve the RowVector by un-wrapping and re-wrapping, but note that `f`
# expects to operate within the transposed domain, so to_vec transposes the elements
Expand Down
2 changes: 1 addition & 1 deletion base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ index_ndims() = ()

# combined dimensionality of all indices
# rather than returning N, it returns an NTuple{N,Bool} so the result is inferrable
@inline index_dimsum(i1, I...) = (index_dimsum(I...)...)
@inline index_dimsum(i1, I...) = (index_dimsum(I...)...,)
@inline index_dimsum(::Colon, I...) = (true, index_dimsum(I...)...)
@inline index_dimsum(::AbstractArray{Bool}, I...) = (true, index_dimsum(I...)...)
@inline function index_dimsum(::AbstractArray{<:Any,N}, I...) where N
Expand Down
2 changes: 1 addition & 1 deletion base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ strides(V::SubArray) = substrides(V.parent, V.indexes)

substrides(parent, I::Tuple) = substrides(1, parent, 1, I)
substrides(s, parent, dim, ::Tuple{}) = ()
substrides(s, parent, dim, I::Tuple{ScalarIndex, Vararg{Any}}) = (substrides(s*size(parent, dim), parent, dim+1, tail(I))...)
substrides(s, parent, dim, I::Tuple{ScalarIndex, Vararg{Any}}) = (substrides(s*size(parent, dim), parent, dim+1, tail(I))...,)
substrides(s, parent, dim, I::Tuple{Slice, Vararg{Any}}) = (s, substrides(s*size(parent, dim), parent, dim+1, tail(I))...)
substrides(s, parent, dim, I::Tuple{AbstractRange, Vararg{Any}}) = (s*step(I[1]), substrides(s*size(parent, dim), parent, dim+1, tail(I))...)
substrides(s, parent, dim, I::Tuple{Any, Vararg{Any}}) = throw(ArgumentError("strides is invalid for SubArrays with indices of type $(typeof(I[1]))"))
Expand Down
10 changes: 5 additions & 5 deletions base/tuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ endof(t::Tuple) = length(t)
size(t::Tuple, d) = (d == 1) ? length(t) : throw(ArgumentError("invalid tuple dimension $d"))
@eval getindex(t::Tuple, i::Int) = getfield(t, i, $(Expr(:boundscheck)))
@eval getindex(t::Tuple, i::Real) = getfield(t, convert(Int, i), $(Expr(:boundscheck)))
getindex(t::Tuple, r::AbstractArray{<:Any,1}) = ([t[ri] for ri in r]...)
getindex(t::Tuple, r::AbstractArray{<:Any,1}) = ([t[ri] for ri in r]...,)
getindex(t::Tuple, b::AbstractArray{Bool,1}) = length(b) == length(t) ? getindex(t, find(b)) : throw(BoundsError(t, b))

# returns new tuple; N.B.: becomes no-op if i is out-of-bounds
Expand Down Expand Up @@ -137,7 +137,7 @@ end
function _ntuple(f, n)
@_noinline_meta
(n >= 0) || throw(ArgumentError(string("tuple length should be ≥0, got ", n)))
([f(i) for i = 1:n]...)
([f(i) for i = 1:n]...,)
end

# inferrable ntuple (enough for bootstrapping)
Expand All @@ -163,7 +163,7 @@ function map(f, t::Any16)
for i=1:n
A[i] = f(t[i])
end
(A...)
(A...,)
end
# 2 argument function
map(f, t::Tuple{}, s::Tuple{}) = ()
Expand All @@ -179,7 +179,7 @@ function map(f, t::Any16, s::Any16)
for i = 1:n
A[i] = f(t[i], s[i])
end
(A...)
(A...,)
end
# n argument function
heads(ts::Tuple...) = map(t -> t[1], ts)
Expand All @@ -195,7 +195,7 @@ function map(f, t1::Any16, t2::Any16, ts::Any16...)
for i = 1:n
A[i] = f(t1[i], t2[i], map(t -> t[i], ts)...)
end
(A...)
(A...,)
end


Expand Down
4 changes: 3 additions & 1 deletion src/ast.scm
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@
(string (car e) (deparse (cadr e)))
(string (deparse (cadr e)) " " (car e) " " (deparse (caddr e)))))
((memq (car e) '($ &))
(string (car e) (deparse (cadr e))))
(if (pair? (cadr e))
(string (car e) "(" (deparse (cadr e)) ")")
(string (car e) (deparse (cadr e)))))
((eq? (car e) '|::|)
(if (length> e 2)
(string (deparse (cadr e)) (car e) (deparse (caddr e)))
Expand Down
32 changes: 23 additions & 9 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@
(define whitespace-newline #f)
; enable parsing `where` with high precedence
(define where-enabled #t)
; allow (x...), parsed as (... x). otherwise a deprecation warning is given (#24452)
(define accept-dots-without-comma #f)

(define current-filename 'none)

Expand Down Expand Up @@ -601,7 +603,9 @@
(if *deperror* "ERROR:" "WARNING:") " deprecated syntax \"" what "\""
(if (or (not s) (eq? current-filename 'none))
""
(string " at " current-filename ":" (input-port-line (if (port? s) s (ts:port s)))))
(string " at " current-filename ":" (if (number? s)
s
(input-port-line (if (port? s) s (ts:port s))))))
"."
(if (equal? instead "")
""
Expand Down Expand Up @@ -1044,7 +1048,8 @@
((not un)
(error (string "\"" op "\" is not a unary operator")))
(else
(let* ((arg (parse-unary s))
(let* ((arg (with-bindings ((accept-dots-without-comma #t))
(parse-unary s)))
(args (if (and (pair? arg) (eq? (car arg) 'tuple))
(cons op (cdr arg))
(list op arg))))
Expand Down Expand Up @@ -1131,11 +1136,14 @@
(or (closing-token? next) (newline? next))))
op)
((memq op '(& |::|)) (list op (parse-where s parse-call)))
(else (list op (parse-unary-prefix s)))))
(else (list op (with-bindings
((accept-dots-without-comma #t))
(parse-unary-prefix s))))))
(parse-atom s))))

(define (parse-def s is-func)
(let* ((ex (parse-unary-prefix s))
(define (parse-def s is-func anon)
(let* ((ex (with-bindings ((accept-dots-without-comma anon))
(parse-unary-prefix s)))
(sig (if (or (and is-func (reserved-word? ex)) (initial-reserved-word? ex))
(error (string "invalid name \"" ex "\""))
(parse-call-chain s ex #f)))
Expand Down Expand Up @@ -1281,6 +1289,7 @@
(or (eq? (car sig) 'call)
(eq? (car sig) 'tuple)
(and paren (eq? (car sig) 'block))
(and paren (eq? (car sig) '...))
(and (eq? (car sig) '|::|)
(pair? (cadr sig))
(eq? (car (cadr sig)) 'call))
Expand Down Expand Up @@ -1413,7 +1422,7 @@

((function macro)
(let* ((paren (eqv? (require-token s) #\())
(sig (parse-def s (not (eq? word 'macro)))))
(sig (parse-def s (eq? word 'function) paren)))
(if (and (not paren) (symbol-or-interpolate? sig))
(begin (if (not (eq? (require-token s) 'end))
(error (string "expected \"end\" in definition of " word " \"" sig "\"")))
Expand Down Expand Up @@ -2265,10 +2274,15 @@
(t (require-token s)))
(cond ((eqv? t #\) )
(take-token s)
;; value in parentheses (x)
(if (and (pair? ex) (eq? (car ex) '...))
;; (ex...)
`(tuple ,ex)
;; value in parentheses (x)
(let ((lineno (input-port-line (ts:port s))))
(if (or accept-dots-without-comma (eq? (peek-token s) '->))
ex
(begin (syntax-deprecation lineno
(string "(" (deparse (cadr ex)) "...)")
(string "(" (deparse (cadr ex)) "...,)"))
`(tuple ,ex))))
ex))
((eq? t 'for)
(expect-space-before s 'for)
Expand Down
2 changes: 1 addition & 1 deletion src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,7 @@
(define (expand-function-def e) ;; handle function definitions
(define (just-arglist? ex)
(and (pair? ex)
(or (memq (car ex) '(tuple block))
(or (memq (car ex) '(tuple block ...))
(and (eq? (car ex) 'where)
(just-arglist? (cadr ex))))))
(let ((name (cadr e)))
Expand Down
7 changes: 3 additions & 4 deletions src/macroexpand.scm
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
((atom? x) x)
((and (= d 0) (eq? (car x) '$))
(if (length= x 2)
(if (and (length= (cadr x) 2) (eq? (caadr x) 'tuple)
(vararg? (cadadr x)))
;; splice expr ($ (tuple (... x)))
`(... ,(cadr (cadr (cadr x))))
(if (vararg? (cadr x))
;; splice expr ($ (... x))
`(... ,(cadr (cadr x)))
;; otherwise normal interpolation
(cadr x))
;; in e.g. `quote quote $$(x...) end end` multiple expressions can be
Expand Down
6 changes: 3 additions & 3 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3184,7 +3184,7 @@ mutable struct D11597{T} <: C11597{T} d::T end
@test_throws TypeError repr(D11597(1.0))

# issue #11772
@test_throws UndefRefError (Vector{Any}(5)...)
@test_throws UndefRefError (Vector{Any}(5)...,)

# issue #11813
let a = UInt8[1, 107, 66, 88, 2, 99, 254, 13, 0, 0, 0, 0]
Expand All @@ -3204,8 +3204,8 @@ let a = UInt8[0, 0, 0, 0, 0x66, 99, 254, 13, 0, 0, 0, 0]
f11813(p) = ((Int32(3),UInt8(0x66)),Int32(0)) === unsafe_load(convert(Ptr{Tuple{Tuple{Int32,UInt8},Int32}},p))
@test f11813(p) === true # redundant comparison test seems to make this test more reliable, don't remove
end
let a = (1:1000...),
b = (1:1000...)
let a = (1:1000...,),
b = (1:1000...,)
@test a == b
@test a === b
@test (a == b) === true
Expand Down
2 changes: 1 addition & 1 deletion test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ const NInt1{N} = Tuple{Int, Vararg{Int, N}}
@test Base.eltype(NInt{1}) === Int
@test Base.eltype(NInt1{0}) === Int
@test Base.eltype(NInt1{1}) === Int
fNInt(x::NInt) = (x...)
fNInt(x::NInt) = (x...,)
gNInt() = fNInt(x)
@test Base.return_types(gNInt, ()) == Any[NInt]
@test Base.return_types(eltype, (NInt,)) == Any[Union{Type{Int}, Type{Union{}}}] # issue 21763
Expand Down
2 changes: 1 addition & 1 deletion test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ end

function test_code_reflection(freflect, f, types, tester)
tester(freflect, f, types)
tester(freflect, f, (types.parameters...))
tester(freflect, f, (types.parameters...,))
nothing
end

Expand Down
5 changes: 5 additions & 0 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,11 @@ let xs = [:(1+2), :(3+4), :(5+6)]
@test ex2.args[2:end] == [3,7,11]
end

let x = [3,2,1]
@test :( $(x...,) ) == (3, 2, 1)
@test :( $(x...), ) == Expr(:tuple, 3, 2, 1)
end

# issue #23519
@test Meta.parse("@foo[1]") == Meta.parse("@foo([1])")
@test Meta.parse("@foo[1 2; 3 4]") == Meta.parse("@foo([1 2; 3 4])")
Expand Down

0 comments on commit b6319d4

Please sign in to comment.