Narrowing typed globals

When locking a non-concrete type to a global, it may be reasonable to allow narrowing the locked type to a subtype.
Consider:

julia> s::Number = 3
3

julia> s::Int64 = 5
ERROR: cannot set type for global Main.s. It already has a value or is already set to a different type.
Stacktrace:
 [1] top-level scope
   @ REPL[4]:1

julia> s = 1.2
1.2

The suggestion is to allow s::Int64 = 5 to proceed without error and lock s into Int64. In this case, the last s = 1.2 would error.

In this way, a global

t = 5

can be essentially the same as:

t::Any = 5

which might be a nice way to think of unlocked globals.

(coded in Julia 1.10)

There may be issues about recompilations needed (if loosely locked globals are narrowed), but that may be a price to pay for allowing interactive development with untyped globals and then getting the speed of typed globals without leaving the REPL.

Anyway, raising this idea to hear the problems with it…

IMO this would break code too easily, and having multiple locations where a global variable can declare different types is too difficult to track across multiple files.

Assuming from your words that you disallow the reverse widening of the declared type, so I’ll focus on the narrowing. Here’s an example of very simple code breaking:

s::Number = 3
function update_s(x)
  global s
  s += x
end
update_s(1.5) # s == 4.5
s::Int64 = 5
update_s(1.5) # InexactError

In more complex code scattered across multiple files, this is too much of a problem to deal with. The only way this wouldn’t be a problem is if no code was ever written between the 2 type declarations, in which case you could’ve easily written the right type at the beginning or discarded it for another variable that declares the narrow type.

1 Like