aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-04-04 10:24:25 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-04-08 17:03:57 +0200
commitdcfd96328f350a6265d7aac55c411ab798e93e77 (patch)
treed07871190bb367e64235daa662d9f314696cc067 /src/dotty/tools
parentebd7df51e5b20e2c42717e216cc6be996d12c52a (diff)
downloaddotty-dcfd96328f350a6265d7aac55c411ab798e93e77.tar.gz
dotty-dcfd96328f350a6265d7aac55c411ab798e93e77.tar.bz2
dotty-dcfd96328f350a6265d7aac55c411ab798e93e77.zip
Shadowed references
In TypeAssigner#ensureAccible we sometimes pick an inherited public member as the denotation of a NamedType instead of an inaccessible private one. The problem is that both are denotations for the same type, which caused a noDoubleBindings assert failure. We now solve this problem by creating a "shadowed" named type to hold the inherited member. The shadowed named type is distinguished by its name, which reads (inherited)originalName In the future, we should make this more robust by using a general tagging scheme to create shadowed names. Another fix is about import symbols. They are now referenced with NonMemberTermRefs. With this fix, the test suite passes with no double def violations.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/config/Config.scala4
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala9
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala6
-rw-r--r--src/dotty/tools/dotc/core/Types.scala22
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala4
6 files changed, 29 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala
index 9b8bd27ec..e77b10bfb 100644
--- a/src/dotty/tools/dotc/config/Config.scala
+++ b/src/dotty/tools/dotc/config/Config.scala
@@ -13,13 +13,13 @@ object Config {
final val checkConstraintsNonCyclic = true
final val flagInstantiationToNothing = false
-
+
/** Enable noDoubleDef checking if option "-YnoDoubleDefs" is set.
* The reason to have an option as well as the present global switch is
* that the noDoubleDef checking is done in a hotspot, and we do not
* want to incur the overhead of checking an option each time.
*/
- final val checkTermRefs = false
+ final val checkNoDoubleBindings = true
/** Throw an exception if a deep subtype recursion is detected */
final val flagDeepSubTypeRecursions = true
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index 35f94aac7..22a7e5734 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -50,6 +50,9 @@ object NameOps {
implicit class NameDecorator[N <: Name](val name: N) extends AnyVal {
import nme._
+ def likeTyped(n: Name): N =
+ (if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N]
+
def isConstructorName = name == CONSTRUCTOR || name == IMPLCLASS_CONSTRUCTOR
def isExceptionResultName = name startsWith EXCEPTION_RESULT_PREFIX
def isImplClassName = name endsWith IMPL_CLASS_SUFFIX
@@ -62,6 +65,8 @@ object NameOps {
def isTraitSetterName = isSetterName && (name containsSlice TRAIT_SETTER_SEPARATOR)
def isSingletonName = name endsWith SINGLETON_SUFFIX
def isModuleClassName = name endsWith MODULE_SUFFIX
+ def isImportName = name startsWith IMPORT
+ def isInheritedName = name.head == '(' && name.startsWith(nme.INHERITED)
def isModuleVarName(name: Name): Boolean =
name.stripAnonNumberSuffix endsWith MODULE_VAR_SUFFIX
@@ -132,6 +137,10 @@ object NameOps {
if (idx < 0) name else (name drop (idx + separator.length)).asInstanceOf[N]
}
+ def inheritedName: N = likeTyped(nme.INHERITED ++ name)
+
+ def revertInherited: N = likeTyped(name.drop(nme.INHERITED.length))
+
/** Translate a name into a list of simple TypeNames and TermNames.
* In all segments before the last, type/term is determined by whether
* the following separator char is '.' or '#'. The last segment
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index d01971982..cb4272f7a 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -100,6 +100,7 @@ object StdNames {
val EXPAND_SEPARATOR: N = "$$"
val IMPL_CLASS_SUFFIX: N = "$class"
val IMPORT: N = "<import>"
+ val INHERITED: N = "(inherited)" // tag to be used until we have proper name kinds
val INTERPRETER_IMPORT_WRAPPER: N = "$iw"
val INTERPRETER_LINE_PREFIX: N = "line"
val INTERPRETER_VAR_PREFIX: N = "res"
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 7762f61dd..dc76999f6 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -684,7 +684,8 @@ object SymDenotations {
/** The symbol, in class `inClass`, that is overridden by this denotation. */
final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
- matchingSymbol(inClass, owner.thisType)
+ if ((this is Private) && (owner ne inClass)) NoSymbol
+ else matchingSymbol(inClass, owner.thisType)
/** All symbols overriden by this denotation. */
final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] =
@@ -731,6 +732,9 @@ object SymDenotations {
override def termRefWithSig(implicit ctx: Context): TermRef =
TermRef.withSig(owner.thisType, name.asTermName, signature, this)
+ def nonMemberTermRef(implicit ctx: Context): TermRef =
+ TermRef.withNonMemberSym(owner.thisType, name.asTermName, symbol.asTerm)
+
/** The variance of this type parameter or type member as an Int, with
* +1 = Covariant, -1 = Contravariant, 0 = Nonvariant, or not a type parameter
*/
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 1dba728bb..c348e246c 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -656,15 +656,6 @@ object Types {
if (res.exists) res else TypeRef(this, name, denot)
}
- /** The type <this . name> , reduced if possible, with given denotation if unreduced */
- def selectNonMember(name: Name, denot: Denotation)(implicit ctx: Context): Type = name match {
- case name: TermName =>
- TermRef(this, name, denot)
- case name: TypeName =>
- val res = lookupRefined(name)
- if (res.exists) res else TypeRef(this, name, denot)
- }
-
/** The type <this . name> with given symbol, reduced if possible */
def select(sym: Symbol)(implicit ctx: Context): Type =
if (sym.isTerm) TermRef(this, sym.asTerm)
@@ -1079,7 +1070,7 @@ object Types {
}
private[dotc] final def setDenot(denot: Denotation)(implicit ctx: Context): Unit = {
- if (Config.checkTermRefs)
+ if (Config.checkNoDoubleBindings)
if (ctx.settings.YnoDoubleBindings.value)
checkSymAssign(denot.symbol)
lastDenotation = denot
@@ -1095,7 +1086,7 @@ object Types {
}
private[dotc] final def setSym(sym: Symbol)(implicit ctx: Context): Unit = {
- if (Config.checkTermRefs)
+ if (Config.checkNoDoubleBindings)
if (ctx.settings.YnoDoubleBindings.value)
checkSymAssign(sym)
uncheckedSetSym(sym)
@@ -1111,7 +1102,9 @@ object Types {
TermRef.withSig(prefix, name.asTermName, sig)
protected def loadDenot(implicit ctx: Context) = {
- val d = prefix.member(name)
+ val d =
+ if (name.isInheritedName) prefix.nonPrivateMember(name.revertInherited)
+ else prefix.member(name)
if (d.exists || ctx.phaseId == FirstPhaseId)
d
else {// name has changed; try load in earlier phase and make current
@@ -1172,6 +1165,11 @@ object Types {
protected def newLikeThis(prefix: Type)(implicit ctx: Context): NamedType =
NamedType(prefix, name)
+ /** Create a NamedType of the same kind as this type, but with a new name.
+ */
+ final def shadowed(implicit ctx: Context): NamedType =
+ NamedType(prefix, name.inheritedName)
+
override def equals(that: Any) = that match {
case that: NamedType =>
this.name == that.name &&
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index b194bdd60..12f2415d8 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -110,7 +110,7 @@ trait TypeAssigner {
// an inherited non-private member with the same name and signature.
val d2 = pre.nonPrivateMember(name)
if (reallyExists(d2) && firstTry)
- test(pre.select(name, d2), false)
+ test(tpe.shadowed.withDenot(d2), false)
else {
val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists)
val what = alts match {
@@ -326,7 +326,7 @@ trait TypeAssigner {
tree.withType(sym.typeRef)
def assignType(tree: untpd.Import, sym: Symbol)(implicit ctx: Context) =
- tree.withType(sym.termRef)
+ tree.withType(sym.nonMemberTermRef)
def assignType(tree: untpd.Annotated, annot: Tree, arg: Tree)(implicit ctx: Context) =
tree.withType(AnnotatedType(Annotation(annot), arg.tpe))