Reputation: 9660
I have the following code in Swift:
func foo()
{
let name = "Hello World"
if name is String
{
}
else
{
}
}
I get the error: 'is' test is always true
I know it is always true! But why is this an error?
Upvotes: 3
Views: 319
Reputation: 186994
Swift compiles your declaration, through type inference, as this:
let name: String = "Hello World"
if name is String { ...
You can't test the type of a variable against the type it was declared as because that will ALWAYS be true, and that fact is evident at compile time. In this case, you know for sure that name
is a String
. The static typing of Swift means you should never need to do this test. You can always assume that a variable of type String
is a String
.
To use is
the type of the var must be castable, but not identical to, the type you are comparing it to. So this will compile if name
is an ambiguous type that could be String
or could be something else entirely. Then the test actually makes sense.
let name: AnyObject = "Hello World"
if name is String {
println("name is a string")
} else {
println("name is NOT a string :(")
}
Some more examples of when you can is
and when you can't.
// Good
// AnyObject can be casted to String
let name: AnyObject = "Hello World"
if name is String {}
// Also good
// UInt32 can be casted to Int
let num: UInt32 = 123
if num is Int {}
// error: 'String' is not a subtype of 'Int'
// Int cannot be casted to String, this will NEVER be true
let name: Int = 123
if name is String {}
// error: 'is' test is always true
// String will always be string, this will ALWAYS be true
let name: String = "Hello"
if name is String {}
Upvotes: 4
Reputation: 72750
Variables in swift are (very) strongly typed. If you write something like that, most likely you are doing something wrong in your code.
I appreciate that the compiler outputs that as an error - otherwise I might thing the else branch can be executed under some conditions.
Data types and structures don't support inheritance, so if you declare a String
variable, it cannot be anything else (besides Any
and AnyObject
, which are protocols though) .
If you declare a string variable :
var test: String = "test"
it can never be anything else, so this always fails:
if test is Int { // < 'Int' is not a subtype of 'String'
...
}
Testing if a string is a string is pointless, so the compiler considers it as an error, although maybe it's more a warning, because the code is syntactically and semantically correct.
By the way checking a data type or struct for Any
and AnyObject
produces the same error, so I presume the same is valid for any protocol they implement.
Upvotes: 1
Reputation: 154533
It's an error because Swift tries its hardest to keep you from doing useless things. Swift figures that since this test is always true, you must have intended to do something else.
Upvotes: 3