aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/Run.scala2
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala6
-rw-r--r--src/dotty/tools/dotc/config/Config.scala7
-rw-r--r--src/dotty/tools/dotc/config/ScalaSettings.scala1
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala3
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala53
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala9
-rw-r--r--src/dotty/tools/dotc/core/Signature.scala6
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala2
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala6
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala4
-rw-r--r--src/dotty/tools/dotc/core/Types.scala146
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala9
-rw-r--r--src/dotty/tools/dotc/transform/Splitter.scala106
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala37
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala11
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala3
-rw-r--r--src/dotty/tools/dotc/typer/ReTyper.scala4
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala5
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala9
-rw-r--r--test/dotc/tests.scala6
-rw-r--r--tests/neg/t0586.scala (renamed from tests/pos/t0586.scala)0
-rw-r--r--tests/neg/t0625.scala (renamed from tests/pos/t0625.scala)0
-rw-r--r--tests/neg/typers.scala62
-rw-r--r--tests/pos/alias.scala3
-rw-r--r--tests/pos/typers.scala84
-rw-r--r--tests/pos/unions.scala18
28 files changed, 459 insertions, 147 deletions
diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala
index 264373baf..247fa4336 100644
--- a/src/dotty/tools/dotc/Run.scala
+++ b/src/dotty/tools/dotc/Run.scala
@@ -51,7 +51,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
private def printTree(ctx: Context) = {
val unit = ctx.compilationUnit
- println(s"result of $unit after ${ctx.phase}:")
+ println(s"result of $unit after ${ctx.phase.prev}:")
println(unit.tpdTree.show(ctx))
}
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 3664263e6..9a9ffe243 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -29,7 +29,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
untpd.Select(qualifier, tp.name).withType(tp)
def Select(qualifier: Tree, sym: Symbol)(implicit ctx: Context): Select =
- untpd.Select(qualifier, sym.name).withType(qualifier.tpe select sym)
+ untpd.Select(qualifier, sym.name).withType(
+ TermRef.withSig(qualifier.tpe, sym.name.asTermName, sym.signature, sym.denot))
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ctx: Context) =
untpd.SelectWithSig(qualifier, name, sig)
@@ -259,10 +260,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
/** new C(args) */
def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply = {
val targs = tp.argTypes
+ val constr = tp.typeSymbol.primaryConstructor.asTerm
Apply(
Select(
New(tp withoutArgs targs),
- TermRef(tp.normalizedPrefix, tp.typeSymbol.primaryConstructor.asTerm))
+ TermRef.withSig(tp.normalizedPrefix, constr))
.appliedToTypes(targs),
args)
}
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala
index f69566733..e77b10bfb 100644
--- a/src/dotty/tools/dotc/config/Config.scala
+++ b/src/dotty/tools/dotc/config/Config.scala
@@ -14,6 +14,13 @@ object Config {
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 checkNoDoubleBindings = true
+
/** Throw an exception if a deep subtype recursion is detected */
final val flagDeepSubTypeRecursions = true
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala
index 144e146c1..aab2942bd 100644
--- a/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -163,6 +163,7 @@ class ScalaSettings extends Settings.SettingGroup {
val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.")
val Yexplainlowlevel = BooleanSetting("-Yexplainlowlevel", "When explaining type errors, show types at a lower level.")
+ val YnoDoubleBindings = BooleanSetting("-YnoDoubleBindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).")
val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize"
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 4f95ff247..b662326c5 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -189,7 +189,6 @@ object Contexts {
private var phasedCtx: Context = _
private var phasedCtxs: Array[Context] = _
-
/** This context at given phase.
* This method will always return a phase period equal to phaseId, thus will never return squashed phases
*/
@@ -211,7 +210,7 @@ object Contexts {
final def withPhase(phase: Phase): Context =
withPhase(phase.id)
- /** If -Ydebug is on, the top of the stack trace where this context
+ /** If -Ydebug is on, the top of the stack trace where this context
* was created, otherwise `null`.
*/
private var creationTrace: Array[StackTraceElement] = _
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index e9b9b20c4..63b94efbd 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -273,35 +273,34 @@ object Denotations {
def unionDenot(denot1: SingleDenotation, denot2: SingleDenotation): Denotation =
if (denot1.signature matches denot2.signature) {
+ val sym1 = denot1.symbol
+ val sym2 = denot2.symbol
val info1 = denot1.info
val info2 = denot2.info
- val sym2 = denot2.symbol
- def sym2Accessible = sym2.isAccessibleFrom(pre)
- if (info1 <:< info2 && sym2Accessible) denot2
+ val sameSym = sym1 eq sym2
+ if (sameSym && info1 <:< info2) denot2
+ else if (sameSym && info2 <:< info1) denot1
else {
- val sym1 = denot1.symbol
- def sym1Accessible = sym1.isAccessibleFrom(pre)
- if (info2 <:< info1 && sym1Accessible) denot1
- else {
- val owner2 = if (sym2 ne NoSymbol) sym2.owner else NoSymbol
- /** Determine a symbol which is overridden by both sym1 and sym2.
- * Preference is given to accessible symbols.
- */
- def lubSym(overrides: Iterator[Symbol], previous: Symbol): Symbol =
- if (!overrides.hasNext) previous
- else {
- val candidate = overrides.next
- if (owner2 derivesFrom candidate.owner)
- if (candidate isAccessibleFrom pre) candidate
- else lubSym(overrides, previous orElse candidate)
- else
- lubSym(overrides, previous)
- }
- new JointRefDenotation(
- lubSym(sym1.allOverriddenSymbols, NoSymbol),
- info1 | info2,
- denot1.validFor & denot2.validFor)
- }
+ val jointSym =
+ if (sameSym) sym1
+ else {
+ val owner2 = if (sym2 ne NoSymbol) sym2.owner else NoSymbol
+ /** Determine a symbol which is overridden by both sym1 and sym2.
+ * Preference is given to accessible symbols.
+ */
+ def lubSym(overrides: Iterator[Symbol], previous: Symbol): Symbol =
+ if (!overrides.hasNext) previous
+ else {
+ val candidate = overrides.next
+ if (owner2 derivesFrom candidate.owner)
+ if (candidate isAccessibleFrom pre) candidate
+ else lubSym(overrides, previous orElse candidate)
+ else
+ lubSym(overrides, previous)
+ }
+ lubSym(sym1.allOverriddenSymbols, NoSymbol)
+ }
+ new JointRefDenotation(jointSym, info1 | info2, denot1.validFor & denot2.validFor)
}
}
else NoDenotation
@@ -335,7 +334,7 @@ object Denotations {
final def info(implicit ctx: Context) = infoOrCompleter
final def validFor = denot1.validFor & denot2.validFor
final def isType = false
- def signature(implicit ctx: Context) = multiHasNot("signature")
+ final def signature(implicit ctx: Context) = Signature.OverloadedSignature
def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation =
denot1.atSignature(sig) orElse denot2.atSignature(sig)
def current(implicit ctx: Context): Denotation =
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/Signature.scala b/src/dotty/tools/dotc/core/Signature.scala
index 02b91b18e..eb85fbb99 100644
--- a/src/dotty/tools/dotc/core/Signature.scala
+++ b/src/dotty/tools/dotc/core/Signature.scala
@@ -1,7 +1,7 @@
package dotty.tools.dotc
package core
-import Names._, Types._, Contexts._
+import Names._, Types._, Contexts._, StdNames._
import transform.Erasure.sigName
/** The signature of a denotation.
@@ -49,6 +49,10 @@ object Signature {
* a type different from PolyType, MethodType, or ExprType.
*/
val NotAMethod = Signature(List(), EmptyTypeName)
+
+ /** The signature of an overloaded denotation.
+ */
+ val OverloadedSignature = Signature(List(tpnme.OVERLOADED), EmptyTypeName)
/** The signature of a method with no parameters and result type `resultType`. */
def apply(resultType: Type, isJava: Boolean)(implicit ctx: Context): Signature =
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 3982c51f0..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"
@@ -109,6 +110,7 @@ object StdNames {
val MODULE_VAR_SUFFIX: N = "$module"
val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING
val USCORE_PARAM_PREFIX: N = "_$"
+ val OVERLOADED: N = "<overloaded>"
val PACKAGE: N = "package"
val PACKAGE_CLS: N = "package$"
val PROTECTED_PREFIX: N = "protected$"
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/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index b4db26ae6..8f66830e8 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -245,7 +245,7 @@ trait Symbols { this: Context =>
for (name <- names) {
val tparam = newNakedSymbol[TypeName](NoCoord)
tparamBuf += tparam
- trefBuf += TypeRef(owner.thisType, name) withSym tparam
+ trefBuf += TypeRef(owner.thisType, name).withSym(tparam, Signature.NotAMethod)
}
val tparams = tparamBuf.toList
val bounds = boundsFn(trefBuf.toList)
@@ -319,7 +319,7 @@ object Symbols {
type ThisName <: Name
private[this] var _id: Int = nextId
- //assert(_id != 5859)
+ //assert(_id != 12325)
/** The unique id of this symbol */
def id = _id
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 8799f9fd0..c348e246c 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -991,6 +991,8 @@ object Types {
val prefix: Type
val name: Name
+ type ThisType >: this.type <: NamedType
+
assert(prefix.isValueType || (prefix eq NoPrefix), s"invalid prefix $prefix")
private[this] var lastDenotation: Denotation = _
@@ -1049,21 +1051,60 @@ object Types {
if (owner.isTerm) d else d.asSeenFrom(prefix)
}
- private[dotc] final def withDenot(denot: Denotation): this.type = {
+ private def checkSymAssign(sym: Symbol) =
+ assert(
+ (lastSymbol eq sym) ||
+ (lastSymbol eq null) ||
+ (lastSymbol.defRunId != sym.defRunId) ||
+ (lastSymbol.defRunId == NoRunId),
+ s"data race? overwriting symbol of $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id}")
+
+ protected def sig: Signature = Signature.NotAMethod
+
+ private[dotc] def withDenot(denot: Denotation)(implicit ctx: Context): ThisType =
+ if (sig != denot.signature)
+ withSig(denot.signature).withDenot(denot).asInstanceOf[ThisType]
+ else {
+ setDenot(denot)
+ this
+ }
+
+ private[dotc] final def setDenot(denot: Denotation)(implicit ctx: Context): Unit = {
+ if (Config.checkNoDoubleBindings)
+ if (ctx.settings.YnoDoubleBindings.value)
+ checkSymAssign(denot.symbol)
lastDenotation = denot
lastSymbol = denot.symbol
- this
}
- private[dotc] final def withSym(sym: Symbol): this.type = {
+ private[dotc] def withSym(sym: Symbol, signature: Signature)(implicit ctx: Context): ThisType =
+ if (sig != signature)
+ withSig(signature).withSym(sym, signature).asInstanceOf[ThisType]
+ else {
+ setSym(sym)
+ this
+ }
+
+ private[dotc] final def setSym(sym: Symbol)(implicit ctx: Context): Unit = {
+ if (Config.checkNoDoubleBindings)
+ if (ctx.settings.YnoDoubleBindings.value)
+ checkSymAssign(sym)
+ uncheckedSetSym(sym)
+ }
+
+ private[dotc] final def uncheckedSetSym(sym: Symbol): Unit = {
lastDenotation = null
lastSymbol = sym
checkedPeriod = Nowhere
- this
}
+ private def withSig(sig: Signature)(implicit ctx: Context): NamedType =
+ 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
@@ -1124,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 &&
@@ -1136,6 +1182,9 @@ object Types {
abstract case class TermRef(override val prefix: Type, name: TermName) extends NamedType with SingletonType {
+ type ThisType = TermRef
+
+ //assert(name.toString != "<local Coder>")
override def underlying(implicit ctx: Context): Type = {
val d = denot
if (d.isOverloaded) NoType else d.info
@@ -1156,16 +1205,31 @@ object Types {
}
abstract case class TypeRef(override val prefix: Type, name: TypeName) extends NamedType {
+
+ type ThisType = TypeRef
+
override def underlying(implicit ctx: Context): Type = info
}
- final class TermRefWithSignature(prefix: Type, name: TermName, val sig: Signature) extends TermRef(prefix, name) {
+ final class TermRefWithSignature(prefix: Type, name: TermName, override val sig: Signature) extends TermRef(prefix, name) {
assert(prefix ne NoPrefix)
override def signature(implicit ctx: Context) = sig
- override def loadDenot(implicit ctx: Context): Denotation =
- super.loadDenot.atSignature(sig)
- override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef =
- TermRef.withSig(prefix, name, sig)
+ override def loadDenot(implicit ctx: Context): Denotation = {
+ val d = super.loadDenot
+ if (sig eq Signature.OverloadedSignature) d
+ else d.atSignature(sig)
+ }
+
+ override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef = {
+ if (sig != Signature.NotAMethod &&
+ sig != Signature.OverloadedSignature &&
+ symbol.exists) {
+ val ownSym = symbol
+ TermRef(prefix, name).withDenot(prefix.member(name).disambiguate(_ eq ownSym))
+ }
+ else TermRef.withSig(prefix, name, sig)
+ }
+
override def equals(that: Any) = that match {
case that: TermRefWithSignature =>
this.prefix == that.prefix &&
@@ -1177,15 +1241,25 @@ object Types {
override def computeHash = doHash((name, sig), prefix)
}
- trait WithNoPrefix extends NamedType {
+ trait WithNonMemberSym extends NamedType {
def fixedSym: Symbol
assert(fixedSym ne NoSymbol)
- withSym(fixedSym)
+ uncheckedSetSym(fixedSym)
+
+ override def withDenot(denot: Denotation)(implicit ctx: Context): ThisType = {
+ assert(denot.symbol eq fixedSym)
+ setDenot(denot)
+ this
+ }
+
+ override def withSym(sym: Symbol, signature: Signature)(implicit ctx: Context): ThisType =
+ unsupported("withSym")
+
override def equals(that: Any) = that match {
- case that: WithNoPrefix => this.fixedSym eq that.fixedSym
+ case that: WithNonMemberSym => this.prefix == that.prefix && (this.fixedSym eq that.fixedSym)
case _ => false
}
- override def computeHash = doHash(fixedSym)
+ override def computeHash = doHash(fixedSym, prefix)
}
final class CachedTermRef(prefix: Type, name: TermName, hc: Int) extends TermRef(prefix, name) {
@@ -1200,8 +1274,8 @@ object Types {
override def computeHash = unsupported("computeHash")
}
- final class NoPrefixTermRef(name: TermName, val fixedSym: TermSymbol) extends TermRef(NoPrefix, name) with WithNoPrefix
- final class NoPrefixTypeRef(name: TypeName, val fixedSym: TypeSymbol) extends TypeRef(NoPrefix, name) with WithNoPrefix
+ final class NonMemberTermRef(prefix: Type, name: TermName, val fixedSym: TermSymbol) extends TermRef(prefix, name) with WithNonMemberSym
+ final class NonMemberTypeRef(prefix: Type, name: TypeName, val fixedSym: TypeSymbol) extends TypeRef(prefix, name) with WithNonMemberSym
object NamedType {
def apply(prefix: Type, name: Name)(implicit ctx: Context) =
@@ -1210,20 +1284,42 @@ object Types {
def apply(prefix: Type, name: Name, denot: Denotation)(implicit ctx: Context) =
if (name.isTermName) TermRef(prefix, name.asTermName, denot)
else TypeRef(prefix, name.asTypeName, denot)
+ def withNonMemberSym(prefix: Type, sym: Symbol)(implicit ctx: Context) =
+ if (sym.isType) TypeRef.withNonMemberSym(prefix, sym.name.asTypeName, sym.asType)
+ else TermRef.withNonMemberSym(prefix, sym.name.asTermName, sym.asTerm)
}
object TermRef {
def apply(prefix: Type, name: TermName)(implicit ctx: Context): TermRef =
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TermRef]
+
def apply(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
withSymAndName(prefix, sym, sym.name)
+
+ def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef = {
+ if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm)
+ else denot match {
+ case denot: SymDenotation if denot.isCompleted => withSig(prefix, name, denot.signature)
+ case _ => apply(prefix, name)
+ }
+ } withDenot denot
+
+ def withNonMemberSym(prefix: Type, name: TermName, sym: TermSymbol)(implicit ctx: Context): TermRef =
+ unique(new NonMemberTermRef(prefix, name, sym))
+
def withSymAndName(prefix: Type, sym: TermSymbol, name: TermName)(implicit ctx: Context): TermRef =
- if (prefix eq NoPrefix) unique(new NoPrefixTermRef(name, sym))
- else apply(prefix, name) withSym sym
- def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef =
- (if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm) else apply(prefix, name)) withDenot denot
+ if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
+ else {
+ if (sym.defRunId != NoRunId && sym.isCompleted) withSig(prefix, name, sym.signature)
+ else apply(prefix, name)
+ } withSym (sym, Signature.NotAMethod)
+
+ def withSig(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
+ unique(withSig(prefix, sym.name, sym.signature).withSym(sym, sym.signature))
+
def withSig(prefix: Type, name: TermName, sig: Signature)(implicit ctx: Context): TermRef =
unique(new TermRefWithSignature(prefix, name, sig))
+
def withSig(prefix: Type, name: TermName, sig: Signature, denot: Denotation)(implicit ctx: Context): TermRef =
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm)
else withSig(prefix, name, sig)) withDenot denot
@@ -1232,11 +1328,17 @@ object Types {
object TypeRef {
def apply(prefix: Type, name: TypeName)(implicit ctx: Context): TypeRef =
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TypeRef]
+
def apply(prefix: Type, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
withSymAndName(prefix, sym, sym.name)
+
+ def withNonMemberSym(prefix: Type, name: TypeName, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
+ unique(new NonMemberTypeRef(prefix, name, sym))
+
def withSymAndName(prefix: Type, sym: TypeSymbol, name: TypeName)(implicit ctx: Context): TypeRef =
- if (prefix eq NoPrefix) unique(new NoPrefixTypeRef(name, sym))
- else apply(prefix, name) withSym sym
+ if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
+ else apply(prefix, name).withSym(sym, Signature.NotAMethod)
+
def apply(prefix: Type, name: TypeName, denot: Denotation)(implicit ctx: Context): TypeRef =
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asType) else apply(prefix, name)) withDenot denot
}
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 557a2b5db..f9cd9ec72 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -3,7 +3,7 @@ package printing
import core._
import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._
-import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation
+import Contexts.Context, Scopes.Scope, Denotations._, Annotations.Annotation
import StdNames.nme
import ast.{Trees, untpd}
import typer.Namer
@@ -475,7 +475,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
Text(flags.flagStrings.filterNot(_.startsWith("<")) map stringToText, " ")
}
- override def toText(denot: Denotation): Text = toText(denot.symbol)
+ override def toText(denot: Denotation): Text = denot match {
+ case denot: MultiDenotation => denot.toString
+ case _ =>
+ if (denot.symbol.exists) toText(denot.symbol)
+ else "some " ~ toText(denot.info)
+ }
override def plain = new PlainPrinter(_ctx)
}
diff --git a/src/dotty/tools/dotc/transform/Splitter.scala b/src/dotty/tools/dotc/transform/Splitter.scala
index 43a91a058..978a9cce4 100644
--- a/src/dotty/tools/dotc/transform/Splitter.scala
+++ b/src/dotty/tools/dotc/transform/Splitter.scala
@@ -3,10 +3,10 @@ package transform
import TreeTransforms._
import ast.Trees._
-import core.Contexts._
-import core.Types._
+import core._
+import Contexts._, Types._, Decorators._, Denotations._, Symbols._, SymDenotations._, Names._
-/** This transform makes usre every identifier and select node
+/** This transform makes sure every identifier and select node
* carries a symbol. To do this, certain qualifiers with a union type
* have to be "splitted" with a type test.
*
@@ -24,4 +24,104 @@ class Splitter extends TreeTransform {
This(cls) withPos tree.pos
case _ => tree
}
+
+ /** If we select a name, make sure the node has a symbol.
+ * If necessary, split the qualifier with type tests.
+ * Example: Assume:
+ *
+ * class A { def f(x: S): T }
+ * class B { def f(x: S): T }
+ * def p(): A | B
+ *
+ * Then p().f(a) translates to
+ *
+ * val ev$1 = p()
+ * if (ev$1.isInstanceOf[A]) ev$1.asInstanceOf[A].f(a)
+ * else ev$1.asInstanceOf[B].f(a)
+ */
+ override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = {
+ val Select(qual, name) = tree
+
+ def memberDenot(tp: Type): SingleDenotation = {
+ val mbr = tp.member(name)
+ if (!mbr.isOverloaded) mbr.asSingleDenotation
+ else tree.tpe match {
+ case tref: TermRefWithSignature => mbr.atSignature(tref.sig)
+ case _ => ctx.error(s"cannot disambiguate overloaded member $mbr"); NoDenotation
+ }
+ }
+
+ def candidates(tp: Type): List[Symbol] = {
+ val mbr = memberDenot(tp)
+ if (mbr.symbol.exists) mbr.symbol :: Nil
+ else tp.widen match {
+ case tref: TypeRef =>
+ tref.info match {
+ case TypeBounds(_, hi) => candidates(hi)
+ case _ => Nil
+ }
+ case OrType(tp1, tp2) =>
+ candidates(tp1) | candidates(tp2)
+ case AndType(tp1, tp2) =>
+ candidates(tp1) & candidates(tp2)
+ case tpw =>
+ Nil
+ }
+ }
+
+ def isStructuralSelect(tp: Type): Boolean = tp.stripTypeVar match {
+ case tp: RefinedType => tp.refinedName == name || isStructuralSelect(tp)
+ case tp: TypeProxy => isStructuralSelect(tp.underlying)
+ case AndType(tp1, tp2) => isStructuralSelect(tp1) || isStructuralSelect(tp2)
+ case _ => false
+ }
+
+ if (tree.symbol.exists) tree
+ else {
+ def choose(qual: Tree, syms: List[Symbol]): Tree = {
+ def testOrCast(which: Symbol, mbr: Symbol) =
+ TypeApply(Select(qual, which), TypeTree(mbr.owner.typeRef) :: Nil)
+ def select(sym: Symbol) = {
+ val qual1 =
+ if (qual.tpe derivesFrom sym.owner) qual
+ else testOrCast(defn.Any_asInstanceOf, sym)
+ Select(qual1, sym) withPos tree.pos
+ }
+ syms match {
+ case Nil =>
+ def msg =
+ if (isStructuralSelect(qual.tpe))
+ s"cannot access member '$name' from structural type ${qual.tpe.widen.show}; use Dynamic instead"
+ else
+ s"no candidate symbols for ${tree.tpe.show} found in ${qual.tpe.show}"
+ ctx.error(msg, tree.pos)
+ tree
+ case sym :: Nil =>
+ select(sym)
+ case sym :: syms1 =>
+ If(testOrCast(defn.Any_isInstanceOf, sym), select(sym), choose(qual, syms1))
+ }
+ }
+ evalOnce(qual)(qual => choose(qual, candidates(qual.tpe)))
+ }
+ }
+
+ /** Distribute arguments among splitted branches */
+ def distribute(tree: GenericApply[Type], rebuild: (Tree, List[Tree]) => Context => Tree)(implicit ctx: Context) = {
+ def recur(fn: Tree): Tree = fn match {
+ case Block(stats, expr) => Block(stats, recur(expr))
+ case If(cond, thenp, elsep) => If(cond, recur(thenp), recur(elsep))
+ case _ => rebuild(fn, tree.args)(ctx) withPos tree.pos
+ }
+ recur(tree.fun)
+ }
+
+ override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo) =
+ distribute(tree, typeApply)
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) =
+ distribute(tree, apply)
+
+ private val typeApply = (fn: Tree, args: List[Tree]) => (ctx: Context) => TypeApply(fn, args)(ctx)
+ private val apply = (fn: Tree, args: List[Tree]) => (ctx: Context) => Apply(fn, args)(ctx)
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index 5913875b8..f52c5bc1c 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -12,8 +12,10 @@ import core.Constants._
import core.StdNames._
import core.Decorators._
import core.transform.Erasure.isUnboundedGeneric
+import typer._
import typer.ErrorReporting._
import ast.Trees._
+import ast.{tpd, untpd}
/** This transform eliminates patterns. Right now it's a dummy.
* Awaiting the real pattern matcher.
@@ -23,14 +25,37 @@ class TreeChecker {
def check(ctx: Context) = {
println(s"checking ${ctx.compilationUnit} after phase ${ctx.phase.prev}")
- Checker.transform(ctx.compilationUnit.tpdTree)(ctx)
+ Checker.typedExpr(ctx.compilationUnit.tpdTree)(ctx)
}
- object Checker extends TreeMap {
- override def transform(tree: Tree)(implicit ctx: Context) = {
- println(i"checking $tree")
- assert(tree.isEmpty || tree.hasType, tree.show)
- super.transform(tree)
+ object Checker extends ReTyper {
+ override def typed(tree: untpd.Tree, pt: Type)(implicit ctx: Context) =
+ if (tree.isEmpty) tree.asInstanceOf[Tree]
+ else {
+ assert(tree.hasType, tree.show)
+ val tree1 = super.typed(tree, pt)
+ def sameType(tp1: Type, tp2: Type) =
+ (tp1 eq tp2) || // accept NoType / NoType
+ (tp1 =:= tp2)
+ def divergenceMsg =
+ s"""Types differ
+ |Original type : ${tree.typeOpt.show}
+ |After checking: ${tree1.tpe.show}
+ |Original tree : ${tree.show}
+ |After checking: ${tree1.show}
+ """.stripMargin
+ assert(sameType(tree1.tpe, tree.typeOpt), divergenceMsg)
+ tree1
+ }
+
+ override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = {
+ assert(tree.isTerm, tree.show)
+ super.typedIdent(tree, pt)
+ }
+
+ override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = {
+ assert(tree.isTerm, tree.show)
+ super.typedSelect(tree, pt)
}
}
}
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 57f11480c..0f47336fc 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -794,8 +794,8 @@ trait Applications extends Compatibility { self: Typer =>
tp
}
- val owner1 = alt1.symbol.owner
- val owner2 = alt2.symbol.owner
+ val owner1 = if (alt1.symbol.exists) alt1.symbol.owner else NoSymbol
+ val owner2 = if (alt2.symbol.exists) alt2.symbol.owner else NoSymbol
val tp1 = stripImplicit(alt1.widen)
val tp2 = stripImplicit(alt2.widen)
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 287e93c7a..ae325af2a 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -102,13 +102,14 @@ trait Checking {
tp
}
- /** Check that class does not define */
+ /** Check that class does not define same symbol twice */
def checkNoDoubleDefs(cls: Symbol)(implicit ctx: Context): Unit = {
val seen = new mutable.HashMap[Name, List[Symbol]] {
override def default(key: Name) = Nil
}
typr.println(i"check no double defs $cls")
- for (decl <- cls.info.decls) {
+
+ def checkDecl(decl: Symbol): Unit = {
for (other <- seen(decl.name)) {
typr.println(i"conflict? $decl $other")
if (decl.signature matches other.signature) {
@@ -129,6 +130,12 @@ trait Checking {
}
seen(decl.name) = decl :: seen(decl.name)
}
+
+ cls.info.decls.foreach(checkDecl)
+ cls.info match {
+ case ClassInfo(_, _, _, _, selfSym: Symbol) => checkDecl(selfSym)
+ case _ =>
+ }
}
def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 2425bea50..2d4bf8099 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -209,7 +209,7 @@ class Namer { typer: Typer =>
ctx.error(s"${preExisting.showLocated} is compiled twice, runid = ${ctx.runId}", tree.pos)
}
else if ((!ctx.owner.isClass || name.isTypeName) && preExisting.exists) {
- ctx.error(d"$name is already defined as $preExisting")
+ ctx.error(i"$name is already defined as $preExisting", tree.pos)
}
}
@@ -474,7 +474,6 @@ class Namer { typer: Typer =>
index(rest)(inClassContext(selfInfo))
denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
- // make sure constr parameters are all entered because we refer to them in desugarings:
}
}
diff --git a/src/dotty/tools/dotc/typer/ReTyper.scala b/src/dotty/tools/dotc/typer/ReTyper.scala
index 896dbba7d..c2f627b1e 100644
--- a/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -3,7 +3,7 @@ package typer
import core.Contexts._
import core.Types._
-import core.Symbols.Symbol
+import core.Symbols._
import typer.ProtoTypes._
import ast.{tpd, untpd}
import ast.Trees._
@@ -48,6 +48,8 @@ class ReTyper extends Typer {
untpd.cpy.Bind(tree, tree.name, body1).withType(tree.typeOpt)
}
+ override def localDummy(cls: ClassSymbol, impl: untpd.Template)(implicit ctx: Context) = impl.symbol
+
override def retrieveSym(tree: untpd.Tree)(implicit ctx: Context): Symbol = tree.symbol
override def localTyper(sym: Symbol) = this
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 5821b58b2..12f2415d8 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -109,7 +109,8 @@ trait TypeAssigner {
// it could be that we found an inaccessbile private member, but there is
// 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)
+ if (reallyExists(d2) && firstTry)
+ test(tpe.shadowed.withDenot(d2), false)
else {
val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists)
val what = alts match {
@@ -325,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))
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 60acda4b7..6e613975b 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -809,11 +809,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val parents1 = ensureConstrCall(ensureFirstIsClass(
parents mapconserve typedParent, cdef.pos.toSynthetic))
val self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class memebers are not visible
- val localDummy = ctx.newLocalDummy(cls, impl.pos)
- val body1 = typedStats(body, localDummy)(inClassContext(self1.symbol))
+ val dummy = localDummy(cls, impl)
+ val body1 = typedStats(body, dummy)(inClassContext(self1.symbol))
checkNoDoubleDefs(cls)
val impl1 = cpy.Template(impl, constr1, parents1, self1, body1)
- .withType(localDummy.termRef)
+ .withType(dummy.termRef)
assignType(cpy.TypeDef(cdef, mods1, name, impl1), cls)
// todo later: check that
@@ -825,6 +825,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
// 4. Polymorphic type defs override nothing.
}
+ def localDummy(cls: ClassSymbol, impl: untpd.Template)(implicit ctx: Context): Symbol =
+ ctx.newLocalDummy(cls, impl.pos)
+
def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = track("typedImport") {
val expr1 = typedExpr(imp.expr, AnySelectionProto)
checkStable(expr1.tpe, imp.expr.pos)
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index dcd5c67c8..3228c3474 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -14,7 +14,7 @@ class tests extends CompilerTest {
// "-Yshow-suppressed-errors",
"-pagewidth", "160"
)
- val twice = List("#runs", "2")
+ val twice = List("#runs", "2", "-YnoDoubleBindings")
val doErase = List("-Ystop-before:terminal")
val posDir = "./tests/pos/"
@@ -55,7 +55,7 @@ class tests extends CompilerTest {
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
@Test def neg_typedidents() = compileFile(negDir, "typedIdents", xerrors = 2)
@Test def neg_assignments() = compileFile(negDir, "assignments", xerrors = 3)
- @Test def neg_typers() = compileFile(negDir, "typers", xerrors = 10)
+ @Test def neg_typers() = compileFile(negDir, "typers", xerrors = 13)
@Test def neg_privates() = compileFile(negDir, "privates", xerrors = 2)
@Test def neg_rootImports = compileFile(negDir, "rootImplicits", xerrors = 2)
@Test def neg_templateParents() = compileFile(negDir, "templateParents", xerrors = 3)
@@ -65,6 +65,8 @@ class tests extends CompilerTest {
@Test def neg_i39 = compileFile(negDir, "i39", xerrors = 1)
@Test def neg_i50_volatile = compileFile(negDir, "i50-volatile", xerrors = 4)
@Test def neg_t0273_doubledefs = compileFile(negDir, "t0273", xerrors = 1)
+ @Test def neg_t0586_structural = compileFile(negDir, "t0586", xerrors = 1)
+ @Test def neg_t0625_structural = compileFile(negDir, "t0625", xerrors = 1)
@Test def neg_t0654_polyalias = compileFile(negDir, "t0654", xerrors = 2)
@Test def neg_t1192_legalPrefix = compileFile(negDir, "t1192", xerrors = 1)
diff --git a/tests/pos/t0586.scala b/tests/neg/t0586.scala
index 540e225a1..540e225a1 100644
--- a/tests/pos/t0586.scala
+++ b/tests/neg/t0586.scala
diff --git a/tests/pos/t0625.scala b/tests/neg/t0625.scala
index 561454259..561454259 100644
--- a/tests/pos/t0625.scala
+++ b/tests/neg/t0625.scala
diff --git a/tests/neg/typers.scala b/tests/neg/typers.scala
index d25a8911e..2f1cf40c4 100644
--- a/tests/neg/typers.scala
+++ b/tests/neg/typers.scala
@@ -1,40 +1,56 @@
object typers {
-
+
+ class A(x: Int) {
+ val x: String = "a" // error: double def
+
+ { val y: String = ""
+ val y: Int = 0 // error: double def
+ y
+ }
+ }
+
+ class B { self => // error: double def
+ def self: Int = 0
+ def self(x: Int): Int = x
+ }
+
class C {
val x: Int
- val x: String
+ val x: String // error: double def
val y: Int
- def y: String
+ def y: String // error: double def
val z: Int
- def z(): String
-
- def f(x: Any) = ()
+ def z(): String // error: double def
+
+ def f(x: Any) = () // error: double def
def f(x: AnyRef): AnyRef
-
+
def g(x: Object): Unit
- def g[T](x: T): T = x
+ def g[T](x: T): T = x // error: double def
}
-
-
+
+
+
+
object returns {
-
- def foo(x: Int) = {
+
+ def foo(x: Int) = { // error: has return; needs result type
return 3
}
-
- return 4
+
+ return 4 // error: return outside method definition
}
-
+
object cyclic {
- def factorial(acc: Int, n: Int) =
+ def factorial(acc: Int, n: Int) =
if (n == 0) acc
- else factorial(acc * n, n - 1)
-
- def foo(x: Int) = x
+ else factorial(acc * n, n - 1) // error: cyclic reference
+
+ def foo(x: Int) = x // error: cyclic reference
def foo() = foo(1)
-
+
}
-
+
object tries {
val x = try {
@@ -46,6 +62,6 @@ object typers {
}
class Refinements {
- val y: C { val x: T; type T }
+ val y: C { val x: T; type T } // error: illegal forward reference in refinement
}
-} \ No newline at end of file
+}
diff --git a/tests/pos/alias.scala b/tests/pos/alias.scala
new file mode 100644
index 000000000..a66edc73a
--- /dev/null
+++ b/tests/pos/alias.scala
@@ -0,0 +1,3 @@
+class A(val x: Int)
+
+class B(x: Int) extends A(x)
diff --git a/tests/pos/typers.scala b/tests/pos/typers.scala
index cb3bbc590..4f012e7bf 100644
--- a/tests/pos/typers.scala
+++ b/tests/pos/typers.scala
@@ -1,61 +1,61 @@
-package test
+package test
import annotation.{tailrec, switch}
import collection.mutable._
object typers {
-
+
val names = List("a", "b", "c")
val ints = List(1, 2, 3)
-
+
object Inference {
for ((name, n) <- (names, ints).zipped)
println(name.length + n)
-
+
def double(x: Char): String = s"$x$x"
-
+
"abc" flatMap double
-
+
}
object Eta {
-
+
def fun(x: Int): Int = x + 1
val foo = fun(_)
}
-
+
case class DefaultParams(init: String => String = identity)
object DefaultParams {
def foo(x: String => String = identity) = x("abc")
-
+
foo()
}
-
+
class List[+T] {
def :: (x: T) = new :: (x, this)
-
+
def len: Int = this match {
case x :: xs1 => 1 + xs1.len
case Nil => 0
}
}
-
+
object Nil extends List[Nothing]
-
+
case class :: [+T] (hd: T, tl: List[T]) extends List[T]
-
+
def len[U](xs: List[U]): Int = xs match {
case x :: xs1 => 1 + len(xs1)
case Nil => 0
}
-
+
object returns {
-
+
def foo(x: Int): Int = {
return 3
}
}
-
+
object tries {
val x = try {
@@ -70,69 +70,71 @@ object typers {
val y = try 2 catch Predef.identity
val z = try 3 finally "abc"
-
+
println("abc".toString)
}
class C {
-
+
@tailrec def factorial(acc: Int, n: Int): Int = (n: @switch) match {
case 0 => acc
case _ => factorial(acc * n, n - 1)
}
-
+
println(factorial(1, 10))
-
-
+
+
}
-
+
class Refinements {
val y: C { type T; val key: T; def process(x: T): Int }
}
-
+
object Accessibility {
-
+
class A {
val x: String = "abc"
}
-
+
class B extends A {
private def x: Int = 1
}
-
+
val b: B = new B
val y = b.x
val z: String = y
-
+
}
-
+
object Self {
-
- class A(self: Int) { self =>
-
+
+ class A(self1: Int) { self =>
+
+ def self1(x: Int) = x
+
class B {
val b = self
val c: A = b
}
-
+
val a = self
val c: A = a
}
-
-
+
+
}
-
+
object Arrays {
-
+
val arr = List("a", "b", "c").toArray
val i = 2
arr(i).charAt(0)
-
+
val x = new ArrayBuffer[String] // testing overloaded polymorphic constructors
val entries = Array("abc", "def")
-
+
for ((x, i) <- entries.zipWithIndex)
println(x)
}
@@ -145,6 +147,6 @@ object typers {
}
val yy: String = y
}
-
-} \ No newline at end of file
+
+}
diff --git a/tests/pos/unions.scala b/tests/pos/unions.scala
index 779d1847e..e57a96fb9 100644
--- a/tests/pos/unions.scala
+++ b/tests/pos/unions.scala
@@ -2,13 +2,31 @@ object unions {
class A {
def f: String = "abc"
+
+ def g(x: Int): Int = x
+ def g(x: Double): Double = x
}
class B {
def f: String = "bcd"
+
+ def g(x: Int) = -x
+ def g(x: Double): Double = -x
}
val x: A | B = if (true) new A else new B
+ def y: B | A = if (true) new A else new B
println(x.f)
+ println(x.g(2))
+ println(y.f)
+ println(y.g(1.0))
+
+ class C {
+ private def foo = 0
+ class D extends C {
+ private def foo = 1
+ def test(cd: C | D, dc: D | C) = (cd.foo, dc.foo)
+ }
+ }
}