Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/ast.scm
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@
(define (vinfo:never-undef v) (< 0 (logand (caddr v) 4)))
(define (vinfo:read v) (< 0 (logand (caddr v) 8)))
(define (vinfo:sa v) (< 0 (logand (caddr v) 16)))
(define (vinfo:nospecialize v) (< 0 (logand (caddr v) 128)))
(define (set-bit x b val) (if val (logior x b) (logand x (lognot b))))
;; record whether var is captured
(define (vinfo:set-capt! v c) (set-car! (cddr v) (set-bit (caddr v) 1 c)))
Expand All @@ -507,6 +508,7 @@
;; occurs undef: mask 32
;; whether var is called (occurs in function call head position)
(define (vinfo:set-called! v a) (set-car! (cddr v) (set-bit (caddr v) 64 a)))
(define (vinfo:set-nospecialize! v c) (set-car! (cddr v) (set-bit (caddr v) 128 c)))

(define var-info-for assq)

Expand Down
44 changes: 18 additions & 26 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -3492,10 +3492,15 @@
(define (analyze-vars e env captvars sp tab)
(if (or (atom? e) (quoted? e))
(begin
(if (symbol? e)
(let ((vi (get tab e #f)))
(if vi
(vinfo:set-read! vi #t))))
(cond
((symbol? e)
(let ((vi (get tab e #f)))
(if vi
(vinfo:set-read! vi #t))))
((nospecialize-meta? e)
(let ((vi (get tab (caddr e) #f)))
(if vi
(vinfo:set-nospecialize! vi #t)))))
e)
(case (car e)
((local-def) ;; a local that we know has an assignment that dominates all usages
Expand Down Expand Up @@ -3594,21 +3599,6 @@ f(x) = yt(x)
(call (core _typebody!) (false) ,s (call (core svec) ,@types))
(return (null)))))))))

(define (type-for-closure name fields super)
(let ((s (make-ssavalue)))
`((thunk ,(linearize `(lambda ()
(() () 0 ())
(block (global ,name)
(= ,s (call (core _structtype) (thismodule) (inert ,name) (call (core svec))
(call (core svec) ,@(map quotify fields))
(call (core svec))
(false) ,(length fields)))
(call (core _setsuper!) ,s ,super)
(const (globalref (thismodule) ,name) ,s)
(call (core _typebody!) (false) ,s
(call (core svec) ,@(map (lambda (v) '(core Box)) fields)))
(return (null)))))))))

;; better versions of above, but they get handled wrong in many places
;; need to fix that in order to handle #265 fully (and use the definitions)

Expand Down Expand Up @@ -4022,6 +4012,10 @@ f(x) = yt(x)
(let ((cv (assq v (cadr (lam:vinfo lam)))))
(and cv (vinfo:asgn cv) (vinfo:capt cv)))))

(define (is-var-nospecialize? v lam)
(let ((vi (assq v (car (lam:vinfo lam)))))
(and vi (vinfo:nospecialize vi))))

(define (toplevel-preserving? e)
(and (pair? e) (memq (car e) '(if elseif block trycatch tryfinally trycatchelse))))

Expand Down Expand Up @@ -4313,16 +4307,14 @@ f(x) = yt(x)
(closure-param-syms (map (lambda (s) (make-ssavalue)) closure-param-names))
(typedef ;; expression to define the type
(let* ((fieldtypes (map (lambda (v)
(if (is-var-boxed? v lam)
'(core Box)
(make-ssavalue)))
(cond ((is-var-boxed? v lam) '(core Box))
((is-var-nospecialize? v lam) (vinfo:type (assq v (car (lam:vinfo lam)))))
(else (make-ssavalue))))
capt-vars))
(para (append closure-param-syms
(filter ssavalue? fieldtypes)))
(fieldnames (append closure-param-names (filter (lambda (v) (not (is-var-boxed? v lam))) capt-vars))))
(if (null? para)
(type-for-closure type-name capt-vars '(core Function))
(type-for-closure-parameterized type-name para fieldnames capt-vars fieldtypes '(core Function)))))
(type-for-closure-parameterized type-name para fieldnames capt-vars fieldtypes '(core Function))))
(mk-method ;; expression to make the method
(if short '()
(let* ((iskw ;; TODO jb/functions need more robust version of this
Expand Down Expand Up @@ -4352,7 +4344,7 @@ f(x) = yt(x)
(P (append
closure-param-names
(filter identity (map (lambda (v ve)
(if (is-var-boxed? v lam)
(if (or (is-var-boxed? v lam) (is-var-nospecialize? v lam))
#f
`(call (core _typeof_captured_variable) ,ve)))
capt-vars var-exprs)))))
Expand Down
9 changes: 9 additions & 0 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4330,3 +4330,12 @@ let ex = @Meta.lower function return_my_method(); 1; end
code[end] = Core.ReturnNode(Core.SSAValue(idx))
@test isa(Core.eval(@__MODULE__, ex), Method)
end

# Capturing a @nospecialize argument should result in an Any field in the closure
module NoSpecClosure
K(@nospecialize(x)) = y -> x
end
let f = NoSpecClosure.K(1)
@test f(2) == 1
@test typeof(f).parameters == Core.svec()
end