<p>I'm looking for prior art on languages handling clashes happening during template instantiation between inner entities. For example, if we have a type parameter E intended to be an exception type and a catch block within that scope like that:</p>
<pre><code>try {...} catch E { /*a*/ } catch Exception { /*b*/ }
</code></pre>
<p>How would existing languages handle the situation if E is instantiated with Exception?
A similar example could be made with int-typed parameters and common switch case if the parameter were allowed to be a <code>case</code> label:</p>
<pre><code>switch (...) { case E: /*a*/ case 7: /*b*/ }
</code></pre>
<p>Note: This is not about overload resolution. It is about precedence or conflict rules when eliminating code during template substitution.</p>
<p>Note: My current understanding of the situation is that it only makes sense in λ polymorphism. For ∀ polymorphism like Java generics, the resolution would always happen before any substitution happens irrespective of the actual language.</p>

<language-comparison><semantics><generics><ambiguity>
Prior art on precedence rules on template instantiation for inner entity clashes
CC BY-SA 4.0
2024-07-13T14:43:51.387Z
I'm struggling to think of a valid use case where this wouldn't just be an error...
CoffeeTableEspresso
CC BY-SA 4.0
2024-07-13T15:24:29.207Z
@CoffeeTableEspresso if you know a widely used language where it is an error, I'd appreciate the answer. Error was one of the options I thought about. Still, my current favorite is a bit more complex than that.
feldentm
<p>In C#, it's not an error. If <code>E</code> is <code>Exception</code>, then the first catch gets executed:</p>
<pre><code>void F&lt;E&gt;() where E : Exception, new()
{
    try
    {
       if (new Random().Next() % 2 == 0)
           throw new E();
       else
           throw new Exception();
    }
    catch (E)
    {
        Console.WriteLine(&quot;E&quot;);
    }
    catch (Exception)
    {
        Console.WriteLine(&quot;Exception&quot;);
    }
}
F&lt;Exception&gt;();
</code></pre>
<p>always prints <code>E</code>.</p>
<p>However, <strong>if</strong> you were to put the <code>Exception</code> catch before the <code>E</code> catch, you would get</p>
<p><code>error CS0160: A previous catch clause already catches all exceptions of this or of a super type ('Exception')</code></p>
<p>Now that you mention it, I think this situation could be worth a warning, or a lint?</p>
<p>But I've never used an exception type as a generic type parameter, so it's a bit of a theoretical question to me.</p>
<hr />
<p>Now, for a switch on types:</p>
<pre><code>int G&lt;E&gt;(object o) =&gt; o switch
    {
        E =&gt; 1,
        Exception =&gt; 2,
        _ =&gt; 3,
    };
Console.WriteLine(G&lt;Exception&gt;(new Exception()));
</code></pre>
<p>This prints 1.</p>
<p>Similarly, if you put the <code>Exception</code> case before <code>E</code> <em>and</em> you add <code>where E : Exception</code>, then you get:</p>
<p><code>error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.</code></p>

CC BY-SA 4.0
2024-07-13T15:09:39.107Z
2024-07-13T15:31:17.440Z
2024-07-13T15:31:17.440Z
Eldritch Conundrum
CC BY-SA 4.0
2024-07-13T15:22:46.283Z
I only noticed myself because for exception handlers, as you say, the behavior starts to matter and is somewhat strange. For switch case, apparently I just picked randomly all the time and never noticed. For me, it's more a consistency thing as I cannot remember ever having encountered it.
feldentm
# Prior art on precedence rules on template instantiation for inner entity clashes
Posted by: username_0 on 2024-07-13
I'm looking for prior art on languages handling clashes happening during template instantiation between inner entities. For example, if we have a type parameter E intended to be an exception type and a catch block within that scope like that:
try {...} catch E { /*a*/ } catch Exception { /*b*/ }

How would existing languages handle the situation if E is instantiated with Exception?
A similar example could be made with int-typed parameters and common switch case if the parameter were allowed to be a case label:
switch (...) { case E: /*a*/ case 7: /*b*/ }

Note: This is not about overload resolution. It is about precedence or conflict rules when eliminating code during template substitution.
Note: My current understanding of the situation is that it only makes sense in λ polymorphism. For ∀ polymorphism like Java generics, the resolution would always happen before any substitution happens irrespective of the actual language.
**Tags:** language-comparison semantics generics ambiguity
> **Comments:**
> **username_1**: I'm struggling to think of a valid use case where this wouldn't just be an error...  
> **username_0**: @CoffeeTableEspresso if you know a widely used language where it is an error, I'd appreciate the answer. Error was one of the options I thought about. Still, my current favorite is a bit more complex than that.  
---
## 1 answers
### Answer by username_2 on 2024-07-13. Score: 4
In C#, it's not an error. If E is Exception, then the first catch gets executed:
void F() where E : Exception, new()
{
    try
    {
       if (new Random().Next() % 2 == 0)
           throw new E();
       else
           throw new Exception();
    }
    catch (E)
    {
        Console.WriteLine("E");
    }
    catch (Exception)
    {
        Console.WriteLine("Exception");
    }
}
F();

always prints E.
However, if you were to put the Exception catch before the E catch, you would get
error CS0160: A previous catch clause already catches all exceptions of this or of a super type ('Exception')
Now that you mention it, I think this situation could be worth a warning, or a lint?
But I've never used an exception type as a generic type parameter, so it's a bit of a theoretical question to me.

Now, for a switch on types:
int G(object o) => o switch
    {
        E => 1,
        Exception => 2,
        _ => 3,
    };
Console.WriteLine(G(new Exception()));

This prints 1.
Similarly, if you put the Exception case before E and you add where E : Exception, then you get:
error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
> **Comments:**
> **username_0** (2024-07-13): I only noticed myself because for exception handlers, as you say, the behavior starts to matter and is somewhat strange. For switch case, apparently I just picked randomly all the time and never noticed. For me, it's more a consistency thing as I cannot remember ever having encountered it.  
---
