diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 6974f7f1b836..f8ccdcee4be5 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -148,7 +148,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, private def paramCount(entries: Array[Type]) = entries.length >> 1 /** The type variable corresponding to parameter numbered `n`, null if none was created */ - private def typeVar(entries: Array[Type], n: Int): Type = + private def typeVar(entries: Array[Type], n: Int): Type | Null = entries(paramCount(entries) + n) /** The `boundsMap` entry corresponding to `param` */ @@ -171,7 +171,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, val origin = tvar.origin val entries = boundsMap(origin.binder) val pnum = origin.paramNum - entries != null && isBounds(entries(pnum)) && (typeVar(entries, pnum) eq tvar) + entries != null && isBounds(entries(pnum)) && (typeVar(entries, pnum) eqn tvar) } // ---------- Dependency handling ---------------------------------------------- @@ -203,11 +203,13 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def nonParamBounds(param: TypeParamRef)(using Context): TypeBounds = entry(param).bounds - def typeVarOfParam(param: TypeParamRef): Type = { + def typeVarOfParam(param: TypeParamRef): Type = val entries = boundsMap(param.binder) if entries == null then NoType - else typeVar(entries, param.paramNum) - } + else + val tvar = typeVar(entries, param.paramNum) + if tvar == null then NoType + else tvar // ---------- Adding TypeLambdas -------------------------------------------------- diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 2cfdd08128ce..3faab121637b 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -145,7 +145,7 @@ object TypeOps: if normed.exists then normed else tp.map(simplify(_, theMap)) case tp: TypeParamRef => val tvar = ctx.typerState.constraint.typeVarOfParam(tp) - if (tvar.exists) tvar else tp + if tvar.exists then tvar else tp case _: ThisType | _: BoundType => tp case tp: AliasingBounds => diff --git a/tests/neg/i15272.scala b/tests/neg/i15272.scala new file mode 100644 index 000000000000..1d380a3b5333 --- /dev/null +++ b/tests/neg/i15272.scala @@ -0,0 +1,11 @@ + sealed trait EdgeN[+NT] + object EdgeN: + case class Head[+NT, +From <: NT, +To <: NT] (from: From, to: To ) extends EdgeN[NT] + case class Cons[+NT, +From <: NT, +ToE <: EdgeN[NT]](from: From, to: ToE) extends EdgeN[NT] + final type InNodesTupleOf[NT, E <: EdgeN[NT]] <: Tuple = E match + case Cons[nt,from,toE] => from *: InNodesTupleOf[nt,toE] + case Head[nt,from ,to] => from *: EmptyTuple + def inNodesTuple[NT,E <: EdgeN[NT]](edge: E): InNodesTupleOf[NT,E] = edge match + case e: Cons[nt,from,toE] => e.from *: inNodesTuple[nt,toE](e.to) // error + case e: Head[nt,from,to] => e.from *: EmptyTuple + end EdgeN \ No newline at end of file diff --git a/tests/pos/i15183/decoder_1.scala b/tests/pos/i15183/decoder_1.scala new file mode 100644 index 000000000000..532fd7246c3a --- /dev/null +++ b/tests/pos/i15183/decoder_1.scala @@ -0,0 +1,14 @@ +import scala.deriving._ + +sealed trait Decoder[T] +object Decoder { + given Decoder[Double] = ??? + + inline given summonEmptyTuple[H]: Tuple.Map[EmptyTuple.type, Decoder] = + EmptyTuple + + inline given summonTuple[H, T <: Tuple](using hd: Decoder[H], td: Tuple.Map[T, Decoder]): Tuple.Map[H *: T, Decoder] = + hd *: td + + inline given derived[T](using m: Mirror.Of[T], d: Tuple.Map[m.MirroredElemTypes, Decoder]): Decoder[T] = ??? +} diff --git a/tests/pos/i15183/test_2.scala b/tests/pos/i15183/test_2.scala new file mode 100644 index 000000000000..2069d5637734 --- /dev/null +++ b/tests/pos/i15183/test_2.scala @@ -0,0 +1,12 @@ +// Fails in each cases below +enum Env derives Decoder: + case Local,Sit,Prod + +enum Env2 derives Decoder: + case Local() + case Sit() + case Prod() + +enum Shape derives Decoder: + case Rectangle(width: Double, height: Double) + case Circle(radius: Double)