diff --git a/base/boot.jl b/base/boot.jl index 5d40191ecab21..50b46758efe2e 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -985,6 +985,14 @@ Unsigned(x::Union{Float16, Float32, Float64, Bool}) = UInt(x) Integer(x::Integer) = x Integer(x::Union{Float16, Float32, Float64}) = Int(x) +# During definition of struct type `B`, if an `A.B` expression refers to +# the eventual global name of the struct, then return the partially-initialized +# type object. +# TODO: remove. This is a shim for backwards compatibility. +function struct_name_shim(@nospecialize(x), name::Symbol, mod::Module, @nospecialize(t)) + return x === mod ? t : getfield(x, name) +end + # Binding for the julia parser, called as # # Core._parse(text, filename, lineno, offset, options) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index b48cb48bf0b79..7acc8a1954bc5 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -963,6 +963,19 @@ (ctors-min-initialized (car expr)) (ctors-min-initialized (cdr expr))))) +(define (insert-struct-shim field-types name) + (map (lambda (x) + (expr-replace (lambda (y) + (and (length= y 3) (eq? (car y) '|.|) + (or (equal? (caddr y) `(quote ,name)) + (equal? (caddr y) `(inert ,name))))) + x + (lambda (y) + `(call (core struct_name_shim) + ,(cadr y) ,(caddr y) + (thismodule) ,name)))) + field-types)) + (define (struct-def-expr- name params bounds super fields0 mut) (receive (fields defs) (separate eventually-decl? fields0) @@ -1022,11 +1035,9 @@ prev params) (quote parameters)))) - '())) - ;; otherwise do an assignment to trigger an error - (const (globalref (thismodule) ,name) ,name))) - (const (globalref (thismodule) ,name) ,name)) - (call (core _typebody!) ,name (call (core svec) ,@field-types)) + '()))))) + (call (core _typebody!) ,name (call (core svec) ,@(insert-struct-shim field-types name))) + (const (globalref (thismodule) ,name) ,name) (null))) ;; "inner" constructors (scope-block diff --git a/src/utils.scm b/src/utils.scm index 97464b9a14e5a..79e3a280b9886 100644 --- a/src/utils.scm +++ b/src/utils.scm @@ -48,6 +48,13 @@ (any (lambda (y) (expr-contains-p p y filt)) (cdr expr)))))) +(define (expr-replace p expr repl) + (cond ((p expr) (repl expr)) + ((and (pair? expr) (not (quoted? expr))) + (cons (car expr) + (map (lambda (x) (expr-replace p x repl)) (cdr expr)))) + (else expr))) + ;; find all subexprs satisfying `p`, applying `key` to each one (define (expr-find-all p expr key (filt (lambda (x) #t))) (if (filt expr) diff --git a/test/core.jl b/test/core.jl index 4b5a674ba44b3..1b36db466ce19 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7669,7 +7669,7 @@ end end @test fieldtypes(M36104.T36104) == (Vector{M36104.T36104},) @test_throws ErrorException("expected") @eval(struct X36104; x::error("expected"); end) -@test @isdefined(X36104) +@test !@isdefined(X36104) struct X36104; x::Int; end @test fieldtypes(X36104) == (Int,) primitive type P36104 8 end