Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type annotations in global scope #964

Closed
maleadt opened this issue Jun 22, 2012 · 15 comments · Fixed by #43671
Closed

Type annotations in global scope #964

maleadt opened this issue Jun 22, 2012 · 15 comments · Fixed by #43671
Assignees
Labels
performance Must go faster

Comments

@maleadt
Copy link
Member

maleadt commented Jun 22, 2012

Is it expected behaviour that I can't type annotate variable declarations in global scope? Example:

julia> foo::Float = 0.1
foo not defined

julia> function bar()
         foo::Float = 0.1
       end

julia> bar()
0.1
@Keno
Copy link
Member

Keno commented Jun 22, 2012

It is expected insofar as that we are aware of the issue. Currently using global variables kills performance specifically because they are of unknown type. Type annotations on global variables are a planned feature but IIRC, there was some technical limitation (maybe @JeffBezanson can go into detail on that).

Hope that helps.

@JeffBezanson
Copy link
Sponsor Member

Planned feature.

@StefanKarpinski
Copy link
Sponsor Member

Further plan: make globals type-const by default. That is, writing

glb = x

is equivalent to this:

glb::typeof(x)
glb = x

unless there was some prior declaration of the type of glb. If you want an global that can hold different types of values, you must explicitly annotate that:

glb = 1      # not const but has to be Int
glb::Any     # can hold anything
glb::String  # can hold any kind of string

This approach will alleviate the horrific performance trap that global variables currently constitute. Most globals are actually constant and they hardly ever change type.

@stevengj
Copy link
Member

The current workaround is to declare globals as const, but this is unsatisfactory in many situations where the value of the global may change but its type does not.

I keep running into this problem in modules, in which the module needs to do some run-time initialization and cache the results in a global, but the only way to do this without screwing the compiler seems to be to annotate every place that the global is used, which is annoying.

Please don't let this issue fall off the queue.

@dmbates
Copy link
Member

dmbates commented Feb 15, 2013

I'm not sure if this is entirely kosher but I have found that I can declare an array as const and still change the values of elements of the array. In the CHOLMOD code all the C functions have an argument which is a pointer to this horribly long cholmod_common struct and many of the optional arguments are changed by changing values in this struct. The way this is done in the extras/suitesparse.jl file in the db/suitesparse branch is to declare a const Uint8 array of the appropriate length and change the values of some parts of this array using reinterpret.

@StefanKarpinski
Copy link
Sponsor Member

That is completely kosher – the only thing that's const is the binding. The array itself is still a mutable thing. However, we still need this stuff.

@stevengj
Copy link
Member

A possibly related problem: you can't usefully declare type annotations with the global keyword either. e.g.

x=3
baz(y::Int) = begin
    global x::Int
    x+y
end

is accepted by the parser, but the type annotation on the global statement doesn't seem to accomplish much. If you run disassemble(baz, (Int,)), you will find that it is still nowhere near as efficient as baz(y::Int) = x::Int + y.

@quinnj
Copy link
Member

quinnj commented Jun 13, 2014

Hearty bump. I've recently been working on porting type-stability-sensitive C++ code where I use the pattern of:

function foo(args...)
    init::Uint64 = 1 # need to ensure init::Uint64 throughout function
...

But then when trying to debug, I can't run the lines one by one because just running

In  [99]:  init::Uint64 = 1

Out [99]: ERROR: init not defined
while loading In[99], in expression starting on line 1

It just makes type annotating a hassle because it's the right way to ensure the type stability of a variable, yet I can't switch between using it in function vs. global scope.

@cdsousa
Copy link
Contributor

cdsousa commented Jun 16, 2014

I've came to discover yet another workaround: using 0-dimensional arrays to store single boxed immutables:

const flag = Array(Bool)
.....
flag[] = true
......
if flag[] .....

About the "globals type-const by default" I think that not only it does not solve all problems but it will also break a little the REPL user experience...

@StefanKarpinski
Copy link
Sponsor Member

Yes, that's a bit of a problem. The REPL experience would not be good with type-const by default.

vtjnash added a commit that referenced this issue Jul 15, 2016
also deprecates `global x::T` meaning a typeassert

also fix a bug where a type-assert was considered to be effect-free,
causing it to be converted into a local variable declaration

ref #964
vtjnash added a commit that referenced this issue Jul 18, 2016
also deprecates `global x::T` meaning a typeassert

also fix a bug where a type-assert was considered to be effect-free,
causing it to be quasi-converted into a local variable declaration

ref #964
vtjnash added a commit that referenced this issue Jul 21, 2016
also deprecates `global x::T` meaning a typeassert

also fix a bug where a type-assert was considered to be effect-free,
causing it to be quasi-converted into a local variable declaration

ref #964
JeffBezanson pushed a commit that referenced this issue Jul 21, 2016
deprecate `x::T` as type declaration syntax, ref #16071

deprecate `x::T = 0` where x is global and `global x::T` meaning typeassert, ref #964

also fix a bug where a typeassert was considered to be effect-free,
causing it to be quasi-converted into a local variable declaration

fix a bug in env.jl where a typeassert was intended
mfasi pushed a commit to mfasi/julia that referenced this issue Sep 5, 2016
deprecate `x::T` as type declaration syntax, ref JuliaLang#16071

deprecate `x::T = 0` where x is global and `global x::T` meaning typeassert, ref JuliaLang#964

also fix a bug where a typeassert was considered to be effect-free,
causing it to be quasi-converted into a local variable declaration

fix a bug in env.jl where a typeassert was intended
@JeffBezanson JeffBezanson modified the milestones: 2.0+, 1.0 May 2, 2017
@StefanKarpinski
Copy link
Sponsor Member

StefanKarpinski commented Jun 28, 2017

I'm not sure why this is considered breaking. Just because we ignore it now? If so, can we at least make this syntax an error on globals so that it is no longer breaking and can be added in 1.1 instead of having to wait until 2.0? Alternatively, this just doesn't seem all that hard to implement.

@mbauman
Copy link
Sponsor Member

mbauman commented Jun 28, 2017

This is no longer breaking after #17445.

@mbauman mbauman removed the kind:breaking This change will break code label Jun 28, 2017
@StefanKarpinski StefanKarpinski modified the milestones: 1.x, 2.0+ Jul 13, 2017
@xgdgsc
Copy link
Contributor

xgdgsc commented May 13, 2020

Sometimes I just copy code from other people' s module to see the output. Can we make this a warning instead of error?

@StefanKarpinski
Copy link
Sponsor Member

Or better yet: add proper support for it.

@oscardssmith
Copy link
Member

If someone is willing to give me some guidance, I'll happily make the PR to fix this.

simeonschaub added a commit that referenced this issue Jan 5, 2022
This is an initial proposal for supporting typed globals based on #964.
The syntax for this is either `global x::T` or just doing `x::T = 1` in
global scope. It is even supported to add these annotations to globals
from inside functions. The type declaration will then be applied when
the method is defined and inside the function body conversion to the
specified type will happen automatically, similar to type annotations
for local variables.

This conversion will not be applied if the assignment is not done inside
the same scope of the type annotation however. This could potentially be
supported as well, but the problem is that this would mean any
assignment to a global variable - typed or not - would need to go
through a call to `convert` first, since lowering can't know if a given
binding already has a type annotation. This probably wouldn't be a good
thing for latency and sysimage size and would add an invalidation risk.

It is allowed to refine a type annotation, but there will be a warning.
Widening the type or changing it to any other type that is not a subtype
of the previous one is an error, since that could cause cached compiled
code to become invalid.
simeonschaub added a commit that referenced this issue Jan 5, 2022
This is an initial proposal for supporting typed globals based on #43455.
The syntax for this is either `global x::T` or just doing `x::T = 1` in
global scope. It is even supported to add these annotations to globals
from inside functions. The type declaration will then be applied when
the method is defined and inside the function body conversion to the
specified type will happen automatically, similar to type annotations
for local variables.

This conversion will not be applied if the assignment is not done inside
the same scope of the type annotation however. This could potentially be
supported as well, but the problem is that this would mean any
assignment to a global variable - typed or not - would need to go
through a call to `convert` first, since lowering can't know if a given
binding already has a type annotation. This probably wouldn't be a good
thing for latency and sysimage size and would add an invalidation risk.

It is allowed to refine a type annotation, but there will be a warning.
Widening the type or changing it to any other type that is not a subtype
of the previous one is an error, since that could cause cached compiled
code to become invalid.

replaces #43455
closes #964
simeonschaub added a commit that referenced this issue Jan 8, 2022
This is an initial proposal for supporting typed globals based on #43455.
The syntax for this is either `global x::T` or just doing `x::T = 1` in
global scope. It is even supported to add these annotations to globals
from inside functions. The type declaration will then be applied when
the method is defined and inside the function body conversion to the
specified type will happen automatically, similar to type annotations
for local variables.

This conversion will not be applied if the assignment is not done inside
the same scope of the type annotation however. This could potentially be
supported as well, but the problem is that this would mean any
assignment to a global variable - typed or not - would need to go
through a call to `convert` first, since lowering can't know if a given
binding already has a type annotation. This probably wouldn't be a good
thing for latency and sysimage size and would add an invalidation risk.

It is allowed to refine a type annotation, but there will be a warning.
Widening the type or changing it to any other type that is not a subtype
of the previous one is an error, since that could cause cached compiled
code to become invalid.

replaces #43455
closes #964
JeffBezanson pushed a commit that referenced this issue Feb 8, 2022
add type declarations to global bindings

replaces #43455
closes #964

Co-authored-by: Miguel Raz Guzmán Macedo <miguelraz@gmail.com>
antoine-levitt pushed a commit to antoine-levitt/julia that referenced this issue Feb 17, 2022
add type declarations to global bindings

replaces JuliaLang#43455
closes JuliaLang#964

Co-authored-by: Miguel Raz Guzmán Macedo <miguelraz@gmail.com>
LilithHafner pushed a commit to LilithHafner/julia that referenced this issue Feb 22, 2022
add type declarations to global bindings

replaces JuliaLang#43455
closes JuliaLang#964

Co-authored-by: Miguel Raz Guzmán Macedo <miguelraz@gmail.com>
LilithHafner pushed a commit to LilithHafner/julia that referenced this issue Mar 8, 2022
add type declarations to global bindings

replaces JuliaLang#43455
closes JuliaLang#964

Co-authored-by: Miguel Raz Guzmán Macedo <miguelraz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Must go faster
Projects
None yet
Development

Successfully merging a pull request may close this issue.