This could be because of the difference between as
and as?
. The key difference is that if you use as
, the compiler must be able to tell that the conversion is valid/will succeed, at compile time.
Because of this, there is a limit on what actual type get
could return. Eventually, the type checker decides that T
is Int
. Keep in mind that the Swift typechecker works on a constraint system.
On the other hand, if you use as?
, the LHS expression can be any type, and there are no compile time checks. The cast will be checked at runtime, and if it fails, the expression evaluates to nil. As a result, as?
does not limit what the type of its LHS expression is.
I've found the relevant section of code in the Swift compiler's source code, so you can explore it further on your own, if you desire. As you can see, in visitCoerceExpr
(foo as T
), it does this:
// Add a conversion constraint for the direct conversion between
// types.
CS.addExplicitConversionConstraint(fromType, toType, RememberChoice,
locator);
which it does not do in visitConditionalCheckedCastExpr
(foo as? T
).
Note that if you don't use T
anywhere else inside get
, you can just return Any
, and let the caller cast. This will allow you to use the as? Int
syntax.
func get() -> Any {
// ...
return 5
}
if let x = get() as? Int { /* ... */ }