Skip to content

Commit 1a3d5ce

Browse files
oderskytgodzik
authored andcommitted
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. [Cherry-picked 4a959b1]
1 parent 0e57f90 commit 1a3d5ce

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
@@ -2261,7 +2261,7 @@ object Types extends TypeUtils {
22612261
def _1: Type
22622262
def _2: Designator
22632263

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

22662266
private var myName: Name | Null = null
22672267
private var lastDenotation: Denotation | Null = null
@@ -2682,10 +2682,7 @@ object Types extends TypeUtils {
26822682
while (tparams.nonEmpty && args.nonEmpty) {
26832683
if (tparams.head.eq(tparam))
26842684
return args.head match {
2685-
case _: TypeBounds if !widenAbstract =>
2686-
if !NamedType.validPrefix(pre) then
2687-
throw TypeError(em"invalid prefix $pre cannot replace parameter $tparam in result of selection")
2688-
TypeRef(pre, tparam)
2685+
case _: TypeBounds if !widenAbstract => TypeRef(pre, tparam)
26892686
case arg => arg
26902687
}
26912688
tparams = tparams.tail
@@ -3041,6 +3038,8 @@ object Types extends TypeUtils {
30413038
apply(prefix, designatorFor(prefix, name, denot)).withDenot(denot)
30423039
}
30433040

3041+
class InvalidPrefix extends Exception
3042+
30443043
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
30453044

30463045
/** 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)