From 90c1a5f97db02d4af1a6e05f79285c5229f74702 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Wed, 15 Mar 2017 18:21:02 +0100 Subject: Fix #2099: avoid loading a private member when recomputing a NamedType denot ParamForwarding creates the following forwarder in B: private[this] def member: Int = super.member Where the type for `super.member` is `TermRef(SubA, member)` and the symbol is the `val member` in `A`. So far this is correct, but in later phases we might call `loadDenot` on this `TermRef` which will end up calling `asMemberOf`, which before this commit just did: prefix.member(name) This is incorrect in our case because `SubA` also happens to have a private `def member`, which means that our forwarder in B now forwards to a private method in a superclass, this subsequently crashes in `ExpandPrivate`. (Note: in the bytecode, a private method cannot have the same name as an overriden method, but this is already worked around in EnsurePrivate.) The fix is simple: when we recompute a member, we should only look at private members if the previous denotation was private. --- compiler/src/dotty/tools/dotc/core/Types.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'compiler/src') diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index abc496ec0..c88342e12 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1585,8 +1585,12 @@ object Types { protected def asMemberOf(prefix: Type)(implicit ctx: Context): Denotation = if (name.isShadowedName) prefix.nonPrivateMember(name.revertShadowed) - else prefix.member(name) - + else { + val d = lastDenotation + // Never go from a non-private denotation to a private one + if (d == null || d.symbol.is(Private)) prefix.member(name) + else prefix.nonPrivateMember(name) + } /** (1) Reduce a type-ref `W # X` or `W { ... } # U`, where `W` is a wildcard type * to an (unbounded) wildcard type. -- cgit v1.2.3 From 1821944511457d6f212b3d577101242ef9e77984 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Thu, 16 Mar 2017 00:07:27 +0100 Subject: Don't force denotations in asMemberOf This was introduced in the previous commit and caused unpickling failures, we are now more conservative and only check the Private flag on SymDenotations so we don't have to load any other denotation. --- compiler/src/dotty/tools/dotc/core/Types.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'compiler/src') diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index c88342e12..fa1b6dda6 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1585,11 +1585,12 @@ object Types { protected def asMemberOf(prefix: Type)(implicit ctx: Context): Denotation = if (name.isShadowedName) prefix.nonPrivateMember(name.revertShadowed) - else { - val d = lastDenotation - // Never go from a non-private denotation to a private one - if (d == null || d.symbol.is(Private)) prefix.member(name) - else prefix.nonPrivateMember(name) + else lastDenotation match { + case d: SymDenotation if !d.is(Private) => + // We shouldn't go from a non-private denotation to a private one + prefix.nonPrivateMember(name) + case _ => + prefix.member(name) } /** (1) Reduce a type-ref `W # X` or `W { ... } # U`, where `W` is a wildcard type -- cgit v1.2.3 From ddb8098b0f063bebe13f42387944508b7493859b Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Thu, 16 Mar 2017 15:02:10 +0100 Subject: Allow going from non-priv to priv denot when run changes --- compiler/src/dotty/tools/dotc/core/Types.scala | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'compiler/src') diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index fa1b6dda6..6c27e53f6 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1482,7 +1482,7 @@ object Types { /** A member of `prefix` (disambiguated by `d.signature`) or, if none was found, `d.current`. */ private def recomputeMember(d: SymDenotation)(implicit ctx: Context): Denotation = - asMemberOf(prefix) match { + asMemberOf(prefix, allowPrivate = d.is(Private)) match { case NoDenotation => d.current case newd: SingleDenotation => newd case newd => @@ -1573,7 +1573,7 @@ object Types { TermRef.withSig(prefix, name.asTermName, sig) protected def loadDenot(implicit ctx: Context): Denotation = { - val d = asMemberOf(prefix) + val d = asMemberOf(prefix, allowPrivate = true) if (d.exists || ctx.phaseId == FirstPhaseId || !lastDenotation.isInstanceOf[SymDenotation]) d else { // name has changed; try load in earlier phase and make current @@ -1583,15 +1583,10 @@ object Types { } } - protected def asMemberOf(prefix: Type)(implicit ctx: Context): Denotation = + protected def asMemberOf(prefix: Type, allowPrivate: Boolean)(implicit ctx: Context): Denotation = if (name.isShadowedName) prefix.nonPrivateMember(name.revertShadowed) - else lastDenotation match { - case d: SymDenotation if !d.is(Private) => - // We shouldn't go from a non-private denotation to a private one - prefix.nonPrivateMember(name) - case _ => - prefix.member(name) - } + else if (!allowPrivate) prefix.nonPrivateMember(name) + else prefix.member(name) /** (1) Reduce a type-ref `W # X` or `W { ... } # U`, where `W` is a wildcard type * to an (unbounded) wildcard type. @@ -1791,7 +1786,7 @@ object Types { val candidate = TermRef.withSig(prefix, name, sig) if (symbol.exists && !candidate.symbol.exists) { // recompute from previous symbol val ownSym = symbol - val newd = asMemberOf(prefix) + val newd = asMemberOf(prefix, allowPrivate = ownSym.is(Private)) candidate.withDenot(newd.suchThat(_.signature == ownSym.signature)) } else candidate -- cgit v1.2.3