<p>In languages like Java that use type erasure for generics, some casts are considered unchecked. One example is casting a value of <code>Object</code> to <code>List&lt;String&gt;</code>. On the other hand, casting from <code>Iterable&lt;String&gt;</code> to <code>List&lt;String&gt;</code> is allowed because the type parameter matches. Casting <code>Object</code> to <code>List&lt;?&gt;</code> is also allowed due to the wildcard.</p>
<p>In <a href="https://docs.oracle.com/javase/specs/jls/se20/html/jls-5.html#jls-5.1.6.2" rel="noreferrer">JLS 5.1.6.2</a>, it states</p>
<blockquote>
<p>A narrowing reference conversion from a type S to a parameterized class or interface type T is unchecked, unless at least one of the following is true:</p>
<ul>
<li>All of the type arguments of T are unbounded wildcards.</li>
<li>T &lt;: S, and S has no subtype X other than T where the type arguments of X are not contained in the type arguments of T.</li>
</ul>
</blockquote>
<ul>
<li>What is required to check the second criteria listed above?</li>
<li>Is there a well known algorithm for performing this check?</li>
<li>What edge cases need to be considered?</li>
</ul>

<types><implementation><java>
How can it be determined that a cast or type test is unchecked?
<p>The second criterion essentially checks the subtyping rule of your language. In Java, it's inheritance plus covariance. For instance:</p>
<ul>
<li>If type <code>A</code> extends/implements type <code>B</code>, then <code>A :&lt; B</code> (same when adding generic parameters)</li>
<li>If <code>A :&lt; B</code> then <code>A[] :&lt; B[]</code> (this rule is true in Java, but is flawed)</li>
</ul>
<p>So, an algorithm for checking this would be a graph-theoretic algorithm that detects if a node is an ancestor of another node.</p>
<p>Regarding edge cases, you may have to deal with special subtyping rules, for example, <code>int</code> is a subtype of <code>long</code> (check the Liskov substitution principle!), but there is no inheritance between them.</p>

CC BY-SA 4.0
2023-05-17T14:40:03.917Z
2023-05-17T14:42:54.097Z
2023-05-17T14:42:54.097Z
ice1000
CC BY-SA 4.0
2023-05-17T14:42:28.267Z
This doesn't really answer the question. I think it is clear why an unchecked cast is a problem. I'm more interested in how the compiler detects that the cast is unchecked.
MI3Guy
CC BY-SA 4.0
2023-05-17T14:48:27.140Z
@MI3Guy hi, I rewrote my answer.
ice1000
# How can it be determined that a cast or type test is unchecked?
Posted by: username_0 on 2023-05-17
In languages like Java that use type erasure for generics, some casts are considered unchecked. One example is casting a value of `Object` to `List`. On the other hand, casting from `Iterable` to `List` is allowed because the type parameter matches. Casting `Object` to `List`  is also allowed due to the wildcard.

In [JLS 5.1.6.2](https://docs.oracle.com/javase/specs/jls/se20/html/jls-5.html#jls-5.1.6.2), it states

> A narrowing reference conversion from a type S to a parameterized class or interface type T is unchecked, unless at least one of the following is true:
>
> * All of the type arguments of T are unbounded wildcards.
> * T <: S, and S has no subtype X other than T where the type arguments of X are not contained in the type arguments of T.

* What is required to check the second criteria listed above?
* Is there a well known algorithm for performing this check?
* What edge cases need to be considered?
**Tags:** types implementation java
---
## 1 answers
### Answer by username_1 on 2023-05-17. Score: 2
The second criterion essentially checks the subtyping rule of your language. In Java, it's inheritance plus covariance. For instance:

* If type `A` extends/implements type `B`, then `A :< B` (same when adding generic parameters)
* If `A :< B` then `A[] :< B[]` (this rule is true in Java, but is flawed)

So, an algorithm for checking this would be a graph-theoretic algorithm that detects if a node is an ancestor of another node.

Regarding edge cases, you may have to deal with special subtyping rules, for example, `int` is a subtype of `long` (check the Liskov substitution principle!), but there is no inheritance between them.
> **Comments:**
> **username_0** (2023-05-17): This doesn't really answer the question. I think it is clear why an unchecked cast is a problem. I'm more interested in how the compiler detects that the cast is unchecked.  
> **username_1** (2023-05-17): @MI3Guy hi, I rewrote my answer.  
---
