I was trying to answer this question, as I thought I knew the answer. Turns out, I did not know quite enough :/
Here is a test I have done:
class In
This is because the class-cast-exception is only thrown when you do something with the value, call a method on it after the cast. In the REPL for example, you would have a toString call in the second case. Note:
new Inst[String].as(3); () // nothing happens
new Inst[String].as(3).toString; () // exception
The reason why this takes the extra step is that Inst[T] is generic with type parameter T which is erased at runtime; only when the call-site (that has a static knowledge of type T) tries to call a method on the result, the actual type check occurs.
For your follow-up question, toString is defined on any object and since T is generic you have a boxed integer (<: AnyRef) and toString and println succeed within the is method. So another example where the Try would fail is this:
class Inst[T] {
def foo(x: Any)(implicit ev: T <:< String) = scala.util.Try {
ev(as(x)).reverse
}.isSuccess
}
new Inst[String].foo(3) // false!