diff --git a/NEWS.md b/NEWS.md index df9d327cb2718..359ad8f0fdd5a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -220,6 +220,9 @@ Language changes is deprecated. It will likely be reclaimed in a later version for passing keyword arguments. Note this does not affect updating operators like `+=` ([#25631]). + * `try` blocks without `catch` or `finally` are no longer allowed. An explicit empty + `catch` block should be written instead ([#27554]). + Breaking changes ---------------- diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index e38dcb3e4d842..9fc15e731238d 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -994,6 +994,7 @@ function builtin_tfunction(@nospecialize(f), argtypes::Array{Any,1}, argvals = anymap(a -> a.val, argtypes) try return Const(f(argvals...)) + catch end end iidx = Int(reinterpret(Int32, f::IntrinsicFunction)) + 1 diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index f6cda34bd1327..f5ef2aef631ac 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -469,8 +469,7 @@ end `try`/`catch` statements also allow the `Exception` to be saved in a variable, e.g. `catch y`. -The `catch` clause is not strictly necessary; when omitted, the default return value is -[`nothing`](@ref). The power of the `try`/`catch` construct lies in the ability to unwind a deeply +The power of the `try`/`catch` construct lies in the ability to unwind a deeply nested computation immediately to a much higher level in the stack of calling functions. """ kw"try", kw"catch" diff --git a/base/download.jl b/base/download.jl index ba9d8dd16d2a2..e5ed437a94a7f 100644 --- a/base/download.jl +++ b/base/download.jl @@ -33,6 +33,7 @@ else Sys.which(checkcmd) downloadcmd = checkcmd break + catch end end end diff --git a/base/iostream.jl b/base/iostream.jl index 58e937d055d99..e3f7225bcf108 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -485,6 +485,7 @@ function read(s::IOStream) if pos > 0 sz -= pos end + catch end b = StringVector(sz<=0 ? 1024 : sz) nr = readbytes_all!(s, b, typemax(Int)) diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 47cb4a99383a0..44e034e233e7f 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -790,12 +790,6 @@ catch end ``` -The `catch` clause is not strictly necessary; when omitted, the default return value is `nothing`. - -```jldoctest -julia> try error() end # Returns nothing -``` - The power of the `try/catch` construct lies in the ability to unwind a deeply nested computation immediately to a much higher level in the stack of calling functions. There are situations where no error has occurred, but the ability to unwind the stack and pass a value to a higher level diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 1b09681198d4f..993400f737044 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1505,7 +1505,8 @@ ((eq? nxt 'end) (list* 'try try-block (or catchv 'false) ;; default to empty catch block in `try ... end` - (or catchb (if finalb 'false '(block))) + (or catchb (if finalb 'false (begin (parser-depwarn s "try without catch or finally" "") + '(block)))) (if finalb (list finalb) '()))) ((and (eq? nxt 'catch) (not catchb)) diff --git a/stdlib/Distributed/src/clusterserialize.jl b/stdlib/Distributed/src/clusterserialize.jl index dcc4f4721dba9..0a796c148b291 100644 --- a/stdlib/Distributed/src/clusterserialize.jl +++ b/stdlib/Distributed/src/clusterserialize.jl @@ -212,6 +212,7 @@ function original_ex(s::ClusterSerializer, ex_str, remote_stktrace) local pid_str = "" try pid_str = string(" from worker ", worker_id_from_socket(s.io)) + catch end stk_str = remote_stktrace ? "Remote" : "Local" diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index bcb9577c2b045..7578420d96449 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -954,6 +954,7 @@ const get_num_threads = function() # anonymous so it will be serialized when cal if Sys.isapple() return tryparse(Cint, get(ENV, "VECLIB_MAXIMUM_THREADS", "1")) end + catch end return nothing diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index 23a22a5997761..20c835bc6527b 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -68,10 +68,10 @@ function versioninfo(io::IO=stdout; verbose::Bool=false, packages::Bool=false) if verbose lsb = "" if Sys.islinux() - try lsb = readchomp(pipeline(`lsb_release -ds`, stderr=devnull)) end + try lsb = readchomp(pipeline(`lsb_release -ds`, stderr=devnull)); catch; end end if Sys.iswindows() - try lsb = strip(read(`$(ENV["COMSPEC"]) /c ver`, String)) end + try lsb = strip(read(`$(ENV["COMSPEC"]) /c ver`, String)); catch; end end if !isempty(lsb) println(io, " ", lsb) @@ -95,7 +95,7 @@ function versioninfo(io::IO=stdout; verbose::Bool=false, packages::Bool=false) if verbose println(io, " Memory: $(Sys.total_memory()/2^30) GB ($(Sys.free_memory()/2^20) MB free)") - try println(io, " Uptime: $(Sys.uptime()) sec") end + try println(io, " Uptime: $(Sys.uptime()) sec"); catch; end print(io, " Load Avg: ") Base.print_matrix(io, Sys.loadavg()') println(io) diff --git a/stdlib/LibGit2/src/LibGit2.jl b/stdlib/LibGit2/src/LibGit2.jl index dcb81fa9c291c..f277145a9833d 100644 --- a/stdlib/LibGit2/src/LibGit2.jl +++ b/stdlib/LibGit2/src/LibGit2.jl @@ -504,6 +504,7 @@ function checkout!(repo::GitRepo, commit::AbstractString = ""; head_name = string(GitHash(head_ref)) end end + catch end # search for commit to get a commit object diff --git a/stdlib/LibGit2/src/commit.jl b/stdlib/LibGit2/src/commit.jl index 5fbd9f185f9d2..ba15a501dbc31 100644 --- a/stdlib/LibGit2/src/commit.jl +++ b/stdlib/LibGit2/src/commit.jl @@ -114,6 +114,7 @@ function commit(repo::GitRepo, msg::AbstractString; if isempty(parent_ids) try # if throws then HEAD not found -> empty repo Base.push!(parent_ids, GitHash(repo, refname)) + catch end end diff --git a/stdlib/LibGit2/src/config.jl b/stdlib/LibGit2/src/config.jl index c0fe4d17aeba8..304e19e25cf24 100644 --- a/stdlib/LibGit2/src/config.jl +++ b/stdlib/LibGit2/src/config.jl @@ -130,7 +130,7 @@ end function get(c::GitConfig, name::AbstractString, default::T) where T res = default - try res = get(T,c,name) end + try res = get(T,c,name); catch; end return res end diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 4fa283eb2c748..b937bd48b762d 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -2694,6 +2694,7 @@ mktempdir() do dir # In some environments, namely Macs, the hostname "macbook.local" is bound # to the external address while "macbook" is bound to the loopback address. pushfirst!(hostnames, replace(gethostname(), r"\..*$" => "")) + catch end loopback = ip"127.0.0.1" diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index b8d4f45bbf906..f670bf5e59b61 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -1201,6 +1201,7 @@ function factorize(A::StridedMatrix{T}) where T if (herm & (T <: Complex)) | sym try return ldlt!(SymTridiagonal(diag(A), diag(A, -1))) + catch end end return lu(Tridiagonal(diag(A, -1), diag(A), diag(A, 1))) diff --git a/stdlib/OldPkg/src/entry.jl b/stdlib/OldPkg/src/entry.jl index b5d05d034cad7..6c9e3faad1a41 100644 --- a/stdlib/OldPkg/src/entry.jl +++ b/stdlib/OldPkg/src/entry.jl @@ -63,6 +63,7 @@ function add(pkg::AbstractString, vers::VersionSet) try LibGit2.fetch(repo) outdated = LibGit2.isdiff(repo, "origin/$branch") ? (:yes) : (:no) + catch end end else diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 2371e4802f479..8385151e737c9 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -2020,6 +2020,7 @@ AnyDict( "^C" => (s,o...)->begin try # raise the debugger if present ccall(:jl_raise_debugger, Int, ()) + catch end cancel_beep(s) move_input_end(s) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index d2ac69050f51d..2a491101627ec 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -217,6 +217,7 @@ function run_frontend(repl::BasicREPL, backend::REPLBackendRef) if isa(e,InterruptException) try # raise the debugger if present ccall(:jl_raise_debugger, Int, ()) + catch end line = "" interrupted = true diff --git a/stdlib/Random/src/RNGs.jl b/stdlib/Random/src/RNGs.jl index 73ff51b1367f5..88737bb9bb169 100644 --- a/stdlib/Random/src/RNGs.jl +++ b/stdlib/Random/src/RNGs.jl @@ -247,6 +247,7 @@ function make_seed() seed = hash(seed, parse(UInt64, read(pipeline(`ifconfig`, `sha1sum`), String)[1:40], base = 16)) + catch end return make_seed(seed) end diff --git a/stdlib/SHA/test/runtests.jl b/stdlib/SHA/test/runtests.jl index eee0c26f5a57b..51ca9308c8acf 100644 --- a/stdlib/SHA/test/runtests.jl +++ b/stdlib/SHA/test/runtests.jl @@ -278,6 +278,7 @@ for f in sha_funcs f(UInt32[0x23467, 0x324775]) warn("Non-UInt8 Arrays should fail") nerrors += 1 + catch end end diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 909ce848e7cc9..d3315761b0ad6 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1065,11 +1065,11 @@ end A = Matrix{Int}(I, 0, 0) S = sparse(A) - iA = try argmax(A) end - iS = try argmax(S) end + iA = try argmax(A); catch; end + iS = try argmax(S); catch; end @test iA === iS === nothing - iA = try argmin(A) end - iS = try argmin(S) end + iA = try argmin(A); catch; end + iS = try argmin(S); catch; end @test iA === iS === nothing end diff --git a/test/char.jl b/test/char.jl index e195d3bececd8..0793ba583b94f 100644 --- a/test/char.jl +++ b/test/char.jl @@ -205,7 +205,7 @@ end @test eof(io) close(io) end - finally + finally rm(file, force=true) end end diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index df7fd2cdcc4eb..9fbf4f754386d 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -1515,6 +1515,7 @@ function h25579(g) try h = -1.25 error("continue at catch block") + catch end return t ? typeof(h) : typeof(h) end diff --git a/test/core.jl b/test/core.jl index 19d5ec8f2e54d..b49a18801836e 100644 --- a/test/core.jl +++ b/test/core.jl @@ -770,6 +770,7 @@ begin global try_finally_glo_after = 1 end global gothere = 1 + catch end @test try_finally_loc_after == 0 @test try_finally_glo_after == 1 @@ -799,7 +800,7 @@ begin @test retfinally() == 5 @test glo == 18 - @test try error() end === nothing + @test try error(); catch; end === nothing end # issue #12806 @@ -1270,6 +1271,7 @@ let function f() try return 1 + catch end end @test f() == 1 @@ -1658,6 +1660,7 @@ try (function() end)(1) # should throw an argument count error @test false +catch end # issue #4526 @@ -1881,6 +1884,7 @@ try # try running this code in a different context that triggers the codegen # assertion `assert(isboxed || v.typ == typ)`. f5142() +catch end primitive type Int5142b 8 end @@ -2282,6 +2286,7 @@ let # This can throw an error, but shouldn't segfault try issue7897!(sa, zeros(10)) + catch end end @@ -2605,6 +2610,7 @@ try mutable struct Foo{T} val::Bar{T} end +catch end GC.gc() redirect_stdout(OLD_STDOUT) diff --git a/test/error.jl b/test/error.jl index d87f2730aa06e..64932a8a80422 100644 --- a/test/error.jl +++ b/test/error.jl @@ -55,7 +55,7 @@ end @test c[1] == 1 c = [0] - ex = try retry(foo_error, check=(s,e)->(s,try e.http_status_code == "503" end != true))(c,2) catch e; e end + ex = try retry(foo_error, check=(s,e)->(s,try e.http_status_code == "503"; catch; end != true))(c,2) catch e; e end @test typeof(ex) == ErrorException @test ex.msg == "foo" @test c[1] == 2 diff --git a/test/read.jl b/test/read.jl index b701e0fdb3b91..8bcf67eb2f9fb 100644 --- a/test/read.jl +++ b/test/read.jl @@ -127,7 +127,7 @@ end open_streams = [] function cleanup() for s_ in open_streams - try close(s_) end + try close(s_); catch; end end empty!(open_streams) for tsk in tasks diff --git a/test/runtests.jl b/test/runtests.jl index 42b5c7d98667e..ae169e84ddcd9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -192,7 +192,7 @@ cd(dirname(@__FILE__)) do isa(e, InterruptException) || rethrow(e) # If the test suite was merely interrupted, still print the # summary, which can be useful to diagnose what's going on - foreach(task->try; schedule(task, InterruptException(); error=true); end, all_tasks) + foreach(task->try; schedule(task, InterruptException(); error=true); catch; end, all_tasks) foreach(wait, all_tasks) finally if isa(stdin, Base.TTY) diff --git a/test/spawn.jl b/test/spawn.jl index 3ede484dca2a3..4500d87528a3e 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -165,6 +165,7 @@ let r, t t = @async begin try wait(r) + catch end p = run(`$sleepcmd 1`, wait=false); wait(p) @test p.exitcode == 0 diff --git a/test/threads.jl b/test/threads.jl index d41611ac7cb4e..960715761de8b 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -465,6 +465,7 @@ function test_load_and_lookup_18020(n) ccall(:jl_load_and_lookup, Ptr{Cvoid}, (Cstring, Cstring, Ref{Ptr{Cvoid}}), "$i", :f, C_NULL) + catch end end end