@@ -95,8 +95,6 @@ enclosing_lambda(ctx, scope::ScopeInfo) = ctx.scopes[scope.lambda_id]
9595parent (ctx, scope:: ScopeInfo ) = is_top_scope (scope) ? nothing :
9696 ctx. scopes[scope. parent_id]
9797
98- enclosing_lambda (ctx, lb:: LambdaBindings ) = ctx. scopes[lb. scope_id]
99-
10098_var_str (v) = v === :local ? " local variable" :
10199 v === :global ? " global variable" :
102100 v === :argument ? " argument" :
@@ -112,7 +110,7 @@ function maybe_declare_in_scope!(ctx, scope::ScopeInfo, ex, new_k::Symbol)
112110 if kind (ex) === K " BindingId"
113111 bid = ex. var_id
114112 @assert get_binding (ctx, bid). kind === new_k
115- record_lambda_var! (ctx, scope, get_binding (ctx, bid), false )
113+ record_lambda_var! (ctx, scope, get_binding (ctx, bid), capt = false )
116114 return bid
117115 elseif kind (ex) === K " Placeholder"
118116 return nothing
@@ -130,7 +128,7 @@ function maybe_declare_in_scope!(ctx, scope::ScopeInfo, ex, new_k::Symbol)
130128 elseif old_k === new_k
131129 (new_k === :global || new_k === :local ) && return bid
132130 throw (LoweringError (ex, " function $(_var_str (new_k)) name not unique" ))
133- # See note in test/scopes.jl
131+ # See note in test/scopes.jl: "globals may overlap args or sparams"
134132 # elseif new_k === :global && old_k in (:argument, :static_parameter)
135133 # declare_in_scope!(ctx, scope, ex, :global)
136134 else
@@ -140,26 +138,27 @@ function maybe_declare_in_scope!(ctx, scope::ScopeInfo, ex, new_k::Symbol)
140138 end
141139end
142140
141+ # globals are added to both `scope` and the top scope
143142function declare_in_scope! (ctx, scope:: ScopeInfo , ex, bk:: Symbol ; kws... )
144143 nk = NameKey (ex)
145144 if bk === :global
146- home_scope = top_scope (ctx)
145+ declaration_scope = top_scope (ctx)
147146 mod = ctx. scope_layers[ex. scope_layer]. mod
148147 else
149- home_scope = scope
148+ declaration_scope = scope
150149 mod = nothing
151150 end
152151 b = _new_binding (ctx, ex, nk. name, bk; mod, kws... )
153- home_scope . vars[nk] = b. id
152+ declaration_scope . vars[nk] = b. id
154153 scope. vars[nk] = b. id
155154 @assert ! haskey (enclosing_lambda (ctx, scope). locals_capt, b. id)
156- record_lambda_var! (ctx, scope, b, false )
155+ record_lambda_var! (ctx, scope, b, capt = false )
157156 return b. id
158157end
159158
160159# If `b` is local and not yet recorded in the lambda bindings, mark it as
161160# `capt`. Also, (if `capt==true`), add it to any parent lambdas.
162- function record_lambda_var! (ctx, scope:: Union{ ScopeInfo, LambdaBindings} , b, capt)
161+ function record_lambda_var! (ctx, scope:: ScopeInfo , b; capt)
163162 if b. kind === :global || b. is_ssa
164163 return
165164 end
@@ -169,7 +168,7 @@ function record_lambda_var!(ctx, scope::Union{ScopeInfo, LambdaBindings}, b, cap
169168 b. is_captured = capt
170169 s2 = parent (ctx, lam)
171170 if capt && ! isnothing (s2)
172- record_lambda_var! (ctx, s2, b, true )
171+ record_lambda_var! (ctx, s2, b, capt = true )
173172 end
174173 end
175174end
@@ -262,7 +261,9 @@ function enter_scope!(ctx, ex)
262261 # ---------------------------------------------------------------------------
263262 # Find assignment targets, possibly introducing implicit locals and globals
264263 for (bid, node_id) in sort! (collect (scope. binding_assignments))
265- # mutable nameless bindings may be introduced in desugaring
264+ # Mutable nameless bindings may be introduced in desugaring. These
265+ # should be capturable, and may be local to the nearest lambda or
266+ # global. Desugaring should ensure these are never used undef.
266267 maybe_declare_in_scope! (ctx, scope, SyntaxTree (ctx. graph, node_id),
267268 get_binding (ctx, bid). kind)
268269 end
@@ -302,7 +303,7 @@ function enter_scope!(ctx, ex)
302303 throw (LoweringError (ex, " cannot overwrite a static parameter" ))
303304 elseif b. kind === :local || b. kind === :argument
304305 # unambiguous assignment to existing variable
305- record_lambda_var! (ctx, scope, b, true )
306+ record_lambda_var! (ctx, scope, b, capt = true )
306307 end
307308 end
308309
@@ -320,8 +321,10 @@ function add_local_decls!(ctx, stmts, srcref, scope)
320321 end
321322end
322323
323- function _resolve_scopes (ctx, ex:: SyntaxTree , @nospecialize (scope))
324+ function _resolve_scopes (ctx, ex:: SyntaxTree ,
325+ @nospecialize (scope:: Union{Nothing, ScopeInfo} ))
324326 k = kind (ex)
327+ @assert scope isa ScopeInfo || k === K " lambda"
325328 if k == K " Identifier"
326329 b = resolve_name (ctx, ex)
327330 # Unresolved names are assumed global
@@ -330,10 +333,10 @@ function _resolve_scopes(ctx, ex::SyntaxTree, @nospecialize(scope))
330333 b = get_binding (ctx, gid)
331334 end
332335 # Locals not present in the current lambda need capturing
333- record_lambda_var! (ctx, scope, b, true )
336+ record_lambda_var! (ctx, scope, b, capt = true )
334337 newleaf (ctx, ex, K " BindingId" , b. id)
335338 elseif k === K " BindingId"
336- record_lambda_var! (ctx, scope, get_binding (ctx, ex), true )
339+ record_lambda_var! (ctx, scope, get_binding (ctx, ex), capt = true )
337340 ex
338341 elseif k == K " softscope"
339342 makeleaf (ctx, ex, K " TOMBSTONE" )
@@ -494,6 +497,8 @@ function _resolve_scopes(ctx, ex::SyntaxTree, @nospecialize(scope))
494497 @assert kind (resolved[1 ]) === K " BindingId"
495498 if get_binding (ctx, resolved[1 ]. var_id). kind === :local
496499 throw (LoweringError (ex, " unsupported `const` declaration on local variable" ))
500+ elseif ! is_top_scope (enclosing_lambda (ctx, scope))
501+ throw (LoweringError (ex, " unsupported `const` inside function" ))
497502 end
498503 resolved
499504 elseif k == K " assign_or_constdecl_if_global"
@@ -590,7 +595,8 @@ function analyze_variables!(ctx, ex)
590595 b. is_read = true
591596 # The type of typed locals is invisible in the previous pass,
592597 # but is filled in here.
593- record_lambda_var! (ctx, ctx. lambda_bindings, b, true )
598+ scope = ctx. scopes[ctx. lambda_bindings. scope_id]
599+ record_lambda_var! (ctx, scope, b, capt= true )
594600 @assert b. kind === :global || b. is_ssa || haskey (ctx. lambda_bindings. locals_capt, b. id)
595601 elseif k == K " Identifier"
596602 @assert false
@@ -611,7 +617,8 @@ function analyze_variables!(ctx, ex)
611617 if kind (lhs) != K " Placeholder"
612618 b = get_binding (ctx, lhs)
613619 add_assign! (b)
614- record_lambda_var! (ctx, ctx. lambda_bindings, b, true )
620+ scope = ctx. scopes[ctx. lambda_bindings. scope_id]
621+ record_lambda_var! (ctx, scope, b, capt= true )
615622 if ! isnothing (b. type)
616623 # Assignments introduce a variable's type later during closure
617624 # conversion, but we must model that explicitly here.
0 commit comments