From 1ccb618cae7ab30c7279cf13b4c76ef558f46203 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 18 May 2022 04:01:28 -0400 Subject: [PATCH] fix #45024, lost `expected assignment after const` error (#45344) (cherry picked from commit 2d40898a0bb09bbde7dae36cacc6ed5e23c7c0fa) --- src/julia-parser.scm | 18 ++++++++++++++++-- test/syntax.jl | 10 ++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 97a11df701a37..22d677b8bdaa2 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1355,11 +1355,19 @@ (list 'where (rewrap-where x (cadr w)) (caddr w)) x)) +(define (parse-struct-field s) + (let ((tok (peek-token s))) + ;; allow `const x` only as a struct field + (if (eq? tok 'const) + (begin (take-token s) + `(const ,(parse-eq s))) + (parse-eq s)))) + (define (parse-struct-def s mut? word) (if (reserved-word? (peek-token s)) (error (string "invalid type name \"" (take-token s) "\""))) (let ((sig (parse-subtype-spec s))) - (begin0 (list 'struct (if mut? '(true) '(false)) sig (parse-block s)) + (begin0 (list 'struct (if mut? '(true) '(false)) sig (parse-block s parse-struct-field)) (expect-end s word)))) ;; consume any number of line endings from a token stream @@ -1456,7 +1464,13 @@ `(const ,expr) expr))) ((const) - `(const ,(parse-eq s))) + (let ((assgn (parse-eq s))) + (if (not (and (pair? assgn) + (or (eq? (car assgn) '=) + (eq? (car assgn) 'global) + (eq? (car assgn) 'local)))) + (error "expected assignment after \"const\"") + `(const ,assgn)))) ((function macro) (let* ((loc (line-number-node s)) diff --git a/test/syntax.jl b/test/syntax.jl index df5ed7babbffd..6ed3e7ca59ad7 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -3278,3 +3278,13 @@ demo44723()::Any = Base.Experimental.@opaque () -> true ? 1 : 2 # issue #45162 f45162(f) = f(x=1) @test first(methods(f45162)).called != 0 + +# issue #45024 +@test_throws ParseError("expected assignment after \"const\"") Meta.parse("const x") +@test_throws ParseError("expected assignment after \"const\"") Meta.parse("const x::Int") +# these cases have always been caught during lowering, since (const (global x)) is not +# ambiguous with the lowered form (const x), but that could probably be changed. +@test Meta.lower(@__MODULE__, :(global const x)) == Expr(:error, "expected assignment after \"const\"") +@test Meta.lower(@__MODULE__, :(global const x::Int)) == Expr(:error, "expected assignment after \"const\"") +@test Meta.lower(@__MODULE__, :(const global x)) == Expr(:error, "expected assignment after \"const\"") +@test Meta.lower(@__MODULE__, :(const global x::Int)) == Expr(:error, "expected assignment after \"const\"")