Skip to content

Commit 83fb072

Browse files
authored
Merge pull request #14666 from dotty-staging/fix-14660
Disallow private opaque type aliases
2 parents b505b08 + fe6c299 commit 83fb072

File tree

6 files changed

+24
-4
lines changed

6 files changed

+24
-4
lines changed

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ object Denotations {
403403
}
404404
case denot1: SingleDenotation =>
405405
if (denot1 eq denot2) denot1
406-
else if (denot1.matches(denot2)) mergeSingleDenot(denot1, denot2)
406+
else if denot1.matches(denot2) then mergeSingleDenot(denot1, denot2)
407407
else NoDenotation
408408
}
409409

@@ -438,8 +438,11 @@ object Denotations {
438438
else defn.RootClass)
439439

440440
def isHidden(sym: Symbol) = sym.exists && !sym.isAccessibleFrom(pre)
441-
val hidden1 = isHidden(sym1)
442-
val hidden2 = isHidden(sym2)
441+
// In typer phase filter out denotations with symbols that are not
442+
// accessible. After typer, this is not possible since we cannot guarantee
443+
// that the current owner is set correctly. See pos/14660.scala.
444+
val hidden1 = isHidden(sym1) && ctx.isTyper
445+
val hidden2 = isHidden(sym2) && ctx.isTyper
443446
if hidden1 && !hidden2 then denot2
444447
else if hidden2 && !hidden1 then denot1
445448
else

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ object Checking {
537537
checkCombination(Private, Protected)
538538
checkCombination(Abstract, Override)
539539
checkCombination(Private, Override)
540+
if sym.isType && !sym.isClass then checkCombination(Private, Opaque)
540541
checkCombination(Lazy, Inline)
541542
// The issue with `erased inline` is that the erased semantics get lost
542543
// as the code is inlined and the reference is removed before the erased usage check.

compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ object QuoteMatcher {
441441
}
442442

443443
/** Result of matching a part of an expression */
444-
private opaque type Matching = Option[Tuple]
444+
private type Matching = Option[Tuple]
445445

446446
private object Matching {
447447

docs/_docs/reference/other-new-features/opaques-details.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ object o:
5151
def id(x: o.T): o.T = x
5252
```
5353

54+
Opaque type aliases cannot be `private` and cannot be overridden in subclasses.
55+
5456
## Type Parameters of Opaque Types
5557

5658
Opaque type aliases can have a single type parameter list. The following aliases

tests/neg/i14660.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Bar:
2+
private opaque type Baz = Int // error
3+
4+
private object Foo:
5+
opaque type O = Int // OK
6+
7+
val x: Baz = 1
8+

tests/pos/i14660.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
trait Foo:
2+
class Bar:
3+
private[Foo] opaque type Baz = Int
4+
5+
def foo: Bar#Baz
6+

0 commit comments

Comments
 (0)