Skip to content

Commit

Permalink
Fix pkg obj prefix of opaque tp ext meth
Browse files Browse the repository at this point in the history
TypeOps.makePackageObjPrefixExplicit is a part of `accessibleType`,
which is called on the result of findRef in typedIdent.  But in
`tryExtension` it's not.  We could fix it in the usage of the results in
`tryExtension`, but I thought perhaps we could fix it for all call
sites, by handling it within findRef.
  • Loading branch information
dwijnand committed Sep 1, 2024
1 parent ec1b115 commit d53c798
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 2 deletions.
8 changes: 6 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
else found
end checkImportAlternatives

extension (tp: Type) def makePackageObjPrefixExplicit: Type = tp match
case tp: NamedType => TypeOps.makePackageObjPrefixExplicit(tp)
case tp => tp

def selection(imp: ImportInfo, name: Name, checkBounds: Boolean): Type =
imp.importSym.info match
case ImportType(expr) =>
Expand All @@ -341,7 +345,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
// so we ignore that import.
if reallyExists(denot) && !isScalaJsPseudoUnion then
if unimported.isEmpty || !unimported.contains(pre.termSymbol) then
return pre.select(name, denot)
return pre.select(name, denot).makePackageObjPrefixExplicit
case _ =>
if imp.importSym.isCompleting then
report.warning(i"cyclic ${imp.importSym}, ignored", pos)
Expand Down Expand Up @@ -501,7 +505,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
defDenot.symbol.owner
else
curOwner
effectiveOwner.thisType.select(name, defDenot)
effectiveOwner.thisType.select(name, defDenot).makePackageObjPrefixExplicit
}
if !curOwner.is(Package) || isDefinedInCurrentUnit(defDenot) then
result = checkNewOrShadowed(found, Definition) // no need to go further out, we found highest prec entry
Expand Down
22 changes: 22 additions & 0 deletions tests/pos/i18097.1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
opaque type Pos = Double

object Pos:
extension (x: Pos)
def mult1(y: Pos): Pos = x * y

extension (x: Pos)
def mult2(y: Pos): Pos = x * y

class Test:
def test(key: String, a: Pos, b: Pos): Unit =
val tup1 = new Tuple1(Pos.mult1(a)(b))
val res1: Pos = tup1._1

val tup2 = new Tuple1(a.mult1(b))
val res2: Pos = tup2._1

val tup3 = new Tuple1(mult2(a)(b))
val res3: Pos = tup3._1

val tup4 = new Tuple1(a.mult2(b))
val res4: Pos = tup4._1 // was error: Found: (tup4._4 : Double) Required: Pos
13 changes: 13 additions & 0 deletions tests/pos/i18097.2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
opaque type Namespace = List[String]

object Namespace:
def apply(head: String): Namespace = List(head)

extension (ns: Namespace)
def appended(segment: String): Namespace = ns.appended(segment)

object Main:
def main(args: Array[String]): Unit =
val a: Namespace = Namespace("a")
.appended("B")
.appended("c") // was error: Found: List[String] Required: Namespace
13 changes: 13 additions & 0 deletions tests/pos/i18097.2.works.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
object Main:
opaque type Namespace = List[String]

object Namespace:
def apply(head: String): Namespace = List(head)

extension (ns: Namespace)
def appended(segment: String): Namespace = ns.appended(segment)

def main(args: Array[String]): Unit =
val a: Namespace = Namespace("a")
.appended("B")
.appended("c")
9 changes: 9 additions & 0 deletions tests/pos/i18097.3/Opaque.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package test

type Foo = Unit
val bar: Foo = ()

opaque type Opaque = Unit

extension (foo: Foo)
def go: Option[Opaque] = ???
13 changes: 13 additions & 0 deletions tests/pos/i18097.3/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package test

final case class Test(value: Opaque)

def test: Test =
bar.go match
case Some(value) => Test(value) // was error: Found: (value : Unit) Required: test.Opaque
case _ => ???

def test2: Test =
go(bar) match
case Some(value) => Test(value)
case _ => ???
20 changes: 20 additions & 0 deletions tests/pos/i18097.orig.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
opaque type PositiveNumber = Double

object PositiveNumber:
extension (x: PositiveNumber)
def mult1(other: PositiveNumber): PositiveNumber =
x * other

extension (x: PositiveNumber)
def mult2(other: PositiveNumber): PositiveNumber =
x * other

object Test:
def multMap1[A](x: Map[A, PositiveNumber], num: PositiveNumber): Map[A, PositiveNumber] = x.map((key, value) => key -> value.mult1(num)).toMap

def multMap2[A](x: Map[A, PositiveNumber], num: PositiveNumber): Map[A, PositiveNumber] = x.map((key, value) => key -> value.mult2(num)).toMap // was error
// ^
// Cannot prove that (A, Double) <:< (A, V2).
//
// where: V2 is a type variable with constraint <: PositiveNumber
def multMap2_2[A](x: Map[A, PositiveNumber], num: PositiveNumber): Map[A, PositiveNumber] = x.map((key, value) => key -> mult2(value)(num)).toMap

0 comments on commit d53c798

Please sign in to comment.