> 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