// Typecasting from Classes And Protocols
class Vegetable {}
class Potato: Vegetable {}
class Chips: Potato {}
protocol Vegetableable {}
protocol Potatoable: Vegetableable {}
protocol Chipsable: Potatoable {}
class Tree {}
protocol Treeable {}
struct CheckCasting {
class Bee {}
func get(c: Vegetable) {
if c is Chips { print("is Cips") }
if c is Tree { print("is Tree") } // Cast from 'Vegetable' to unrelated type 'Tree' always fails
}
func get(p: Vegetableable) {
if p is Chipsable { print("is Chpsable") } // No warnings, is right
}
func get(t: Treeable) {
if t is Chipsable { print("is Chipsable") } // No warnings ?
if t is Bee { print("is Bee") } // No warnings ?
}
}
I mean, that compiler knows, about in my last method func get(t: Treeable), the Treeable not inherited from Vegetableable and Bee not conformed to the any protocol at all. Where is my warnings?
I mean, that compiler knows, about in my last method func get(t: Treeable), the Treeable not inherited from Vegetableable and Bee not conformed to the any protocol at all. Where is my warnings?
You don't get any warning because:
a value can be both Treeable and Chipsable:
struct Foo: Treeable, Chipsable { ... }
a value can be both Treeable and Bee:
// With a subclass:
class TreeableBee: Bee, Treeable { ... }
// Or with an extension on Bee:
extension Bee: Treeable { ... }
As you see, the compiler can't emit any warning, because other pieces of code in your app may mix protocols and classes together: those checks are totally valid.
Or, in other words, the compiler doesn't know what the concrete type passed as Treeable will be beforehand. While it might be sometimes possible to diagnose «this cast fails for all method invocations we see» under strong accessibility constraints, the criteria, benefits and even the meaning of that diagnostic message are rather opaque.
I agree that we would all benefit from tools that reveal, generally speaking, "unused code".
There are unused methods, unused types, etc. But we also have a subtle but valid case of "unused code" here.
Unless I'm mistaken, I think there is a consensus that such tools should belong to linters, not on the default toolchain. I admit I did not search the web for such tools yet!
Sorry, my answer was too short. I meant the warning for the "if is" that is never true because there is no conformance for the non-public structs and protocols in the example above:
func get(t: Treeable) {
if t is Chipsable { print("is Chipsable") } // expected-error: Will never be executed
if t is Bee { print("is Bee") } // expected-error: Will never be executed
}
I think you need to also consider the process of writing code here, not just the process of compiling a completed and fully-functional codebase. It might be annoying to get a bunch of warnings or errors just because you've written the protocol part before creating your conforming types. Or because you've considered future code evolution where you might have a type that conforms to Treeable and Chipsable, even though you don't plan to implement one in the immediate future.