Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pkg obj prefix of opaque tp ext meth #21527

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading