Skip to content

Commit 5648ca7

Browse files
authored
Merge pull request #5480 from dotty-staging/fix-#5455
Fix #5455: Fix computation of companion object of opaque type
2 parents 74477d9 + 7663d98 commit 5648ca7

File tree

5 files changed

+85
-5
lines changed

5 files changed

+85
-5
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Symbols._, StdNames._, Trees._
88
import Decorators._, transform.SymUtils._
99
import NameKinds.{UniqueName, EvidenceParamName, DefaultGetterName}
1010
import typer.FrontEnd
11+
import util.Property
1112
import collection.mutable.ListBuffer
1213
import reporting.diagnostic.messages._
1314
import reporting.trace
@@ -18,6 +19,11 @@ object desugar {
1819
import untpd._
1920
import DesugarEnums._
2021

22+
/** If a Select node carries this attachment, suppress the check
23+
* that its type refers to an acessible symbol.
24+
*/
25+
val SuppressAccessCheck = new Property.Key[Unit]
26+
2127
/** Info of a variable in a pattern: The named tree and its type */
2228
private type VarInfo = (NameTree, Tree)
2329

@@ -727,9 +733,11 @@ object desugar {
727733
fwd
728734
}
729735
val moduleName = tdef.name.toTermName
730-
val aliasType = cpy.TypeDef(tdef)(
731-
rhs = completeForwarder(Select(Ident(moduleName), tdef.name)))
732-
val localType = tdef.withFlags(Synthetic | Opaque)
736+
val localRef = Select(Ident(moduleName), tdef.name)
737+
localRef.pushAttachment(SuppressAccessCheck, ())
738+
val aliasType = cpy.TypeDef(tdef)(rhs = completeForwarder(localRef))
739+
val localType = tdef.withMods(Modifiers(Synthetic | Opaque).withPrivateWithin(tdef.name))
740+
733741
val companions = moduleDef(ModuleDef(
734742
moduleName, Template(emptyConstructor, Nil, EmptyValDef, localType :: Nil))
735743
.withFlags(Synthetic | Opaque))

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ object SymDenotations {
985985
if (is(Module)) sourceModule
986986
else if (isOpaqueAlias)
987987
info match {
988-
case TypeAlias(TypeRef(TermRef(prefix, _), _)) => prefix.termSymbol
988+
case TypeAlias(TypeRef(prefix: TermRef, _)) => prefix.termSymbol
989989
}
990990
else registeredCompanion.sourceModule
991991

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ trait TypeAssigner {
259259
qualType = errorType(em"$qualType takes type parameters", qual1.pos)
260260
else if (!qualType.isInstanceOf[TermType]) qualType = errorType(em"$qualType is illegal as a selection prefix", qual1.pos)
261261
val ownType = selectionType(qualType, tree.name, tree.pos)
262-
ensureAccessible(ownType, qual1.isInstanceOf[Super], tree.pos)
262+
if (tree.getAttachment(desugar.SuppressAccessCheck).isDefined) ownType
263+
else ensureAccessible(ownType, qual1.isInstanceOf[Super], tree.pos)
263264
}
264265

265266
/** Type assignment method. Each method takes as parameters

tests/neg/i5455.scala

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
object Library {
2+
3+
opaque type Nat = Int
4+
5+
object Nat {
6+
def apply(n: Int): Nat = {
7+
require(n >= 0)
8+
n
9+
}
10+
def times(x: Nat, y: Nat): Nat = x * y
11+
def toInt(n: Nat): Int = n
12+
13+
implicit class NatOps(val self: Nat) extends AnyVal {
14+
def *(other: Nat): Nat = self * other
15+
def toInt: Int = self.asInstanceOf
16+
}
17+
}
18+
}
19+
20+
object User extends App {
21+
import Library._
22+
23+
val x = Nat(3)
24+
val y = Nat(4)
25+
26+
val a = x * y
27+
val b = double1(x)
28+
val c = double2(x)
29+
30+
def double0(n: Nat): Nat = n * Nat(2) // ok
31+
32+
def double1(n: Nat.Nat): Nat = n * Nat(2) // error
33+
34+
def double2(n: Nat.Nat): Nat.Nat = n * Nat(2) // error // error
35+
}

tests/run/i5455.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
object Library {
2+
3+
opaque type Nat = Int
4+
5+
object Nat {
6+
def apply(n: Int): Nat = {
7+
require(n >= 0)
8+
n
9+
}
10+
def times(x: Nat, y: Nat): Nat = x * y
11+
def toInt(n: Nat): Int = n
12+
13+
implicit class NatOps(val self: Nat) extends AnyVal {
14+
def *(other: Nat): Nat = self * other
15+
def toInt: Int = self.asInstanceOf
16+
}
17+
}
18+
}
19+
20+
object Test extends App {
21+
import Library._
22+
23+
val x = Nat(3)
24+
val y = Nat(4)
25+
26+
val a = x * y
27+
val b = double1(x)
28+
val c = double2(x)
29+
30+
assert(a.toInt == 12)
31+
assert(b.toInt == 6)
32+
assert(c.toInt == 6)
33+
34+
def double1(n: Nat): Nat = n * Nat(2)
35+
def double2(n: Nat): Nat = Nat.NatOps(n) * Nat(2)
36+
}

0 commit comments

Comments
 (0)