Skip to content

Commit

Permalink
Heal member-select on opaque reference
Browse files Browse the repository at this point in the history
When the prefix of an opaque isn't the .this reference of the module
class, then its RHS isn't visible.  TypeComparer uses ctx.owner to
"heal" or "lift" this type such that it is.  We reuse that logic for
member selection.
  • Loading branch information
dwijnand committed Mar 4, 2024
1 parent c4ddadb commit f9025c9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
11 changes: 11 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
typedSelectWithAdapt(tree, pt, qual)
else EmptyTree

def tryLiftToThis() =
val wtp = qual.tpe.widen
val liftedTp = comparing(_.liftToThis(wtp))
if liftedTp ne wtp then
val qual1 = qual.cast(liftedTp)
val tree1 = cpy.Select(tree0)(qual1, selName)
val rawType1 = selectionType(tree1, qual1)
tryType(tree1, qual1, rawType1)
else EmptyTree

def trySmallGenericTuple(tree: untpd.Select, qual: Tree, withCast: Boolean) =
if qual.tpe.isSmallGenericTuple then
if withCast then
Expand Down Expand Up @@ -761,6 +771,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
tryType(tree, qual, rawType)
.orElse(trySimplifyApply())
.orElse(tryInstantiateTypeVar())
.orElse(tryLiftToThis())
.orElse(trySmallGenericTuple(tree, qual, withCast = true))
.orElse(tryExt(tree, qual))
.orElse(tryGadt(tree))
Expand Down
12 changes: 12 additions & 0 deletions tests/pos/i19609.orig.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
object o {
opaque type T = String

summon[o.T =:= T] // OK
summon[o.T =:= String] // OK

def test1(t: T): Int =
t.length // OK

def test2(t: o.T): Int =
t.length // Error: value length is not a member of Playground.o.T
}
24 changes: 24 additions & 0 deletions tests/pos/i19609.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
object o { u =>
opaque type T = String

def st = summon[String =:= T]
def su = summon[String =:= u.T]
def so = summon[String =:= o.T]

def ts = summon[T =:= String]
def tu = summon[T =:= u.T]
def to = summon[T =:= o.T]

def us = summon[u.T =:= String]
def ut = summon[u.T =:= T]
def uo = summon[u.T =:= o.T]

def os = summon[o.T =:= String]
def ot = summon[o.T =:= T]
def ou = summon[o.T =:= u.T]

def ms(x: String): Int = x.length // ok
def mt(x: T): Int = x.length // ok
def mu(x: u.T): Int = x.length // ok
def mo(x: o.T): Int = x.length // was: error: value length is not a member of o.T
}

0 comments on commit f9025c9

Please sign in to comment.