Skip to content

Commit 7fb87cb

Browse files
authored
Merge pull request #15338 from griggt/bport-fix-15272
[backport] Avoid NPE in simplify
2 parents f7f239c + b75efdb commit 7fb87cb

File tree

5 files changed

+45
-6
lines changed

5 files changed

+45
-6
lines changed

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
148148
private def paramCount(entries: Array[Type]) = entries.length >> 1
149149

150150
/** The type variable corresponding to parameter numbered `n`, null if none was created */
151-
private def typeVar(entries: Array[Type], n: Int): Type =
151+
private def typeVar(entries: Array[Type], n: Int): Type | Null =
152152
entries(paramCount(entries) + n)
153153

154154
/** The `boundsMap` entry corresponding to `param` */
@@ -171,7 +171,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
171171
val origin = tvar.origin
172172
val entries = boundsMap(origin.binder)
173173
val pnum = origin.paramNum
174-
entries != null && isBounds(entries(pnum)) && (typeVar(entries, pnum) eq tvar)
174+
entries != null && isBounds(entries(pnum)) && (typeVar(entries, pnum) eqn tvar)
175175
}
176176

177177
// ---------- Dependency handling ----------------------------------------------
@@ -203,11 +203,13 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
203203
def nonParamBounds(param: TypeParamRef)(using Context): TypeBounds =
204204
entry(param).bounds
205205

206-
def typeVarOfParam(param: TypeParamRef): Type = {
206+
def typeVarOfParam(param: TypeParamRef): Type =
207207
val entries = boundsMap(param.binder)
208208
if entries == null then NoType
209-
else typeVar(entries, param.paramNum)
210-
}
209+
else
210+
val tvar = typeVar(entries, param.paramNum)
211+
if tvar == null then NoType
212+
else tvar
211213

212214
// ---------- Adding TypeLambdas --------------------------------------------------
213215

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ object TypeOps:
145145
if normed.exists then normed else tp.map(simplify(_, theMap))
146146
case tp: TypeParamRef =>
147147
val tvar = ctx.typerState.constraint.typeVarOfParam(tp)
148-
if (tvar.exists) tvar else tp
148+
if tvar.exists then tvar else tp
149149
case _: ThisType | _: BoundType =>
150150
tp
151151
case tp: AliasingBounds =>

tests/neg/i15272.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
sealed trait EdgeN[+NT]
2+
object EdgeN:
3+
case class Head[+NT, +From <: NT, +To <: NT] (from: From, to: To ) extends EdgeN[NT]
4+
case class Cons[+NT, +From <: NT, +ToE <: EdgeN[NT]](from: From, to: ToE) extends EdgeN[NT]
5+
final type InNodesTupleOf[NT, E <: EdgeN[NT]] <: Tuple = E match
6+
case Cons[nt,from,toE] => from *: InNodesTupleOf[nt,toE]
7+
case Head[nt,from ,to] => from *: EmptyTuple
8+
def inNodesTuple[NT,E <: EdgeN[NT]](edge: E): InNodesTupleOf[NT,E] = edge match
9+
case e: Cons[nt,from,toE] => e.from *: inNodesTuple[nt,toE](e.to) // error
10+
case e: Head[nt,from,to] => e.from *: EmptyTuple
11+
end EdgeN

tests/pos/i15183/decoder_1.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import scala.deriving._
2+
3+
sealed trait Decoder[T]
4+
object Decoder {
5+
given Decoder[Double] = ???
6+
7+
inline given summonEmptyTuple[H]: Tuple.Map[EmptyTuple.type, Decoder] =
8+
EmptyTuple
9+
10+
inline given summonTuple[H, T <: Tuple](using hd: Decoder[H], td: Tuple.Map[T, Decoder]): Tuple.Map[H *: T, Decoder] =
11+
hd *: td
12+
13+
inline given derived[T](using m: Mirror.Of[T], d: Tuple.Map[m.MirroredElemTypes, Decoder]): Decoder[T] = ???
14+
}

tests/pos/i15183/test_2.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Fails in each cases below
2+
enum Env derives Decoder:
3+
case Local,Sit,Prod
4+
5+
enum Env2 derives Decoder:
6+
case Local()
7+
case Sit()
8+
case Prod()
9+
10+
enum Shape derives Decoder:
11+
case Rectangle(width: Double, height: Double)
12+
case Circle(radius: Double)

0 commit comments

Comments
 (0)