Skip to content

Commit 4a959b1

Browse files
committed
More systematic handling of invalid prefixes
It looks like there are many situations where an illegal higher-kinded type in an argument for a value type parameter causes illegal TermRefs and TypeRefs to be constructed, leading to an assertion error. We now turn the assertion error into a specialized exception which eventually leads to a TypeError being thrown. The problem is we cannot detect illegal kinds in arguments early enough to prevent these situations. We do detect them later, but the damage can already be done before that.
1 parent 40e076d commit 4a959b1

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,7 +2302,7 @@ object Types extends TypeUtils {
23022302
def _1: Type
23032303
def _2: Designator
23042304

2305-
assert(NamedType.validPrefix(prefix), s"invalid prefix $prefix")
2305+
if !NamedType.validPrefix(prefix) then throw InvalidPrefix()
23062306

23072307
private var myName: Name | Null = null
23082308
private var lastDenotation: Denotation | Null = null
@@ -2736,10 +2736,7 @@ object Types extends TypeUtils {
27362736
while (tparams.nonEmpty && args.nonEmpty) {
27372737
if (tparams.head.eq(tparam))
27382738
return args.head match {
2739-
case _: TypeBounds if !widenAbstract =>
2740-
if !NamedType.validPrefix(pre) then
2741-
throw TypeError(em"invalid prefix $pre cannot replace parameter $tparam in result of selection")
2742-
TypeRef(pre, tparam)
2739+
case _: TypeBounds if !widenAbstract => TypeRef(pre, tparam)
27432740
case arg => arg
27442741
}
27452742
tparams = tparams.tail
@@ -3070,6 +3067,8 @@ object Types extends TypeUtils {
30703067
apply(prefix, designatorFor(prefix, name, denot)).withDenot(denot)
30713068
}
30723069

3070+
class InvalidPrefix extends Exception
3071+
30733072
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
30743073

30753074
/** The type cls.this

compiler/src/dotty/tools/dotc/core/Uniques.scala

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package core
33

44
import Types.*, Contexts.*, util.Stats.*, Hashable.*, Names.*
55
import config.Config
6+
import Symbols.Symbol
67
import Decorators.*
78
import util.{WeakHashSet, Stats}
89
import WeakHashSet.Entry
@@ -41,8 +42,10 @@ object Uniques:
4142
val h = doHash(null, designator, prefix)
4243
if monitored then recordCaching(h, classOf[NamedType])
4344
def newType =
44-
if (isTerm) new CachedTermRef(prefix, designator, h)
45-
else new CachedTypeRef(prefix, designator, h)
45+
try
46+
if isTerm then new CachedTermRef(prefix, designator, h)
47+
else new CachedTypeRef(prefix, designator, h)
48+
catch case ex: InvalidPrefix => badPrefix(prefix, designator)
4649
if h == NotCached then newType
4750
else
4851
// Inlined from WeakHashSet#put
@@ -61,6 +64,14 @@ object Uniques:
6164

6265
linkedListLoop(oldHead)
6366
end if
67+
end enterIfNew
68+
69+
private def badPrefix(prefix: Type, desig: Designator)(using Context): Nothing =
70+
def name = desig match
71+
case desig: Name => desig
72+
case desig: Symbol => desig.name
73+
throw TypeError(em"invalid prefix $prefix when trying to form $prefix . $name")
74+
6475
end NamedTypeUniques
6576

6677
final class AppliedUniques extends WeakHashSet[AppliedType](Config.initialUniquesCapacity * 2) with Hashable:

tests/neg/i23504.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
def test =
2-
Seq.empty[[T] =>> () => ?].head() // error
2+
Seq.empty[[T] =>> () => ?].head() // error
3+
Seq.empty[[T] =>> Int => Int].head(1) // error

0 commit comments

Comments
 (0)