diff --git a/base/views.jl b/base/views.jl index d83005c86f46c..6898abdda1471 100644 --- a/base/views.jl +++ b/base/views.jl @@ -123,20 +123,21 @@ julia> A ``` """ macro view(ex) + Meta.isexpr(ex, :ref) || throw(ArgumentError( + "Invalid use of @view macro: argument must be a reference expression A[...].")) + ex = replace_ref_begin_end!(ex) + # NOTE We embed `view` as a function object itself directly into the AST. + # By doing this, we prevent the creation of function definitions like + # `view(A, idx) = xxx` in cases such as `@view(A[idx]) = xxx.` if Meta.isexpr(ex, :ref) - ex = replace_ref_begin_end!(ex) - if Meta.isexpr(ex, :ref) - ex = Expr(:call, view, ex.args...) - else # ex replaced by let ...; foo[...]; end - if !(Meta.isexpr(ex, :let) && Meta.isexpr(ex.args[2], :ref)) - error("invalid expression") - end - ex.args[2] = Expr(:call, view, ex.args[2].args...) - end - Expr(:&&, true, esc(ex)) + ex = Expr(:call, view, ex.args...) + elseif Meta.isexpr(ex, :let) && (arg2 = ex.args[2]; Meta.isexpr(arg2, :ref)) + # ex replaced by let ...; foo[...]; end + ex.args[2] = Expr(:call, view, arg2.args...) else - throw(ArgumentError("Invalid use of @view macro: argument must be a reference expression A[...].")) + error("invalid expression") end + return esc(ex) end ############################################################################ diff --git a/test/subarray.jl b/test/subarray.jl index ad68496e38245..40877d842df76 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -937,3 +937,21 @@ end v = view(1:2, r) @test v == view(1:2, collect(r)) end + +# https://github.com/JuliaLang/julia/pull/53064 +# `@view(A[idx]) = xxx` should raise syntax error always +@test try + Core.eval(@__MODULE__, :(@view(A[idx]) = 2)) + false +catch err + err isa ErrorException && startswith(err.msg, "syntax:") +end +module Issue53064 +import Base: view +end +@test try + Core.eval(Issue53064, :(@view(A[idx]) = 2)) + false +catch err + err isa ErrorException && startswith(err.msg, "syntax:") +end