Skip to content

Commit bcde8c4

Browse files
committed
record isRefinedMethod in SingleDenotation
1 parent a0ae794 commit bcde8c4

File tree

13 files changed

+105
-33
lines changed

13 files changed

+105
-33
lines changed

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

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ object Denotations {
477477
val jointInfo = infoMeet(info1, info2, safeIntersection)
478478
if jointInfo.exists then
479479
val sym = if symScore >= 0 then sym1 else sym2
480-
JointRefDenotation(sym, jointInfo, denot1.validFor & denot2.validFor, pre)
480+
JointRefDenotation(sym, jointInfo, denot1.validFor & denot2.validFor, pre, denot1.isRefinedMethod && denot2.isRefinedMethod)
481481
else if symScore == 2 then denot1
482482
else if symScore == -2 then denot2
483483
else
@@ -569,7 +569,7 @@ object Denotations {
569569

570570
/** A non-overloaded denotation */
571571
abstract class SingleDenotation(symbol: Symbol, initInfo: Type) extends Denotation(symbol, initInfo) {
572-
protected def newLikeThis(symbol: Symbol, info: Type, pre: Type): SingleDenotation
572+
protected def newLikeThis(symbol: Symbol, info: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation
573573

574574
final def name(using Context): Name = symbol.name
575575

@@ -582,6 +582,9 @@ object Denotations {
582582
*/
583583
def prefix: Type = NoPrefix
584584

585+
/** If this denotation references a refined method */
586+
def isRefinedMethod: Boolean = false
587+
585588
/** Either the Scala or Java signature of the info, depending on where the
586589
* symbol is defined.
587590
*
@@ -614,9 +617,9 @@ object Denotations {
614617
case _ => Signature.NotAMethod
615618
}
616619

617-
def derivedSingleDenotation(symbol: Symbol, info: Type, pre: Type = this.prefix)(using Context): SingleDenotation =
618-
if ((symbol eq this.symbol) && (info eq this.info) && (pre eq this.prefix)) this
619-
else newLikeThis(symbol, info, pre)
620+
def derivedSingleDenotation(symbol: Symbol, info: Type, pre: Type = this.prefix, isRefinedMethod: Boolean = false)(using Context): SingleDenotation =
621+
if ((symbol eq this.symbol) && (info eq this.info) && (pre eq this.prefix) && (isRefinedMethod == this.isRefinedMethod)) this
622+
else newLikeThis(symbol, info, pre, isRefinedMethod)
620623

621624
def mapInfo(f: Type => Type)(using Context): SingleDenotation =
622625
derivedSingleDenotation(symbol, f(info))
@@ -1112,7 +1115,7 @@ object Denotations {
11121115
}
11131116
}
11141117

1115-
abstract class NonSymSingleDenotation(symbol: Symbol, initInfo: Type, override val prefix: Type) extends SingleDenotation(symbol, initInfo) {
1118+
abstract class NonSymSingleDenotation(symbol: Symbol, initInfo: Type, override val prefix: Type, override val isRefinedMethod: Boolean) extends SingleDenotation(symbol, initInfo) {
11161119
def infoOrCompleter: Type = initInfo
11171120
def isType: Boolean = infoOrCompleter.isInstanceOf[TypeType]
11181121
}
@@ -1121,29 +1124,31 @@ object Denotations {
11211124
symbol: Symbol,
11221125
initInfo: Type,
11231126
initValidFor: Period,
1124-
prefix: Type) extends NonSymSingleDenotation(symbol, initInfo, prefix) {
1127+
prefix: Type,
1128+
isRefinedMethod: Boolean) extends NonSymSingleDenotation(symbol, initInfo, prefix, isRefinedMethod) {
11251129
validFor = initValidFor
11261130
override def hasUniqueSym: Boolean = true
1127-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1128-
new UniqueRefDenotation(s, i, validFor, pre)
1131+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1132+
new UniqueRefDenotation(s, i, validFor, pre, isRefinedMethod)
11291133
}
11301134

11311135
class JointRefDenotation(
11321136
symbol: Symbol,
11331137
initInfo: Type,
11341138
initValidFor: Period,
1135-
prefix: Type) extends NonSymSingleDenotation(symbol, initInfo, prefix) {
1139+
prefix: Type,
1140+
isRefinedMethod: Boolean) extends NonSymSingleDenotation(symbol, initInfo, prefix, isRefinedMethod) {
11361141
validFor = initValidFor
11371142
override def hasUniqueSym: Boolean = false
1138-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1139-
new JointRefDenotation(s, i, validFor, pre)
1143+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1144+
new JointRefDenotation(s, i, validFor, pre, isRefinedMethod)
11401145
}
11411146

1142-
class ErrorDenotation(using Context) extends NonSymSingleDenotation(NoSymbol, NoType, NoType) {
1147+
class ErrorDenotation(using Context) extends NonSymSingleDenotation(NoSymbol, NoType, NoType, false) {
11431148
override def exists: Boolean = false
11441149
override def hasUniqueSym: Boolean = false
11451150
validFor = Period.allInRun(ctx.runId)
1146-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1151+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
11471152
this
11481153
}
11491154

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,8 +1498,8 @@ object SymDenotations {
14981498

14991499
// ----- copies and transforms ----------------------------------------
15001500

1501-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1502-
new UniqueRefDenotation(s, i, validFor, pre)
1501+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1502+
new UniqueRefDenotation(s, i, validFor, pre, isRefinedMethod)
15031503

15041504
/** Copy this denotation, overriding selective fields */
15051505
final def copySymDenotation(
@@ -2209,8 +2209,8 @@ object SymDenotations {
22092209
ensureCompleted()
22102210
myCompanion
22112211

2212-
override def registeredCompanion_=(c: Symbol) =
2213-
myCompanion = c
2212+
override def registeredCompanion_=(c: Symbol) =
2213+
myCompanion = c
22142214

22152215
private var myNestingLevel = -1
22162216

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -752,14 +752,14 @@ object Types {
752752
}
753753
else
754754
val joint = pdenot.meet(
755-
new JointRefDenotation(NoSymbol, rinfo, Period.allInRun(ctx.runId), pre),
755+
new JointRefDenotation(NoSymbol, rinfo, Period.allInRun(ctx.runId), pre, isRefinedMethod = false),
756756
pre,
757757
safeIntersection = ctx.base.pendingMemberSearches.contains(name))
758758
joint match
759759
case joint: SingleDenotation
760760
if rinfo.isInstanceOf[MethodOrPoly] && rinfo <:< joint.info =>
761761
// use `rinfo` to keep the right parameter names for named args. See i8516.scala.
762-
joint.derivedSingleDenotation(joint.symbol, rinfo)
762+
joint.derivedSingleDenotation(joint.symbol, rinfo, isRefinedMethod = true)
763763
case _ =>
764764
joint
765765
}
@@ -809,7 +809,7 @@ object Types {
809809
def goSuper(tp: SuperType) = go(tp.underlying) match {
810810
case d: JointRefDenotation =>
811811
typr.println(i"redirecting super.$name from $tp to ${d.symbol.showLocated}")
812-
new UniqueRefDenotation(d.symbol, tp.memberInfo(d.symbol), d.validFor, pre)
812+
new UniqueRefDenotation(d.symbol, tp.memberInfo(d.symbol), d.validFor, pre, isRefinedMethod = false)
813813
case d => d
814814
}
815815

@@ -4697,7 +4697,7 @@ object Types {
46974697
// also other information about the named type (e.g. bounds).
46984698
contains(
46994699
TypeRef(tp.prefix, cls)
4700-
.withDenot(new UniqueRefDenotation(cls, tp, cls.validFor, tp.prefix)))
4700+
.withDenot(new UniqueRefDenotation(cls, tp, cls.validFor, tp.prefix, isRefinedMethod = false)))
47014701
case _ =>
47024702
lo <:< tp && tp <:< hi
47034703
}

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ class TreePickler(pickler: TastyPickler) {
413413
name.isTypeName
414414
|| qual.isInstanceOf[TreePickler.Hole]
415415
|| sig == Signature.NotAMethod
416-
|| !tree.denot.symbol.exists // polymorphic function type
416+
|| !tree.denot.symbol.exists // polymorphic function type
417+
|| !tree.denot.isOverloaded && tree.denot.asSingleDenotation.isRefinedMethod
417418
if skipOwner then
418419
writeByte(if name.isTypeName then SELECTtpt else SELECT)
419420
pickleNameAndSig(name, sig, ename)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,30 +1189,26 @@ class TreeUnpickler(reader: TastyReader,
11891189
val SignedName(name, sig, target) = sname: @unchecked // only methods with params use SELECTin
11901190
val qualType = qual.tpe.widenIfUnstable
11911191
val prefix = ctx.typeAssigner.maybeSkolemizePrefix(qualType, name)
1192+
11921193
def overloadNotFound(select: Tree, symPart: String) =
11931194
typer.ErrorReporting.errorTree(select,
11941195
i"""While unpickling, I was looking in `$qual` (of widened type: ${qual.tpe.widen})
11951196
|but could not find method `$name` (${sname.info}):
11961197
| - $symPart.""".stripMargin)
1197-
// def matchOverload(denot: SingleDenotation) =
1198-
// val sym = denot.symbol
1199-
// sym.exists
1200-
// && sym.owner == owner
1201-
// && sym.targetName == target
1202-
// && sym.signature == sig
1203-
// val denot = qualType.findMember(name, prefix).filterWithPredicate(matchOverload)
1198+
12041199
val denot =
1205-
// TODO: handle refinements
12061200
val cls = ownerTpe.classSymbol
12071201
if !cls.exists then NoDenotation
12081202
else
12091203
val clsDenot = cls.asClass.classDenot
12101204
val d0 = clsDenot.findMember(name, cls.thisType, EmptyFlags, EmptyFlags).atSignature(sig, target)
1211-
if !d0.symbol.exists || d0.symbol.isAccessibleFrom(prefix) then d0.asSeenFrom(prefix)
1205+
if !d0.symbol.exists || d0.symbol.isAccessibleFrom(prefix) then
1206+
d0.asSeenFrom(prefix)
12121207
else
12131208
clsDenot.findMember(name, cls.thisType, EmptyFlags, excluded=Private)
12141209
.atSignature(sig, target)
12151210
.asSeenFrom(prefix)
1211+
12161212
val select = makeSelect(qual, name, denot)
12171213
if !(owner.exists && denot.exists) && ctx.settings.YstrictTasty.value then
12181214
val symPart =

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class Erasure extends Phase with DenotTransformer {
113113
}
114114
case ref: JointRefDenotation =>
115115
new UniqueRefDenotation(
116-
ref.symbol, transformInfo(ref.symbol, ref.symbol.info), ref.validFor, ref.prefix)
116+
ref.symbol, transformInfo(ref.symbol, ref.symbol.info), ref.validFor, ref.prefix, ref.isRefinedMethod)
117117
case _ =>
118118
ref.derivedSingleDenotation(ref.symbol, transformInfo(ref.symbol, ref.symbol.info))
119119
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package a
2+
3+
object A {
4+
5+
trait Fn[-T1, +R] { def apply(v1: T1): R }
6+
7+
val fn0: Fn[Int, Int] = x => x
8+
9+
val fn = fn0
10+
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package a
2+
3+
object A {
4+
5+
trait Fn[-T1, +R] { def apply(v1: T1): R }
6+
7+
val fn0: Fn[Int, Int] { def apply(arg: Int): Int } = ???
8+
9+
val fn = fn0
10+
11+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import a.*
2+
3+
object B extends App {
4+
A.fn(0)
5+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
lazy val a = project.in(file("a"))
2+
.settings(
3+
Compile / classDirectory := (ThisBuild / baseDirectory).value / "b-input"
4+
)
5+
6+
lazy val b = project.in(file("b"))
7+
.settings(
8+
Compile / unmanagedClasspath += (ThisBuild / baseDirectory).value / "b-input",
9+
Compile / classDirectory := (ThisBuild / baseDirectory).value / "c-input"
10+
)
11+
12+
lazy val `a-changes` = project.in(file("a-changes"))
13+
.settings(
14+
Compile / classDirectory := (ThisBuild / baseDirectory).value / "c-input"
15+
)
16+
17+
lazy val c = project.in(file("."))
18+
.settings(
19+
scalacOptions ++= Seq("-from-tasty", "-Ystrict-tasty", "-Ycheck:all"),
20+
Compile / sources := Seq(new java.io.File("c-input/B.tasty")),
21+
Compile / unmanagedClasspath += (ThisBuild / baseDirectory).value / "c-input",
22+
Compile / classDirectory := (ThisBuild / baseDirectory).value / "c-output"
23+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import sbt._
2+
import Keys._
3+
4+
object DottyInjectedPlugin extends AutoPlugin {
5+
override def requires = plugins.JvmPlugin
6+
override def trigger = allRequirements
7+
8+
override val projectSettings = Seq(
9+
scalaVersion := sys.props("plugin.scalaVersion")
10+
)
11+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version"))
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# compile library A
2+
> a/compile
3+
# compile library B, from source, against A
4+
> b/compile
5+
# add a refinement in library A', it changes the parameter names
6+
> a-changes/compile
7+
# compile B, from tasty, against A', it should continue compile: named arguments still ok.
8+
> c/compile

0 commit comments

Comments
 (0)