Skip to content

Commit 0aab2b7

Browse files
authored
Merge pull request #15753 from dotty-staging/backport-15667
Backport #15667: Better infos for dependent class parameter references
2 parents 3d29fd1 + dfdecf1 commit 0aab2b7

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
@@ -2456,10 +2456,12 @@ object Types {
24562456
ctx.base.underlyingRecursions -= 1
24572457

24582458
/** The argument corresponding to class type parameter `tparam` as seen from
2459-
* prefix `pre`. Can produce a TypeBounds type in case prefix is an & or | type
2460-
* and parameter is non-variant.
2459+
* prefix `pre`. Can produce a TypeBounds type if `widenAbstract` is true,
2460+
* or prefix is an & or | type and parameter is non-variant.
2461+
* Otherwise, a typebounds argument is dropped and the original type parameter
2462+
* reference is returned.
24612463
*/
2462-
def argForParam(pre: Type)(using Context): Type = {
2464+
def argForParam(pre: Type, widenAbstract: Boolean = false)(using Context): Type = {
24632465
val tparam = symbol
24642466
val cls = tparam.owner
24652467
val base = pre.baseType(cls)
@@ -2471,7 +2473,7 @@ object Types {
24712473
while (tparams.nonEmpty && args.nonEmpty) {
24722474
if (tparams.head.eq(tparam))
24732475
return args.head match {
2474-
case _: TypeBounds => TypeRef(pre, tparam)
2476+
case _: TypeBounds if !widenAbstract => TypeRef(pre, tparam)
24752477
case arg => arg
24762478
}
24772479
tparams = tparams.tail
@@ -5806,10 +5808,10 @@ object Types {
58065808
// if H#T = U, then for any x in L..H, x.T =:= U,
58075809
// hence we can replace with U under all variances
58085810
reapply(alias.rewrapAnnots(tp1))
5809-
case tp: TypeBounds =>
5811+
case bounds: TypeBounds =>
58105812
// If H#T = ? >: S <: U, then for any x in L..H, S <: x.T <: U,
58115813
// hence we can replace with S..U under all variances
5812-
expandBounds(tp)
5814+
expandBounds(bounds)
58135815
case info: SingletonType =>
58145816
// if H#x: y.type, then for any x in L..H, x.type =:= y.type,
58155817
// 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)