Recognizing IDs inside `do` blocks in Swift 3.1
Swift seems to line up identifier recognition line by line:
print(fox) // Error: Use of unresolved identifier 'fox'
let fox = "π¦"
However do
, a strange thing happens in the block :
do {
print(dog) // Error: Use of local variable 'dog' before its declaration
let dog = "πΆ"
}
How does the compiler know what I'm going to declare dog
after trying to print it? Is ID recognition handled differently within blocks do
?
source to share
It looks like the Swift compiler handles undefined identifiers differently depending on the scope.
The difference between variables fox
and dog
is scope. This does not apply to blocks do
: any block type will change the classification of the variable undefined from "unresolved identifier" (global scope) to "local variable before declaration" (local scope).
Here are other ways to get the same error:
_ = {
print(fox) // Error: Use of local variable 'fox' before its declaration
let fox = "π¦"
}
func foo() {
print(fox) // Error: Use of local variable 'fox' before its declaration
let fox = "π¦"
}
class Bar {
func bar() {
print(fox) // Error: Use of local variable 'fox' before its declaration
let fox = "π¦"
}
}
My guess as to why this is happening is that the compiler waits for the end of the local scope before reporting errors, and error messages in the global scope are immediately reported. This is a good compromise, because the end of the local area usually does not require a complete scan of the entire translation unit to the end.
source to share
From your comment on @dasblinkenlight's answer you still seem to be unsure about "how this is handled", maybe this will help:
When the compiler needs to resolve an identifier, it starts by looking in the immediate enclosing scope, then proceeds to the scope that spans that, and so on, until it reaches the global scope.
As part of this search, the compiler should look at the entire scope, including the part that got past the point where the identifier it resolves is used. (Indeed, compilers are often multi-pass, so looking ahead can already be done here.) This process creates an error indicating that an identifier is being used before it is declared.
If the search moves completely into the global scope without finding a match, then an unresolved error occurs.
Addendum: not all scopes work the same
The declaration of the declaration occurs within a certain area of ββthe declaration; e.g. function body, class, body while
, global level, etc.
Nested declaration areas eg. scope inside a function, function inside a class, class in the global scope.
In local declaration scopes, such as the body of a function and any nested scopes, the object must be declared before using it - the order of declarations makes sense.
Objects declared directly in the scope of the type declaration (class, structure, etc.) or the scope of the global declaration can be referenced before they are declared - the order of the declarations does not matter. This allows mutual recursion, etc.
Thus, an error indicating that an object is in use before it is declared is only possible in the local scope.
NTN
source to share