Skip to content

Commit 59f3def

Browse files
oderskyKordyjan
authored andcommitted
Better infos for dependent class parameter references
We sometimes create a dependent parameter reference p.X where `p` is a path with a type that has a wildcard argument, e.g. `P[X >: L <: H].` So far the denotation of `p.X` had as info the bounds with which `X` was declared in `P`. Now it gets the actual parameter bounds instead. Fixes #15652 #15652 started failing when tuple unpackings started to use `val`s instead of `def`s in #14816. That caused dependent class parameter references to be created and uncovered the problem.
1 parent 9fa1f48 commit 59f3def

File tree

4 files changed

+25
-8
lines changed

4 files changed

+25
-8
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,10 @@ object Denotations {
11181118
if !owner.membersNeedAsSeenFrom(pre) && (!ownerIsPrefix || hasOriginalInfo)
11191119
|| symbol.is(NonMember)
11201120
then this
1121+
else if symbol.isAllOf(ClassTypeParam) then
1122+
val arg = symbol.typeRef.argForParam(pre, widenAbstract = true)
1123+
if arg.exists then derivedSingleDenotation(symbol, arg.bounds, pre)
1124+
else derived(symbol.info)
11211125
else derived(symbol.info)
11221126
}
11231127
}

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,7 @@ object TypeOps:
426426
override def apply(tp: Type): Type =
427427
try
428428
tp match
429-
case tp: TermRef
430-
if toAvoid(tp) =>
429+
case tp: TermRef if toAvoid(tp) =>
431430
tp.info.widenExpr.dealias match {
432431
case info: SingletonType => apply(info)
433432
case info => range(defn.NothingType, apply(info))

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

+8-6
Original file line numberDiff line numberDiff line change
@@ -2453,10 +2453,12 @@ object Types {
24532453
ctx.base.underlyingRecursions -= 1
24542454

24552455
/** The argument corresponding to class type parameter `tparam` as seen from
2456-
* prefix `pre`. Can produce a TypeBounds type in case prefix is an & or | type
2457-
* and parameter is non-variant.
2456+
* prefix `pre`. Can produce a TypeBounds type if `widenAbstract` is true,
2457+
* or prefix is an & or | type and parameter is non-variant.
2458+
* Otherwise, a typebounds argument is dropped and the original type parameter
2459+
* reference is returned.
24582460
*/
2459-
def argForParam(pre: Type)(using Context): Type = {
2461+
def argForParam(pre: Type, widenAbstract: Boolean = false)(using Context): Type = {
24602462
val tparam = symbol
24612463
val cls = tparam.owner
24622464
val base = pre.baseType(cls)
@@ -2468,7 +2470,7 @@ object Types {
24682470
while (tparams.nonEmpty && args.nonEmpty) {
24692471
if (tparams.head.eq(tparam))
24702472
return args.head match {
2471-
case _: TypeBounds => TypeRef(pre, tparam)
2473+
case _: TypeBounds if !widenAbstract => TypeRef(pre, tparam)
24722474
case arg => arg
24732475
}
24742476
tparams = tparams.tail
@@ -5803,10 +5805,10 @@ object Types {
58035805
// if H#T = U, then for any x in L..H, x.T =:= U,
58045806
// hence we can replace with U under all variances
58055807
reapply(alias.rewrapAnnots(tp1))
5806-
case tp: TypeBounds =>
5808+
case bounds: TypeBounds =>
58075809
// If H#T = ? >: S <: U, then for any x in L..H, S <: x.T <: U,
58085810
// hence we can replace with S..U under all variances
5809-
expandBounds(tp)
5811+
expandBounds(bounds)
58105812
case info: SingletonType =>
58115813
// if H#x: y.type, then for any x in L..H, x.type =:= y.type,
58125814
// hence we can replace with y.type under all variances

tests/pos/i15652.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait Node
2+
type NodeParser[T] = Node => T
3+
4+
def child(key: String): Option[Node] = ???
5+
6+
def optionalOneOf[T](in: Map[String, NodeParser[? <: T]]): Option[T] =
7+
val mappings = in flatMap { (key, parser) =>
8+
child(key) map { node =>
9+
key -> (() => parser(node))
10+
}
11+
}
12+
mappings.headOption map (_._2())

0 commit comments

Comments
 (0)