Skip to content

Commit 0a0997a

Browse files
committed
record isRefinedMethod in SingleDenotation
1 parent 2ff10dd commit 0a0997a

File tree

13 files changed

+103
-31
lines changed

13 files changed

+103
-31
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
/** For SymDenotations, the language-specific signature of the info, depending on
586589
* where the symbol is defined. For non-SymDenotations, the Scala 3
587590
* signature.
@@ -615,9 +618,9 @@ object Denotations {
615618
case _ => Signature.NotAMethod
616619
}
617620

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

622625
def mapInfo(f: Type => Type)(using Context): SingleDenotation =
623626
derivedSingleDenotation(symbol, f(info))
@@ -1114,7 +1117,7 @@ object Denotations {
11141117
}
11151118
}
11161119

1117-
abstract class NonSymSingleDenotation(symbol: Symbol, initInfo: Type, override val prefix: Type) extends SingleDenotation(symbol, initInfo) {
1120+
abstract class NonSymSingleDenotation(symbol: Symbol, initInfo: Type, override val prefix: Type, override val isRefinedMethod: Boolean) extends SingleDenotation(symbol, initInfo) {
11181121
def infoOrCompleter: Type = initInfo
11191122
def isType: Boolean = infoOrCompleter.isInstanceOf[TypeType]
11201123
}
@@ -1123,29 +1126,31 @@ object Denotations {
11231126
symbol: Symbol,
11241127
initInfo: Type,
11251128
initValidFor: Period,
1126-
prefix: Type) extends NonSymSingleDenotation(symbol, initInfo, prefix) {
1129+
prefix: Type,
1130+
isRefinedMethod: Boolean) extends NonSymSingleDenotation(symbol, initInfo, prefix, isRefinedMethod) {
11271131
validFor = initValidFor
11281132
override def hasUniqueSym: Boolean = true
1129-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1130-
new UniqueRefDenotation(s, i, validFor, pre)
1133+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1134+
new UniqueRefDenotation(s, i, validFor, pre, isRefinedMethod)
11311135
}
11321136

11331137
class JointRefDenotation(
11341138
symbol: Symbol,
11351139
initInfo: Type,
11361140
initValidFor: Period,
1137-
prefix: Type) extends NonSymSingleDenotation(symbol, initInfo, prefix) {
1141+
prefix: Type,
1142+
isRefinedMethod: Boolean) extends NonSymSingleDenotation(symbol, initInfo, prefix, isRefinedMethod) {
11381143
validFor = initValidFor
11391144
override def hasUniqueSym: Boolean = false
1140-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1141-
new JointRefDenotation(s, i, validFor, pre)
1145+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1146+
new JointRefDenotation(s, i, validFor, pre, isRefinedMethod)
11421147
}
11431148

1144-
class ErrorDenotation(using Context) extends NonSymSingleDenotation(NoSymbol, NoType, NoType) {
1149+
class ErrorDenotation(using Context) extends NonSymSingleDenotation(NoSymbol, NoType, NoType, false) {
11451150
override def exists: Boolean = false
11461151
override def hasUniqueSym: Boolean = false
11471152
validFor = Period.allInRun(ctx.runId)
1148-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1153+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
11491154
this
11501155
}
11511156

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,8 +1504,8 @@ object SymDenotations {
15041504

15051505
// ----- copies and transforms ----------------------------------------
15061506

1507-
protected def newLikeThis(s: Symbol, i: Type, pre: Type): SingleDenotation =
1508-
new UniqueRefDenotation(s, i, validFor, pre)
1507+
protected def newLikeThis(s: Symbol, i: Type, pre: Type, isRefinedMethod: Boolean): SingleDenotation =
1508+
new UniqueRefDenotation(s, i, validFor, pre, isRefinedMethod)
15091509

15101510
/** Copy this denotation, overriding selective fields */
15111511
final def copySymDenotation(

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,14 +773,14 @@ object Types {
773773
}
774774
else
775775
val joint = pdenot.meet(
776-
new JointRefDenotation(NoSymbol, rinfo, Period.allInRun(ctx.runId), pre),
776+
new JointRefDenotation(NoSymbol, rinfo, Period.allInRun(ctx.runId), pre, isRefinedMethod = false),
777777
pre,
778778
safeIntersection = ctx.base.pendingMemberSearches.contains(name))
779779
joint match
780780
case joint: SingleDenotation
781781
if rinfo.isInstanceOf[MethodOrPoly] && rinfo <:< joint.info =>
782782
// use `rinfo` to keep the right parameter names for named args. See i8516.scala.
783-
joint.derivedSingleDenotation(joint.symbol, rinfo)
783+
joint.derivedSingleDenotation(joint.symbol, rinfo, isRefinedMethod = true)
784784
case _ =>
785785
joint
786786
}
@@ -830,7 +830,7 @@ object Types {
830830
def goSuper(tp: SuperType) = go(tp.underlying) match {
831831
case d: JointRefDenotation =>
832832
typr.println(i"redirecting super.$name from $tp to ${d.symbol.showLocated}")
833-
new UniqueRefDenotation(d.symbol, tp.memberInfo(d.symbol), d.validFor, pre)
833+
new UniqueRefDenotation(d.symbol, tp.memberInfo(d.symbol), d.validFor, pre, isRefinedMethod = false)
834834
case d => d
835835
}
836836

@@ -4711,7 +4711,7 @@ object Types {
47114711
// also other information about the named type (e.g. bounds).
47124712
contains(
47134713
TypeRef(tp.prefix, cls)
4714-
.withDenot(new UniqueRefDenotation(cls, tp, cls.validFor, tp.prefix)))
4714+
.withDenot(new UniqueRefDenotation(cls, tp, cls.validFor, tp.prefix, isRefinedMethod = false)))
47154715
case _ =>
47164716
lo <:< tp && tp <:< hi
47174717
}

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
@@ -1191,30 +1191,26 @@ class TreeUnpickler(reader: TastyReader,
11911191
val SignedName(name, sig, target) = sname: @unchecked // only methods with params use SELECTin
11921192
val qualType = qual.tpe.widenIfUnstable
11931193
val prefix = ctx.typeAssigner.maybeSkolemizePrefix(qualType, name)
1194+
11941195
def overloadNotFound(select: Tree, symPart: String) =
11951196
typer.ErrorReporting.errorTree(select,
11961197
i"""While unpickling, I was looking in `$qual` (of widened type: ${qual.tpe.widen})
11971198
|but could not find method `$name` (${sname.info}):
11981199
| - $symPart.""".stripMargin)
1199-
// def matchOverload(denot: SingleDenotation) =
1200-
// val sym = denot.symbol
1201-
// sym.exists
1202-
// && sym.owner == owner
1203-
// && sym.targetName == target
1204-
// && sym.signature == sig
1205-
// val denot = qualType.findMember(name, prefix).filterWithPredicate(matchOverload)
1200+
12061201
val denot =
1207-
// TODO: handle refinements
12081202
val cls = ownerTpe.classSymbol
12091203
if !cls.exists then NoDenotation
12101204
else
12111205
val clsDenot = cls.asClass.classDenot
12121206
val d0 = clsDenot.findMember(name, cls.thisType, EmptyFlags, EmptyFlags).atSignature(sig, target)
1213-
if !d0.symbol.exists || d0.symbol.isAccessibleFrom(prefix) then d0.asSeenFrom(prefix)
1207+
if !d0.symbol.exists || d0.symbol.isAccessibleFrom(prefix) then
1208+
d0.asSeenFrom(prefix)
12141209
else
12151210
clsDenot.findMember(name, cls.thisType, EmptyFlags, excluded=Private)
12161211
.atSignature(sig, target)
12171212
.asSeenFrom(prefix)
1213+
12181214
val select = makeSelect(qual, name, denot)
12191215
if !(owner.exists && denot.exists) && ctx.settings.YstrictTasty.value then
12201216
val symPart =

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class Erasure extends Phase with DenotTransformer {
120120
}
121121
case ref: JointRefDenotation =>
122122
new UniqueRefDenotation(
123-
ref.symbol, transformInfo(ref.symbol, ref.symbol.info), ref.validFor, ref.prefix)
123+
ref.symbol, transformInfo(ref.symbol, ref.symbol.info), ref.validFor, ref.prefix, ref.isRefinedMethod)
124124
case _ =>
125125
ref.derivedSingleDenotation(ref.symbol, transformInfo(ref.symbol, ref.symbol.info))
126126
}
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)