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
[SR-2616] 'lazy' keyword results in "Type of expression is ambiguous without more context" #45221
Comments
Mysterious. @rudkx, any ideas? |
The diagnostic is lousy but this is an unanticipated type checking failure which is why. The type checker builds a slightly different constraint system in the lazy case and we fail on it. It's going to take some debugging to understand why. |
I've debugging this before, because it is the root cause of some compiler_crashers. The problem is that if the lazy property does not declare a type, we type check it twice, once to infer the type, and the second time as part of the body of the getter method. The second time often fails. We need to stop synthesizing a getter body in Sema for lazy properties altogether, and emit the getter entirely in SILGen instead. We already have the ability to do that for global variables, and lazy properties are not much different. |
Another easy way of seeing this issue (or a similar issue?) is: class Foo {
let bar = 42
lazy var baz = { self.bar }()
} The above does not compile: |
Just curious...
The body still needs to be typechecked at some point. What goes wrong when typechecking as part of a getter method / how would moving it to SILGen avoid this? (I'm curious but I don't know where this currently happens for global variables. Are you talking about something in here? https://github.com/apple/swift/blob/99de1fd10b13cbfd9b2f89d308c64cfe8c99e280/lib/SIL/SILGlobalVariable.cpp#L72) |
> The body still needs to be typechecked at some point. Right. Sema will type check the initializer expression, and either use that to set the VarDecl's type, or validate it against the VarDecl's type. > What goes wrong when typechecking as part of a getter method The problem is the double typechecking of the same Expr. Sema doesn't really support this correctly, even though CSDiag pretends. > how would moving it to SILGen avoid this? A lazy getter is basically
Instead of synthesizing an AST containing a possibly-typechecked initializer expression in the middle, we would have SILGen emit the scaffolding directly. Global variables don't have an AST for the getter body – SILGen emits the getter directly. Otherwise, they would have the same problem. |
The 'static initializer' thing for SILGlobalVariable is something different. This is where the initializer expression produces something sufficiently simple (eg, an integer literal or something) that instead of executing code to construct the value, we can just embed it directly in the program binary. |
Additional Detail from JIRA
md5: d87c612724b08f8b9285ef4e117bd00d
is duplicated by:
relates to:
Issue Description:
The following code results in "Type of expression is ambiguous without more context" when the lazy keyword is used. Without 'lazy', it compiles fine. Xcode 8 GM seed, Swift 3
Jacob Bandes-Storch pointed this out on the list:
This problem seems to occur when using an initializer with some default argument values. The following code also exhibits the issue:
The text was updated successfully, but these errors were encountered: