aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala5
-rw-r--r--src/dotty/tools/dotc/core/Types.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala12
-rw-r--r--src/dotty/tools/dotc/repl/InterpreterLoop.scala3
-rw-r--r--src/dotty/tools/dotc/repl/ManifestInfo.scala20
-rw-r--r--src/dotty/tools/dotc/reporting/diagnostic/Message.scala5
-rw-r--r--src/dotty/tools/dotc/reporting/diagnostic/messages.scala112
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitOuter.scala20
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala11
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala11
10 files changed, 168 insertions, 33 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index db2ce5649..fc96735b0 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -306,8 +306,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
case _ =>
false
}
- typeIsElidable ||
- tp.symbol.is(JavaStatic) ||
+ typeIsElidable ||
+ tp.symbol.is(JavaStatic) ||
tp.symbol.hasAnnotation(defn.ScalaStaticAnnot)
}
@@ -343,6 +343,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def singleton(tp: Type)(implicit ctx: Context): Tree = tp match {
case tp: TermRef => ref(tp)
case tp: ThisType => This(tp.cls)
+ case tp: SkolemType => singleton(tp.narrow)
case SuperType(qual, _) => singleton(qual)
case ConstantType(value) => Literal(value)
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index ce308412b..ae248295c 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -73,6 +73,8 @@ object Types {
* +- NoPrefix
* +- ErrorType
* +- WildcardType
+ *
+ * Note: please keep in sync with copy in `docs/docs/internals/type-system.md`.
*/
abstract class Type extends DotClass with Hashable with printing.Showable {
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index f442c13b3..aade359f8 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -151,7 +151,7 @@ object Parsers {
/* ------------- ERROR HANDLING ------------------------------------------- */
/** The offset of the last time when a statement on a new line was definitely
- * encountered in the current scope or an outer scope\
+ * encountered in the current scope or an outer scope.
*/
private var lastStatOffset = -1
@@ -505,7 +505,7 @@ object Parsers {
if (t1 ne t) t1 else dotSelectors(selector(t), finish)
}
- /** Dotelectors ::= { `.' ident()
+ /** DotSelectors ::= { `.' ident()
*
* Accept `.' separated identifiers acting as a selectors on given tree `t`.
* @param finish An alternative parse in case the token following a `.' is not an identifier.
@@ -521,7 +521,7 @@ object Parsers {
* | [Ident `.'] this
*
* @param thisOK If true, [Ident `.'] this is acceptable as the path.
- * If false, another selection is required aftre the `this`.
+ * If false, another selection is required after the `this`.
* @param finish An alternative parse in case the token following a `.' is not an identifier.
* If the alternative does not apply, its tree argument is returned unchanged.
*/
@@ -1076,7 +1076,7 @@ object Parsers {
val uscoreStart = in.skipToken()
if (isIdent(nme.raw.STAR)) {
in.nextToken()
- if (in.token != RPAREN) syntaxError("`_*' can be used only for last argument", uscoreStart)
+ if (in.token != RPAREN) syntaxError(SeqWildcardPatternPos(), uscoreStart)
Typed(t, atPos(uscoreStart) { Ident(tpnme.WILDCARD_STAR) })
} else {
syntaxErrorOrIncomplete(IncorrectRepeatedParameterSyntax())
@@ -1424,7 +1424,7 @@ object Parsers {
// `x: _*' is parsed in `ascription'
if (isIdent(nme.raw.STAR)) {
in.nextToken()
- if (in.token != RPAREN) syntaxError("`_*' can be used only for last argument", wildIndent.pos)
+ if (in.token != RPAREN) syntaxError(SeqWildcardPatternPos(), wildIndent.pos)
atPos(wildIndent.pos) { Ident(tpnme.WILDCARD_STAR) }
} else wildIndent
case LPAREN =>
@@ -1436,7 +1436,7 @@ object Parsers {
case _ =>
if (isLiteral) literal()
else {
- syntaxErrorOrIncomplete("illegal start of simple pattern")
+ syntaxErrorOrIncomplete(IllegalStartOfSimplePattern())
errorTermTree
}
}
diff --git a/src/dotty/tools/dotc/repl/InterpreterLoop.scala b/src/dotty/tools/dotc/repl/InterpreterLoop.scala
index 8b1000f2e..b3ac41c55 100644
--- a/src/dotty/tools/dotc/repl/InterpreterLoop.scala
+++ b/src/dotty/tools/dotc/repl/InterpreterLoop.scala
@@ -66,7 +66,8 @@ class InterpreterLoop(compiler: Compiler, config: REPL.Config)(implicit ctx: Con
output.flush()
}
- val version = ".next (pre-alpha)"
+ val gitHash = ManifestInfo.attributes.getOrElse("Git-Hash", "unknown")
+ val version = s".next (pre-alpha, git-hash: $gitHash)"
/** The main read-eval-print loop for the interpreter. It calls
* `command()` for each line of input.
diff --git a/src/dotty/tools/dotc/repl/ManifestInfo.scala b/src/dotty/tools/dotc/repl/ManifestInfo.scala
new file mode 100644
index 000000000..206dccd67
--- /dev/null
+++ b/src/dotty/tools/dotc/repl/ManifestInfo.scala
@@ -0,0 +1,20 @@
+package dotty.tools.dotc.repl
+
+import java.net.JarURLConnection
+import scala.collection.JavaConversions._
+
+object ManifestInfo {
+
+ val attributes: Map[String, String] = {
+ for {
+ resourceUrl <- Option(getClass.getResource(getClass.getSimpleName + ".class"))
+ urlConnection = resourceUrl.openConnection() if urlConnection.isInstanceOf[JarURLConnection]
+ manifest <- Option(urlConnection.asInstanceOf[JarURLConnection].getManifest)
+ } yield {
+ manifest.getMainAttributes.foldLeft(Map[String, String]())(
+ (map, attribute) => map + (attribute._1.toString -> attribute._2.toString)
+ )
+ }
+ }.getOrElse(Map())
+
+}
diff --git a/src/dotty/tools/dotc/reporting/diagnostic/Message.scala b/src/dotty/tools/dotc/reporting/diagnostic/Message.scala
index 8b1f65673..8b607c18c 100644
--- a/src/dotty/tools/dotc/reporting/diagnostic/Message.scala
+++ b/src/dotty/tools/dotc/reporting/diagnostic/Message.scala
@@ -18,7 +18,8 @@ object Message {
/** A `Message` contains all semantic information necessary to easily
* comprehend what caused the message to be logged. Each message can be turned
* into a `MessageContainer` which contains the log level and can later be
- * consumed by a subclass of `Reporter`.
+ * consumed by a subclass of `Reporter`. However, the error position is only
+ * part of `MessageContainer`, not `Message`.
*
* @param errorId a unique number identifying the message, this will later be
* used to reference documentation online
@@ -31,7 +32,7 @@ abstract class Message(val errorId: Int) { self =>
* > expected: String
* > found: Int
*
- * This message wil be placed underneath the position given by the enclosing
+ * This message will be placed underneath the position given by the enclosing
* `MessageContainer`
*/
def msg: String
diff --git a/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index 649f2a8f8..5e6a402ef 100644
--- a/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -184,7 +184,7 @@ object messages {
val caseDef = s"case $pat$guard => $body"
- hl"""|For each ${"case"} bound variable names have to be unique. In:
+ hl"""|For each ${"case"} bound variable names have to be unique. In:
|
|$caseDef
|
@@ -194,12 +194,14 @@ object messages {
case class MissingIdent(tree: untpd.Ident, treeKind: String, name: String)(implicit ctx: Context)
extends Message(6) {
- val kind = "Missing Identifier"
+ val kind = "Unbound Identifier"
val msg = em"not found: $treeKind$name"
val explanation = {
- hl"""|An identifier for `$treeKind$name` is missing. This means that something
- |has either been misspelt or you're forgetting an import"""
+ hl"""|The identifier for `$treeKind$name` is not bound, that is,
+ |no declaration for this identifier can be found.
+ |That can happen for instance if $name or its declaration has either been
+ |misspelt, or if you're forgetting an import"""
}
}
@@ -787,4 +789,106 @@ object messages {
val msg = "unreachable code"
val explanation = ""
}
+
+ case class SeqWildcardPatternPos()(implicit ctx: Context) extends Message(31) {
+ val kind = "Syntax"
+ val msg = "`_*' can be used only for last argument"
+ val explanation = {
+ val code =
+ """def sumOfTheFirstTwo(list: List[Int]): Int = list match {
+ | case List(first, second, x:_*) => first + second
+ | case _ => 0
+ |}"""
+ hl"""|Sequence wildcard pattern is expected at the end of an argument list.
+ |This pattern matches any remaining elements in a sequence.
+ |Consider the following example:
+ |
+ |$code
+ |
+ |Calling:
+ |
+ |${"sumOfTheFirstTwo(List(1, 2, 10))"}
+ |
+ |would give 3 as a result"""
+ }
+ }
+
+ case class IllegalStartOfSimplePattern()(implicit ctx: Context) extends Message(32) {
+ val kind = "Syntax"
+ val msg = "illegal start of simple pattern"
+ val explanation = {
+ val sipCode =
+ """def f(x: Int, y: Int) = x match {
+ | case `y` => ...
+ |}
+ """
+ val constructorPatternsCode =
+ """case class Person(name: String, age: Int)
+ |
+ |def test(p: Person) = p match {
+ | case Person(name, age) => ...
+ |}
+ """
+ val tupplePatternsCode =
+ """def swap(tuple: (String, Int)): (Int, String) = tuple match {
+ | case (text, number) => (number, text)
+ |}
+ """
+ val patternSequencesCode =
+ """def getSecondValue(list: List[Int]): Int = list match {
+ | case List(_, second, x:_*) => second
+ | case _ => 0
+ |}"""
+ hl"""|Simple patterns can be divided into several groups:
+ |- Variable Patterns: ${"case x => ..."}.
+ | It matches any value, and binds the variable name to that value.
+ | A special case is the wild-card pattern _ which is treated as if it was a fresh
+ | variable on each occurrence.
+ |
+ |- Typed Patterns: ${"case x: Int => ..."} or ${"case _: Int => ..."}.
+ | This pattern matches any value matched by the specified type; it binds the variable
+ | name to that value.
+ |
+ |- Literal Patterns: ${"case 123 => ..."} or ${"case 'A' => ..."}.
+ | This type of pattern matches any value that is equal to the specified literal.
+ |
+ |- Stable Identifier Patterns:
+ |
+ | $sipCode
+ |
+ | the match succeeds only if the x argument and the y argument of f are equal.
+ |
+ |- Constructor Patterns:
+ |
+ | $constructorPatternsCode
+ |
+ | The pattern binds all object's fields to the variable names (name and age, in this
+ | case).
+ |
+ |- Tuple Patterns:
+ |
+ | $tupplePatternsCode
+ |
+ | Calling:
+ |
+ | ${"""swap(("Luftballons", 99)"""}
+ |
+ | would give ${"""(99, "Luftballons")"""} as a result.
+ |
+ |- Pattern Sequences:
+ |
+ | $patternSequencesCode
+ |
+ | Calling:
+ |
+ | ${"getSecondValue(List(1, 10, 2))"}
+ |
+ | would give 10 as a result.
+ | This pattern is possible because a companion object for the List class has a method
+ | with the following signature:
+ |
+ | ${"def unapplySeq[A](x: List[A]): Some[List[A]]"}
+ |"""
+ }
+ }
}
diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index 3f235dca7..3fec47e9f 100644
--- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -226,14 +226,18 @@ object ExplicitOuter {
case ref: TermRef =>
if (ref.prefix ne NoPrefix)
!ref.symbol.isStatic && isOuterRef(ref.prefix)
- else if (ref.symbol is Hoistable)
- // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
- // an outer path then.
- isOuterSym(ref.symbol.owner.enclosingClass)
- else
- // ref.symbol will get a proxy in immediately enclosing class. If this properly
- // contains the current class, it needs an outer path.
- ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
+ else (
+ (ref.symbol is Hoistable) &&
+ // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
+ // an outer path then.
+ isOuterSym(ref.symbol.owner.enclosingClass)
+ ||
+ // If not hoistable, ref.symbol will get a proxy in immediately enclosing class. If this properly
+ // contains the current class, it needs an outer path.
+ // If the symbol is hoistable, it might have free variables for which the same
+ // reasoning applies. See pos/i1664.scala
+ ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
+ )
case _ => false
}
def hasOuterPrefix(tp: Type) = tp match {
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index dd7326fae..687de1e7a 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -656,6 +656,8 @@ class Namer { typer: Typer =>
* (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix)
* (2) If may not derive from itself
* (3) Overriding type parameters must be correctly forwarded. (@see checkTypeParamOverride)
+ * (4) The class is not final
+ * (5) If the class is sealed, it is defined in the same compilation unit as the current class
*/
def checkedParentType(parent: untpd.Tree, paramAccessors: List[Symbol]): Type = {
val ptype = parentType(parent)(ctx.superCallContext)
@@ -674,7 +676,14 @@ class Namer { typer: Typer =>
}
else if (!paramAccessors.forall(checkTypeParamOverride(pt, _)))
defn.ObjectType
- else pt
+ else {
+ val pclazz = pt.typeSymbol
+ if (pclazz.is(Final))
+ ctx.error(em"cannot extend final $pclazz", cls.pos)
+ if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile)
+ ctx.error(em"cannot extend sealed $pclazz in different compilation unit", cls.pos)
+ pt
+ }
}
}
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index 026015d1d..46bdbf3b3 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -72,8 +72,7 @@ object RefChecks {
}
}
- /** Check that final and sealed restrictions on class parents
- * and that self type of this class conforms to self types of parents.
+ /** Check that self type of this class conforms to self types of parents.
* and required classes.
*/
private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match {
@@ -83,14 +82,8 @@ object RefChecks {
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
ctx.error(ex"$category: self type ${cinfo.selfType} of $cls does not conform to self type $otherSelf of $relation ${other.classSymbol}", cls.pos)
}
- for (parent <- cinfo.classParents) {
- val pclazz = parent.classSymbol
- if (pclazz.is(Final))
- ctx.error(em"cannot extend final $pclazz", cls.pos)
- if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile)
- ctx.error(em"cannot extend sealed $pclazz in different compilation unit", cls.pos)
+ for (parent <- cinfo.classParents)
checkSelfConforms(parent, "illegal inheritance", "parent")
- }
for (reqd <- cinfo.givenSelfType.classSymbols)
checkSelfConforms(reqd.typeRef, "missing requirement", "required")
case _ =>