diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 81a54cdc1f29..f902bb14df2f 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -934,6 +934,9 @@ object SymDenotations { ( !this.is(Local) || isAccessPrivilegedThisType(pre) || canBeLocal(name, flags) + && { + !symbol.defTree.hasAttachment(typer.Typer.OriginallyPrivateLocal) + } && { resetFlag(Local) true @@ -2658,11 +2661,9 @@ object SymDenotations { * This holds for all symbols except * - constructors, since they can never be referred to as members of their * own, fully elaborated `this`. - * - parameters and parameter accessors, since their Local status is already - * determined by whether they have a `val` or `var` or not. */ def canBeLocal(name: Name, flags: FlagSet)(using Context) = - !name.isConstructorName && !flags.is(Param) && !flags.is(ParamAccessor) + !name.isConstructorName /** Factory method for SymDenotion creation. All creations * should be done via this method. diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index b6b3ac34d130..7f99cc289679 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -87,6 +87,10 @@ object Typer { /** Tree adaptation lost fidelity; this attachment preserves the original tree. */ val AdaptedTree = new Property.StickyKey[tpd.Tree] + /** An attachment on a tree that was originally private local + */ + val OriginallyPrivateLocal = new Property.Key[Unit] + /** An attachment on a Select node with an `apply` field indicating that the `apply` * was inserted by the Typer. */ @@ -3039,6 +3043,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer report.error(em"Cannot return repeated parameter type ${sym.info.finalResultType}", sym.srcPos) if !sym.is(Module) && !sym.isConstructor && sym.info.finalResultType.isErasedClass then sym.setFlag(Erased) + // This is probably too late. Do this in Namer? + if mdef.isInstanceOf[ValDef] && sym.isAllOf(PrivateLocal) then + mdef.putAttachment(OriginallyPrivateLocal, ()) mdef.ensureHasSym(sym) mdef.setDefTree diff --git a/tests/neg/i22620.scala b/tests/neg/i22620.scala deleted file mode 100644 index 97d1d55e3302..000000000000 --- a/tests/neg/i22620.scala +++ /dev/null @@ -1,4 +0,0 @@ - -import scala.collection.mutable.ArrayBuffer - -class PrivateTest[-M](private val v: ArrayBuffer[M]) // error diff --git a/tests/pos/i22620.scala b/tests/pos/i22620.scala new file mode 100644 index 000000000000..9ed543815bd8 --- /dev/null +++ b/tests/pos/i22620.scala @@ -0,0 +1,4 @@ +import scala.collection.mutable.ArrayBuffer + +class PrivateTest[-M](private val v: ArrayBuffer[M]) + diff --git a/tests/pos/private-local-override.scala b/tests/pos/private-local-override.scala new file mode 100644 index 000000000000..3bc015ffb1e5 --- /dev/null +++ b/tests/pos/private-local-override.scala @@ -0,0 +1,11 @@ +sealed abstract class Tree[+A]( + final val key: A +) +final class RedTree[+A](key: A) extends Tree[A](key) +final class BlackTree[+A](key: A) extends Tree[A](key) +object RedTree { + def unapply[A](t: RedTree[A]) = Some((t.key)) +} +object BlackTree { + def unapply[A](t: BlackTree[A]) = Some((t.key)) +}