From ebceab86d507d72da9ddc0e4f45893b984658f7a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 14 Aug 2017 16:19:48 -0400 Subject: [PATCH] deprecate `const` on local variables, which used to be ignored. part of #5148 --- NEWS.md | 3 +++ base/complex.jl | 14 +++++++------- base/libc.jl | 10 +++++----- base/libdl.jl | 8 ++++---- base/loading.jl | 2 +- base/math.jl | 6 +++--- base/regex.jl | 8 ++++---- base/repl/REPL.jl | 2 +- base/repl/REPLCompletions.jl | 15 ++++++++------- base/sparse/sparsematrix.jl | 12 ++++++------ doc/src/manual/variables-and-scoping.md | 3 ++- src/julia-syntax.scm | 16 ++++++++++++---- test/TestHelpers.jl | 4 ++-- test/core.jl | 13 +++++++------ test/dates/io.jl | 2 +- test/misc.jl | 2 +- test/perf/shootout/binary_trees.jl | 6 +++--- test/perf/threads/lbm3d/lbm3d.jl | 10 +++++----- test/perf/threads/stockcorr/pstockcorr.jl | 16 ++++++++-------- test/pkg.jl | 4 ++-- test/repl.jl | 2 +- test/replcompletions.jl | 2 +- test/subtype.jl | 4 ++-- 23 files changed, 89 insertions(+), 75 deletions(-) diff --git a/NEWS.md b/NEWS.md index 02a4cb0beb31b1..4f001ae743fece 100644 --- a/NEWS.md +++ b/NEWS.md @@ -63,6 +63,9 @@ Language changes (`need_to_handle_undef_sparam = Set{Any}(m.sig for m in Test.detect_unbound_args(Base, recursive=true))`) is equal (`==`) to some known set (`expected = Set()`). ([#23117]) + * `const` declarations on local variables were previously ignored. They now give a + warning, so that this syntax can be disallowed or given a new meaning in a + future version ([#5148]). Breaking changes ---------------- diff --git a/base/complex.jl b/base/complex.jl index 64b80ae149076f..0664f9679c2485 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -499,9 +499,9 @@ julia> rad2deg(angle(-1 - im)) angle(z::Complex) = atan2(imag(z), real(z)) function log(z::Complex{T}) where T<:AbstractFloat - const T1::T = 1.25 - const T2::T = 3 - const ln2::T = log(convert(T,2)) #0.6931471805599453 + T1::T = 1.25 + T2::T = 3 + ln2::T = log(convert(T,2)) #0.6931471805599453 x, y = reim(z) ρ, k = ssqs(x,y) ax = abs(x) @@ -835,7 +835,7 @@ function cosh(z::Complex) end function tanh(z::Complex{T}) where T<:AbstractFloat - const Ω = prevfloat(typemax(T)) + Ω = prevfloat(typemax(T)) ξ, η = reim(z) if isnan(ξ) && η==0 return Complex(ξ, η) end if 4*abs(ξ) > asinh(Ω) #Overflow? @@ -880,9 +880,9 @@ function acosh(z::Complex) end function atanh(z::Complex{T}) where T<:AbstractFloat - const Ω = prevfloat(typemax(T)) - const θ = sqrt(Ω)/4 - const ρ = 1/θ + Ω = prevfloat(typemax(T)) + θ = sqrt(Ω)/4 + ρ = 1/θ x, y = reim(z) ax = abs(x) ay = abs(y) diff --git a/base/libc.jl b/base/libc.jl index fe3f46d446f9cd..98f254416166dc 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -39,7 +39,7 @@ if Sys.iswindows() function dup(src::WindowsRawSocket) new_handle = Ref{Ptr{Void}}(-1) my_process = ccall(:GetCurrentProcess, stdcall, Ptr{Void}, ()) - const DUPLICATE_SAME_ACCESS = 0x2 + DUPLICATE_SAME_ACCESS = 0x2 status = ccall(:DuplicateHandle, stdcall, Int32, (Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Ptr{Void}}, UInt32, Int32, UInt32), my_process, src.handle, my_process, new_handle, 0, false, DUPLICATE_SAME_ACCESS) @@ -290,10 +290,10 @@ if Sys.iswindows() GetLastError() = ccall(:GetLastError, stdcall, UInt32, ()) function FormatMessage(e=GetLastError()) - const FORMAT_MESSAGE_ALLOCATE_BUFFER = UInt32(0x100) - const FORMAT_MESSAGE_FROM_SYSTEM = UInt32(0x1000) - const FORMAT_MESSAGE_IGNORE_INSERTS = UInt32(0x200) - const FORMAT_MESSAGE_MAX_WIDTH_MASK = UInt32(0xFF) + FORMAT_MESSAGE_ALLOCATE_BUFFER = UInt32(0x100) + FORMAT_MESSAGE_FROM_SYSTEM = UInt32(0x1000) + FORMAT_MESSAGE_IGNORE_INSERTS = UInt32(0x200) + FORMAT_MESSAGE_MAX_WIDTH_MASK = UInt32(0xFF) lpMsgBuf = Ref{Ptr{UInt16}}() lpMsgBuf[] = 0 len = ccall(:FormatMessageW, stdcall, UInt32, (Cint, Ptr{Void}, Cint, Cint, Ptr{Ptr{UInt16}}, Cint, Ptr{Void}), diff --git a/base/libdl.jl b/base/libdl.jl index 9c2b8255f77888..cd08d66cf2f78b 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -234,8 +234,8 @@ function dllist() dynamic_libraries = Vector{AbstractString}(0) @static if Sys.islinux() - const callback = cfunction(dl_phdr_info_callback, Cint, - Tuple{Ref{dl_phdr_info}, Csize_t, Ref{Vector{AbstractString}}}) + callback = cfunction(dl_phdr_info_callback, Cint, + Tuple{Ref{dl_phdr_info}, Csize_t, Ref{Vector{AbstractString}}}) ccall(:dl_iterate_phdr, Cint, (Ptr{Void}, Ref{Vector{AbstractString}}), callback, dynamic_libraries) end @@ -254,8 +254,8 @@ function dllist() end @static if Sys.isbsd() && !Sys.isapple() - const callback = cfunction(dl_phdr_info_callback, Cint, - Tuple{Ref{dl_phdr_info}, Csize_t, Ref{Vector{AbstractString}}}) + callback = cfunction(dl_phdr_info_callback, Cint, + Tuple{Ref{dl_phdr_info}, Csize_t, Ref{Vector{AbstractString}}}) ccall(:dl_iterate_phdr, Cint, (Ptr{Void}, Ref{Vector{AbstractString}}), callback, dynamic_libraries) shift!(dynamic_libraries) end diff --git a/base/loading.jl b/base/loading.jl index 12c0ba917c7287..c3be02d771fb7d 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -46,7 +46,7 @@ elseif Sys.isapple() isfile(path) || return false path_basename = String(basename(path)) local casepreserved_basename - const header_size = 12 + header_size = 12 buf = Vector{UInt8}(length(path_basename) + header_size + 1) while true ret = ccall(:getattrlist, Cint, diff --git a/base/math.jl b/base/math.jl index 07e17d69d57c11..64f957d7a14676 100644 --- a/base/math.jl +++ b/base/math.jl @@ -758,9 +758,9 @@ end @inline literal_pow(::typeof(^), x::Float16, ::Val{p}) where {p} = Float16(literal_pow(^,Float32(x),Val(p))) function angle_restrict_symm(theta) - const P1 = 4 * 7.8539812564849853515625e-01 - const P2 = 4 * 3.7748947079307981766760e-08 - const P3 = 4 * 2.6951514290790594840552e-15 + P1 = 4 * 7.8539812564849853515625e-01 + P2 = 4 * 3.7748947079307981766760e-08 + P3 = 4 * 2.6951514290790594840552e-15 y = 2*floor(theta/(2*pi)) r = ((theta - y*P1) - y*P2) - y*P3 diff --git a/base/regex.jl b/base/regex.jl index 75e8dcc70e8216..fec921d0c810d4 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -251,10 +251,10 @@ function _write_capture(io, re, group) end function _replace(io, repl_s::SubstitutionString, str, r, re) - const SUB_CHAR = '\\' - const GROUP_CHAR = 'g' - const LBRACKET = '<' - const RBRACKET = '>' + SUB_CHAR = '\\' + GROUP_CHAR = 'g' + LBRACKET = '<' + RBRACKET = '>' repl = repl_s.string i = start(repl) e = endof(repl) diff --git a/base/repl/REPL.jl b/base/repl/REPL.jl index 4309a83efb7e19..d08e3fca01e3fd 100644 --- a/base/repl/REPL.jl +++ b/base/repl/REPL.jl @@ -807,7 +807,7 @@ function setup_interface( extra_repl_keymap = [extra_repl_keymap] end - const repl_keymap = AnyDict( + repl_keymap = AnyDict( ';' => function (s,o...) if isempty(s) || position(LineEdit.buffer(s)) == 0 buf = copy(LineEdit.buffer(s)) diff --git a/base/repl/REPLCompletions.jl b/base/repl/REPLCompletions.jl index bdb84d972b933b..2a02f1620c171c 100644 --- a/base/repl/REPLCompletions.jl +++ b/base/repl/REPLCompletions.jl @@ -82,14 +82,15 @@ function complete_symbol(sym, ffunc) suggestions end +const sorted_keywords = [ + "abstract type", "baremodule", "begin", "break", "catch", "ccall", + "const", "continue", "do", "else", "elseif", "end", "export", "false", + "finally", "for", "function", "global", "if", "import", + "importall", "let", "local", "macro", "module", "mutable struct", + "primitive type", "quote", "return", "struct", + "true", "try", "using", "while"] + function complete_keyword(s::String) - const sorted_keywords = [ - "abstract type", "baremodule", "begin", "break", "catch", "ccall", - "const", "continue", "do", "else", "elseif", "end", "export", "false", - "finally", "for", "function", "global", "if", "import", - "importall", "let", "local", "macro", "module", "mutable struct", - "primitive type", "quote", "return", "struct", - "true", "try", "using", "while"] r = searchsorted(sorted_keywords, s) i = first(r) n = length(sorted_keywords) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 11a0a434edc7e0..212565d4cddcc7 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -2042,8 +2042,8 @@ function getindex_I_sorted(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::Abst end function getindex_I_sorted_bsearch_A(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} - const nI = length(I) - const nJ = length(J) + nI = length(I) + nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval colptrS = Vector{Ti}(nJ+1) @@ -2101,8 +2101,8 @@ function getindex_I_sorted_bsearch_A(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVecto end function getindex_I_sorted_linear(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} - const nI = length(I) - const nJ = length(J) + nI = length(I) + nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval colptrS = Vector{Ti}(nJ+1) @@ -2160,8 +2160,8 @@ function getindex_I_sorted_linear(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, end function getindex_I_sorted_bsearch_I(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} - const nI = length(I) - const nJ = length(J) + nI = length(I) + nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval colptrS = Vector{Ti}(nJ+1) diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index f1df11b7ed5a36..22b1f2c8e75518 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -475,7 +475,8 @@ their values (or even their types) might change at almost any time. If a global not change, adding a `const` declaration solves this performance problem. Local constants are quite different. The compiler is able to determine automatically when a local -variable is constant, so local constant declarations are not necessary, and are currently just ignored. +variable is constant, so local constant declarations are not necessary, and in fact are currently +not supported. Special top-level assignments, such as those performed by the `function` and `struct` keywords, are constant by default. diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index e6481ffdefe2d0..2e1d2d7dcc8fc4 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1320,7 +1320,7 @@ (if (null? params) (error (string "empty type parameter list in \"" (deparse `(= (curly ,name) ,type-ex)) "\""))) `(block - (const ,name) + (const-if-global ,name) ,(expand-forms `(= ,name (where ,type-ex ,@params))))) (expand-forms @@ -3115,11 +3115,12 @@ f(x) = yt(x) (if (vinfo:never-undef vi) '(null) `(newvar ,(cadr e)))))) - ((const) + ((const) e) + ((const-if-global) (if (or (assq (cadr e) (car (lam:vinfo lam))) (assq (cadr e) (cadr (lam:vinfo lam)))) '(null) - e)) + `(const ,(cadr e)))) ((isdefined) ;; convert isdefined expr to function for closure converted variables (let* ((sym (cadr e)) (vi (and (symbol? sym) (assq sym (car (lam:vinfo lam))))) @@ -3661,7 +3662,14 @@ f(x) = yt(x) ((local-def) #f) ((local) #f) ((implicit-global) #f) - ((const) (emit e)) + ((const) + (if (or (assq (cadr e) (car (lam:vinfo lam))) + (assq (cadr e) (cadr (lam:vinfo lam)))) + (begin + (syntax-deprecation #f (string "`const` declaration on local variable" (linenode-string current-loc)) + "") + '(null)) + (emit e))) ((isdefined) (if tail (emit-return e) e)) ;; top level expressions returning values diff --git a/test/TestHelpers.jl b/test/TestHelpers.jl index 4f99773aa2a7ab..0ee2501159c980 100644 --- a/test/TestHelpers.jl +++ b/test/TestHelpers.jl @@ -24,8 +24,8 @@ function open_fake_pty() error("Unable to create a fake PTY in Windows") end - const O_RDWR = Base.Filesystem.JL_O_RDWR - const O_NOCTTY = Base.Filesystem.JL_O_NOCTTY + O_RDWR = Base.Filesystem.JL_O_RDWR + O_NOCTTY = Base.Filesystem.JL_O_NOCTTY fdm = ccall(:posix_openpt, Cint, (Cint,), O_RDWR|O_NOCTTY) fdm == -1 && error("Failed to open PTY master") diff --git a/test/core.jl b/test/core.jl index 1faaba8622958e..81704008c6b7f8 100644 --- a/test/core.jl +++ b/test/core.jl @@ -438,7 +438,8 @@ function const_implies_local() x = 1 local y let - const x = 0 + # TODO: change back to `const` if that's ever allowed + local x = 0 y = x end x, y @@ -2055,11 +2056,11 @@ end # issue #8798 let - const npy_typestrs = Dict("b1"=>Bool, - "i1"=>Int8, "u1"=>UInt8, - "i2"=>Int16, "u2"=>UInt16, - "i4"=>Int32, "u4"=>UInt32, - "i8"=>Int64, "u8"=>UInt64) + npy_typestrs = Dict("b1"=>Bool, + "i1"=>Int8, "u1"=>UInt8, + "i2"=>Int16, "u2"=>UInt16, + "i4"=>Int32, "u4"=>UInt32, + "i8"=>Int64, "u8"=>UInt64) sizeof_lookup() = sizeof(npy_typestrs["i8"]) @test sizeof_lookup() == 8 end diff --git a/test/dates/io.jl b/test/dates/io.jl index c7523277e45352..55e01c6ab3a61d 100644 --- a/test/dates/io.jl +++ b/test/dates/io.jl @@ -378,7 +378,7 @@ end # Issue: https://github.com/quinnj/TimeZones.jl/issues/19 let - const Zulu = String + Zulu = String function Dates.tryparsenext(d::Dates.DatePart{'Z'}, str, i, len) Dates.tryparsenext_word(str, i, len, Dates.min_width(d), Dates.max_width(d)) diff --git a/test/misc.jl b/test/misc.jl index 094e8dc0c9328e..840bb5ce56e007 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -576,7 +576,7 @@ if Sys.iswindows() let addr = cfunction(WeVirtualProtectThisToRWX, UInt64, (UInt64, UInt64)) addr = addr-(UInt64(addr)%4096) - const PAGE_EXECUTE_READWRITE = 0x40 + PAGE_EXECUTE_READWRITE = 0x40 oldPerm = Ref{UInt32}() err18083 = ccall(:VirtualProtect,stdcall,Cint, (Ptr{Void}, Csize_t, UInt32, Ptr{UInt32}), diff --git a/test/perf/shootout/binary_trees.jl b/test/perf/shootout/binary_trees.jl index 042fd815685147..f81469ea00a3f5 100644 --- a/test/perf/shootout/binary_trees.jl +++ b/test/perf/shootout/binary_trees.jl @@ -44,9 +44,9 @@ function loop_depths(d, min_depth, max_depth) end function binary_trees(N::Int=10) - const min_depth = 4 - const max_depth = N - const stretch_depth = max_depth + 1 + min_depth = 4 + max_depth = N + stretch_depth = max_depth + 1 # create and check stretch tree let c = check(make(0, stretch_depth)) diff --git a/test/perf/threads/lbm3d/lbm3d.jl b/test/perf/threads/lbm3d/lbm3d.jl index 14df2cea3c46f0..11fcee4c37c92e 100644 --- a/test/perf/threads/lbm3d/lbm3d.jl +++ b/test/perf/threads/lbm3d/lbm3d.jl @@ -119,11 +119,11 @@ end precompile(calc_equi!, (Array{Float64,4}, Array{Float64,4}, Array{Float64,3}, Array{Float64,3}, Array{Float64,3}, Array{Float64,2}, Array{Float64,3}, Array{Float64,3}, Array{Float64,3}, Array{Float64,3}, Int64, Int64, Int64, Float64)) function lbm3d(n) - const nx = n - const ny = nx - const nz = nx - const omega = 1.0 - const density = 1.0 + nx = n + ny = nx + nz = nx + omega = 1.0 + density = 1.0 # Implementation note: setting nchunk to nthreads() is a hack # to simulate the previous implementation's use of parallel regions. diff --git a/test/perf/threads/stockcorr/pstockcorr.jl b/test/perf/threads/stockcorr/pstockcorr.jl index 0b00c158f82e88..33e055dc5006ea 100644 --- a/test/perf/threads/stockcorr/pstockcorr.jl +++ b/test/perf/threads/stockcorr/pstockcorr.jl @@ -61,15 +61,15 @@ end # Threaded version function pstockcorr(n) ## Correlated asset information - const CurrentPrice = [78. 102.] # Initial Prices of the two stocks - const Corr = [1. 0.4; 0.4 1.] # Correlation Matrix - const T = 500 # Number of days to simulate = 2years = 500days - const dt = 1/250 # Time step (1year = 250days) - const Div=[0.01 0.01] # Dividend - const Vol=[0.2 0.3] # Volatility + CurrentPrice = [78. 102.] # Initial Prices of the two stocks + Corr = [1. 0.4; 0.4 1.] # Correlation Matrix + T = 500 # Number of days to simulate = 2years = 500days + dt = 1/250 # Time step (1year = 250days) + Div=[0.01 0.01] # Dividend + Vol=[0.2 0.3] # Volatility ## Market Information - const r = 0.03 # Risk-free rate + r = 0.03 # Risk-free rate ## Define storages SimulPriceA = zeros(T,n) # Simulated Price of Asset A @@ -78,7 +78,7 @@ function pstockcorr(n) SimulPriceB[1,:] = CurrentPrice[2] ## Generating the paths of stock prices by Geometric Brownian Motion - const UpperTriangle = full(chol(Corr)) # UpperTriangle Matrix by Cholesky decomposition + UpperTriangle = full(chol(Corr)) # UpperTriangle Matrix by Cholesky decomposition # Optimization: pre-allocate these for performance # NOTE: the new GC will hopefully fix this, but currently GC time diff --git a/test/pkg.jl b/test/pkg.jl index 937ec7bba2c720..3df2f550329421 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -480,7 +480,7 @@ temp_pkg_dir() do nothingtodomsg) Pkg.update("Example") metadata_dir = Pkg.dir("METADATA") - const old_commit = "313bfaafa301e82d40574a778720e893c559a7e2" + old_commit = "313bfaafa301e82d40574a778720e893c559a7e2" # Force a METADATA rollback to an old version, so that we will install some # outdated versions of some packages and then update some of those @@ -525,7 +525,7 @@ temp_pkg_dir() do Pkg.rm(package) # Remove package if installed metadata_dir = Pkg.dir("METADATA") - const old_commit = "83ff7116e51fc9cdbd7e67affbd344b9f5c9dbf2" + old_commit = "83ff7116e51fc9cdbd7e67affbd344b9f5c9dbf2" # Reset METADATA to the second to last update of Example.jl LibGit2.with(LibGit2.GitRepo, metadata_dir) do repo diff --git a/test/repl.jl b/test/repl.jl index 3c3fc9a1cbf6fb..727bb33d4770cf 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -232,7 +232,7 @@ function AddCustomMode(repl, prompt) hp.mode_mapping[:foobar] = foobar_mode foobar_mode.hist = hp - const foobar_keymap = Dict{Any,Any}( + foobar_keymap = Dict{Any,Any}( '<' => function (s,args...) if isempty(s) if !haskey(s.mode_state,foobar_mode) diff --git a/test/replcompletions.jl b/test/replcompletions.jl index 6e4630aa52eafd..f47108f2dc10a3 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -76,7 +76,7 @@ function temp_pkg_dir_noinit(fn::Function) # Used in tests below to set up and tear down a sandboxed package directory # Unlike the version in test/pkg.jl, this does not run Pkg.init so does not # clone METADATA (only pkg and libgit2-online tests should need internet access) - const tmpdir = joinpath(tempdir(),randstring()) + tmpdir = joinpath(tempdir(),randstring()) withenv("JULIA_PKGDIR" => tmpdir) do @test !isdir(Pkg.dir()) try diff --git a/test/subtype.jl b/test/subtype.jl index 458843661792ed..e18f4d6593f29e 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1094,12 +1094,12 @@ f20103(::Type{TT20103{X,Y}},x::X,y::Y) where {X,Y} = 1 f20103(::Type{TT20103{X,X}},x::X) where {X} = 100 @test_broken typeintersect(Type{NTuple{N,E}} where E where N, Type{NTuple{N,E} where N} where E) == Union{} # use @testintersect once fixed let ints = (Int, Int32, UInt, UInt32) - const Ints = Union{ints...} + Ints = Union{ints...} vecs = [] for i = 2:4, t in ints push!(vecs, NTuple{i, t}) end - const Vecs = Union{vecs...} + Vecs = Union{vecs...} T = Type{Tuple{V, I}} where V <: Vecs where I <: Ints @testintersect(T, T, T) test(a::Type{Tuple{V, I}}) where {V <: Vecs, I <: Ints} = I