> On Sep 22, 2016, at 11:28 AM, Jens Persson <j...@bitcycle.com> wrote:
> 
> Yes, but should the compiler silently accept that? And is this issue really 
> related to the other issue?

No, this is a separate issue. The compiler might be able to catch some obvious 
cases, but it'd be impossible to statically prevent all circularities. The 
runtime could probably do a better job detecting this situation, though, and 
give a runtime error instead of just letting the deadlock happen.

-Joe

> /Jens
> 
> On Thu, Sep 22, 2016 at 8:23 PM, Joe Groff <jgr...@apple.com> wrote:
> 
> > On Sep 22, 2016, at 11:23 AM, Jens Persson <j...@bitcycle.com> wrote:
> >
> > Oh, but how can the following (earlier mentioned) example have anything to 
> > do with Script-mode top-level locals being treated as globals?
> >
> > Create "AnotherFile.swift" containing:
> > func f() -> Int { return a }
> > let a = f()
> 
> In this case, you have a deadlock, since the initialization of `a` depends on 
> its own initialization.
> 
> -Joe
> 
> > Create "main.swift" containing:
> > print(a)
> >
> > Compile. Run. For ever. At zero % CPU.
> >
> > /Jens
> >
> >
> >
> > On Thu, Sep 22, 2016 at 8:03 PM, Jens Persson <j...@bitcycle.com> wrote:
> > Thank you for the thorough explanation!
> > /Jens
> >
> > On Thu, Sep 22, 2016 at 7:28 PM, Jordan Rose <jordan_r...@apple.com> wrote:
> > Yep, it really is a long-standing bug. Script-mode top-level locals are 
> > treated as globals (module-scope bindings) by the compiler, but their 
> > initial bindings are evaluated eagerly instead of lazily (as you’d want in 
> > a script). Taken together, this means that you can get this completely 
> > unsafe behavior.
> >
> > So, why is ‘a’ accepted but ‘b’ not in your original example?
> >
> >> func foo() -> Int { return b }
> >> let a = 1
> >> let b = 2
> >> print(foo())
> >
> > The secret to the current behavior is that script mode is executed 
> > interactively, instead of parsing it all up front. To make things a little 
> > better, it actually parses any number of declarations until it sees 
> > something it actually needs to execute—a statement or a declaration with an 
> > initial value expression. This allows for recursive functions while still 
> > being “live”.
> >
> > The consequence here is that one top-level binding after a series of 
> > functions may be visible. This is obviously not optimal.
> >
> > To fix this, we should:
> >
> > - Distinguish between script-mode top-level locals and module-scope 
> > variables that happen to be declared. My personal preference is to treat 
> > anything with explicit access control as a normal lazy global and anything 
> > without access as a top-level local.
> >
> > - Consider parsing everything up front, even if we don’t type-check it, so 
> > that we can say “use of ‘b’ before it’s initialized” instead of “undeclared 
> > name ‘b’”
> >
> > Note that we do need to be conservative here. This code should continue to 
> > be rejected, even though ‘f’ doesn’t refer to ‘local’ directly, because 
> > calling ‘f' would be dangerous before the initialization of ‘local':
> >
> > internal func f() -> Int {
> >   return g()
> > }
> > // more code here
> >
> > let local = 42
> > private func g() -> Int {
> >   return local
> > }
> >
> > Thanks for bringing this up, if only so I have an opportunity to write out 
> > the issue. :-)
> > Jordan
> >
> >
> >> On Sep 21, 2016, at 23:04, Jens Persson <j...@bitcycle.com> wrote:
> >>
> >> Did you see the other code examples that came up in that twitter 
> >> conversations?
> >> For example:
> >>
> >> This worrying little program compiles:
> >> func f() -> Int {
> >>     return a
> >> }
> >> let a = f()
> >>
> >>
> >> It also compiles if you print(a) at the end, and it will print 0.
> >>
> >> If we replace Int with [Int] it will still compile but crash when run.
> >>
> >> And also this:
> >>
> >> AnotherFile.swift containing:
> >> func f() -> Int {
> >>     return a
> >> }
> >> let a = f()
> >>
> >> main.swift containing
> >> print(a)
> >>
> >> Compile, run (for eternity, at 0% CPU).
> >>
> >> /Jens
> >>
> >>
> >> On Thu, Sep 22, 2016 at 3:13 AM, Joe Groff <jgr...@apple.com> wrote:
> >>
> >> > On Sep 21, 2016, at 2:22 PM, Jens Persson via swift-users 
> >> > <swift-users@swift.org> wrote:
> >> >
> >> > // This little Swift program compiles (and runs) fine:
> >> >
> >> > func foo() -> Int { return a }
> >> > let a = 1
> >> > let b = 2
> >> > print(foo())
> >> >
> >> > But if `foo()` returns `b` instead of `a`, I get this compile time error:
> >> > "Use of unresolved identifier `b`"
> >>
> >> This looks like a bug to me (cc-ing Jordan, who's thought about global 
> >> scoping issues more than me). In "script mode", it shouldn't be possible 
> >> to refer to a variable before its initialization is executed. However, the 
> >> way this is currently modeled is…problematic, to say the least, among 
> >> other reasons because script globals are still visible to "library" files 
> >> in the same module.
> >>
> >> -Joe
> >>
> >
> >
> >
> 
> 

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to