Skip to content

Commit 6bc463d

Browse files
committed
Merge pull request #115 from dotty-staging/fix/double-bindings
Fix/double bindings
2 parents 26185f6 + dcfd963 commit 6bc463d

28 files changed

+459
-147
lines changed

src/dotty/tools/dotc/Run.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
5151

5252
private def printTree(ctx: Context) = {
5353
val unit = ctx.compilationUnit
54-
println(s"result of $unit after ${ctx.phase}:")
54+
println(s"result of $unit after ${ctx.phase.prev}:")
5555
println(unit.tpdTree.show(ctx))
5656
}
5757

src/dotty/tools/dotc/ast/tpd.scala

+4-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
2929
untpd.Select(qualifier, tp.name).withType(tp)
3030

3131
def Select(qualifier: Tree, sym: Symbol)(implicit ctx: Context): Select =
32-
untpd.Select(qualifier, sym.name).withType(qualifier.tpe select sym)
32+
untpd.Select(qualifier, sym.name).withType(
33+
TermRef.withSig(qualifier.tpe, sym.name.asTermName, sym.signature, sym.denot))
3334

3435
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ctx: Context) =
3536
untpd.SelectWithSig(qualifier, name, sig)
@@ -259,10 +260,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
259260
/** new C(args) */
260261
def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply = {
261262
val targs = tp.argTypes
263+
val constr = tp.typeSymbol.primaryConstructor.asTerm
262264
Apply(
263265
Select(
264266
New(tp withoutArgs targs),
265-
TermRef(tp.normalizedPrefix, tp.typeSymbol.primaryConstructor.asTerm))
267+
TermRef.withSig(tp.normalizedPrefix, constr))
266268
.appliedToTypes(targs),
267269
args)
268270
}

src/dotty/tools/dotc/config/Config.scala

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ object Config {
1414

1515
final val flagInstantiationToNothing = false
1616

17+
/** Enable noDoubleDef checking if option "-YnoDoubleDefs" is set.
18+
* The reason to have an option as well as the present global switch is
19+
* that the noDoubleDef checking is done in a hotspot, and we do not
20+
* want to incur the overhead of checking an option each time.
21+
*/
22+
final val checkNoDoubleBindings = true
23+
1724
/** Throw an exception if a deep subtype recursion is detected */
1825
final val flagDeepSubTypeRecursions = true
1926

src/dotty/tools/dotc/config/ScalaSettings.scala

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ class ScalaSettings extends Settings.SettingGroup {
163163
val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
164164
val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.")
165165
val Yexplainlowlevel = BooleanSetting("-Yexplainlowlevel", "When explaining type errors, show types at a lower level.")
166+
val YnoDoubleBindings = BooleanSetting("-YnoDoubleBindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).")
166167

167168
val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize"
168169

src/dotty/tools/dotc/core/Contexts.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ object Contexts {
189189
private var phasedCtx: Context = _
190190
private var phasedCtxs: Array[Context] = _
191191

192-
193192
/** This context at given phase.
194193
* This method will always return a phase period equal to phaseId, thus will never return squashed phases
195194
*/
@@ -211,7 +210,7 @@ object Contexts {
211210
final def withPhase(phase: Phase): Context =
212211
withPhase(phase.id)
213212

214-
/** If -Ydebug is on, the top of the stack trace where this context
213+
/** If -Ydebug is on, the top of the stack trace where this context
215214
* was created, otherwise `null`.
216215
*/
217216
private var creationTrace: Array[StackTraceElement] = _

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

+26-27
Original file line numberDiff line numberDiff line change
@@ -273,35 +273,34 @@ object Denotations {
273273

274274
def unionDenot(denot1: SingleDenotation, denot2: SingleDenotation): Denotation =
275275
if (denot1.signature matches denot2.signature) {
276+
val sym1 = denot1.symbol
277+
val sym2 = denot2.symbol
276278
val info1 = denot1.info
277279
val info2 = denot2.info
278-
val sym2 = denot2.symbol
279-
def sym2Accessible = sym2.isAccessibleFrom(pre)
280-
if (info1 <:< info2 && sym2Accessible) denot2
280+
val sameSym = sym1 eq sym2
281+
if (sameSym && info1 <:< info2) denot2
282+
else if (sameSym && info2 <:< info1) denot1
281283
else {
282-
val sym1 = denot1.symbol
283-
def sym1Accessible = sym1.isAccessibleFrom(pre)
284-
if (info2 <:< info1 && sym1Accessible) denot1
285-
else {
286-
val owner2 = if (sym2 ne NoSymbol) sym2.owner else NoSymbol
287-
/** Determine a symbol which is overridden by both sym1 and sym2.
288-
* Preference is given to accessible symbols.
289-
*/
290-
def lubSym(overrides: Iterator[Symbol], previous: Symbol): Symbol =
291-
if (!overrides.hasNext) previous
292-
else {
293-
val candidate = overrides.next
294-
if (owner2 derivesFrom candidate.owner)
295-
if (candidate isAccessibleFrom pre) candidate
296-
else lubSym(overrides, previous orElse candidate)
297-
else
298-
lubSym(overrides, previous)
299-
}
300-
new JointRefDenotation(
301-
lubSym(sym1.allOverriddenSymbols, NoSymbol),
302-
info1 | info2,
303-
denot1.validFor & denot2.validFor)
304-
}
284+
val jointSym =
285+
if (sameSym) sym1
286+
else {
287+
val owner2 = if (sym2 ne NoSymbol) sym2.owner else NoSymbol
288+
/** Determine a symbol which is overridden by both sym1 and sym2.
289+
* Preference is given to accessible symbols.
290+
*/
291+
def lubSym(overrides: Iterator[Symbol], previous: Symbol): Symbol =
292+
if (!overrides.hasNext) previous
293+
else {
294+
val candidate = overrides.next
295+
if (owner2 derivesFrom candidate.owner)
296+
if (candidate isAccessibleFrom pre) candidate
297+
else lubSym(overrides, previous orElse candidate)
298+
else
299+
lubSym(overrides, previous)
300+
}
301+
lubSym(sym1.allOverriddenSymbols, NoSymbol)
302+
}
303+
new JointRefDenotation(jointSym, info1 | info2, denot1.validFor & denot2.validFor)
305304
}
306305
}
307306
else NoDenotation
@@ -335,7 +334,7 @@ object Denotations {
335334
final def info(implicit ctx: Context) = infoOrCompleter
336335
final def validFor = denot1.validFor & denot2.validFor
337336
final def isType = false
338-
def signature(implicit ctx: Context) = multiHasNot("signature")
337+
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
339338
def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation =
340339
denot1.atSignature(sig) orElse denot2.atSignature(sig)
341340
def current(implicit ctx: Context): Denotation =

src/dotty/tools/dotc/core/NameOps.scala

+9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ object NameOps {
5050
implicit class NameDecorator[N <: Name](val name: N) extends AnyVal {
5151
import nme._
5252

53+
def likeTyped(n: Name): N =
54+
(if (name.isTermName) n.toTermName else n.toTypeName).asInstanceOf[N]
55+
5356
def isConstructorName = name == CONSTRUCTOR || name == IMPLCLASS_CONSTRUCTOR
5457
def isExceptionResultName = name startsWith EXCEPTION_RESULT_PREFIX
5558
def isImplClassName = name endsWith IMPL_CLASS_SUFFIX
@@ -62,6 +65,8 @@ object NameOps {
6265
def isTraitSetterName = isSetterName && (name containsSlice TRAIT_SETTER_SEPARATOR)
6366
def isSingletonName = name endsWith SINGLETON_SUFFIX
6467
def isModuleClassName = name endsWith MODULE_SUFFIX
68+
def isImportName = name startsWith IMPORT
69+
def isInheritedName = name.head == '(' && name.startsWith(nme.INHERITED)
6570

6671
def isModuleVarName(name: Name): Boolean =
6772
name.stripAnonNumberSuffix endsWith MODULE_VAR_SUFFIX
@@ -132,6 +137,10 @@ object NameOps {
132137
if (idx < 0) name else (name drop (idx + separator.length)).asInstanceOf[N]
133138
}
134139

140+
def inheritedName: N = likeTyped(nme.INHERITED ++ name)
141+
142+
def revertInherited: N = likeTyped(name.drop(nme.INHERITED.length))
143+
135144
/** Translate a name into a list of simple TypeNames and TermNames.
136145
* In all segments before the last, type/term is determined by whether
137146
* the following separator char is '.' or '#'. The last segment

src/dotty/tools/dotc/core/Signature.scala

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package dotty.tools.dotc
22
package core
33

4-
import Names._, Types._, Contexts._
4+
import Names._, Types._, Contexts._, StdNames._
55
import transform.Erasure.sigName
66

77
/** The signature of a denotation.
@@ -49,6 +49,10 @@ object Signature {
4949
* a type different from PolyType, MethodType, or ExprType.
5050
*/
5151
val NotAMethod = Signature(List(), EmptyTypeName)
52+
53+
/** The signature of an overloaded denotation.
54+
*/
55+
val OverloadedSignature = Signature(List(tpnme.OVERLOADED), EmptyTypeName)
5256

5357
/** The signature of a method with no parameters and result type `resultType`. */
5458
def apply(resultType: Type, isJava: Boolean)(implicit ctx: Context): Signature =

src/dotty/tools/dotc/core/StdNames.scala

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ object StdNames {
100100
val EXPAND_SEPARATOR: N = "$$"
101101
val IMPL_CLASS_SUFFIX: N = "$class"
102102
val IMPORT: N = "<import>"
103+
val INHERITED: N = "(inherited)" // tag to be used until we have proper name kinds
103104
val INTERPRETER_IMPORT_WRAPPER: N = "$iw"
104105
val INTERPRETER_LINE_PREFIX: N = "line"
105106
val INTERPRETER_VAR_PREFIX: N = "res"
@@ -109,6 +110,7 @@ object StdNames {
109110
val MODULE_VAR_SUFFIX: N = "$module"
110111
val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING
111112
val USCORE_PARAM_PREFIX: N = "_$"
113+
val OVERLOADED: N = "<overloaded>"
112114
val PACKAGE: N = "package"
113115
val PACKAGE_CLS: N = "package$"
114116
val PROTECTED_PREFIX: N = "protected$"

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,8 @@ object SymDenotations {
684684

685685
/** The symbol, in class `inClass`, that is overridden by this denotation. */
686686
final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
687-
matchingSymbol(inClass, owner.thisType)
687+
if ((this is Private) && (owner ne inClass)) NoSymbol
688+
else matchingSymbol(inClass, owner.thisType)
688689

689690
/** All symbols overriden by this denotation. */
690691
final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] =
@@ -731,6 +732,9 @@ object SymDenotations {
731732
override def termRefWithSig(implicit ctx: Context): TermRef =
732733
TermRef.withSig(owner.thisType, name.asTermName, signature, this)
733734

735+
def nonMemberTermRef(implicit ctx: Context): TermRef =
736+
TermRef.withNonMemberSym(owner.thisType, name.asTermName, symbol.asTerm)
737+
734738
/** The variance of this type parameter or type member as an Int, with
735739
* +1 = Covariant, -1 = Contravariant, 0 = Nonvariant, or not a type parameter
736740
*/

src/dotty/tools/dotc/core/Symbols.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ trait Symbols { this: Context =>
245245
for (name <- names) {
246246
val tparam = newNakedSymbol[TypeName](NoCoord)
247247
tparamBuf += tparam
248-
trefBuf += TypeRef(owner.thisType, name) withSym tparam
248+
trefBuf += TypeRef(owner.thisType, name).withSym(tparam, Signature.NotAMethod)
249249
}
250250
val tparams = tparamBuf.toList
251251
val bounds = boundsFn(trefBuf.toList)
@@ -319,7 +319,7 @@ object Symbols {
319319
type ThisName <: Name
320320

321321
private[this] var _id: Int = nextId
322-
//assert(_id != 5859)
322+
//assert(_id != 12325)
323323

324324
/** The unique id of this symbol */
325325
def id = _id

0 commit comments

Comments
 (0)