summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-02-07 18:30:46 +0000
committerMartin Odersky <odersky@gmail.com>2007-02-07 18:30:46 +0000
commit67cf4f5e32bc036788ff7a5426a5f5c0bb07fb70 (patch)
treede57c9ef5cba16ea71ded0c3c20118ae74006873 /src
parent9be1288dec994c96ab4619b7e3ffb096664ba01a (diff)
downloadscala-67cf4f5e32bc036788ff7a5426a5f5c0bb07fb70.tar.gz
scala-67cf4f5e32bc036788ff7a5426a5f5c0bb07fb70.tar.bz2
scala-67cf4f5e32bc036788ff7a5426a5f5c0bb07fb70.zip
changed non-exhaustivity to attributes
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala11
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala13
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala42
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala37
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala13
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/models/Models.scala2
-rw-r--r--src/compiler/scala/tools/nsc/models/SemanticTokens.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala27
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala58
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala79
-rwxr-xr-xsrc/library/scala/unsealed.scala18
21 files changed, 240 insertions, 97 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 108d68d9b7..2d64666980 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -363,7 +363,6 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
uncurry,
tailCalls,
explicitOuter,
- //transMatcher,
// checkDefined,
erasure,
lambdaLift,
@@ -513,7 +512,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
if (sym.isTerm) sym.moduleClass.reset(loaders.moduleClassLoader)
}
} else {
- assert(symData.isEmpty || !settings.stop.value.isEmpty || !settings.skip.value.isEmpty)
+ assert(symData.isEmpty || !settings.stop.value.isEmpty || !settings.skip.value.isEmpty, symData)
if (deprecationWarnings) {
warning("there were deprecation warnings; re-run with -deprecation for details")
}
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index b0e3fa4838..830194c5c1 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -305,7 +305,7 @@ abstract class TreeBrowsers {
case Bind(name, rhs) =>
Pair("Bind", name)
- case Match(selector, cases, _) =>
+ case Match(selector, cases) =>
Pair("Visitor", EMPTY)
case Function(vparams, body) =>
@@ -353,6 +353,9 @@ abstract class TreeBrowsers {
case TypeTree() =>
Pair("TypeTree", EMPTY)
+ case Attributed(constr, elements, arg) =>
+ Pair("AttributedTypeTree", EMPTY)
+
case AttributedTypeTree(attribs, tpt) =>
Pair("AttributedTypeTree", EMPTY)
@@ -449,7 +452,7 @@ abstract class TreeBrowsers {
case Bind(name, rhs) =>
List(rhs)
- case Match(selector, cases, _) =>
+ case Match(selector, cases) =>
selector :: cases
case Function(vparams, body) =>
@@ -497,8 +500,8 @@ abstract class TreeBrowsers {
case TypeTree() =>
Nil
- case AttributedTypeTree(attribs, tpt) =>
- attribs ::: List(tpt)
+ case Attributed(constr, elements, arg) =>
+ constr :: elements ::: List(arg)
case SingletonTypeTree(ref) =>
List(ref)
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 0ce8c00bf3..e0bce93ea8 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -191,8 +191,8 @@ abstract class TreePrinters {
case Block(stats, expr) =>
printColumn(stats ::: List(expr), "{", ";", "}")
- case Match(selector, cases, check) =>
- print(selector); printColumn(cases, if (check) " match {" else "match! {", "", "}")
+ case Match(selector, cases) =>
+ print(selector); printColumn(cases, " match {", "", "}")
case CaseDef(pat, guard, body) =>
print("case "); print(pat); printOpt(" if ", guard)
@@ -294,6 +294,15 @@ abstract class TreePrinters {
print(" ")
print(tree)
+ case Attributed(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), elements, tree) =>
+ print("@"); print(tpt)
+ if (!args.isEmpty)
+ printRow(args, "(", ",", ")")
+ if (!elements.isEmpty)
+ print((for (val Assign(name, value) <- elements) yield "val " + name + " = " + value).
+ mkString("{", ",", "}"))
+ print(" "); print(tree)
+
case SingletonTypeTree(ref) =>
print(ref); print(".type")
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index b575e2e1f6..25cfaf6cf4 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -537,7 +537,7 @@ trait Trees requires Global {
* <code>Ident(nme.WILDCARD)</code></li>
* </ul>
*/
- case class Match(selector: Tree, cases: List[CaseDef], checkExhaustive: boolean)
+ case class Match(selector: Tree, cases: List[CaseDef])
extends TermTree
/** Return expression */
@@ -658,6 +658,11 @@ trait Trees requires Global {
def TypeTree(tp: Type): TypeTree = TypeTree() setType tp
// def TypeTree(tp: Type, tree : Tree): TypeTree = TypeTree(tree) setType tp
+ /** A tree that has anP attribute attached to it */
+ case class Attributed(constr: Tree, elements: List[Tree], arg: Tree) extends Tree {
+ override def isType = arg.isType
+ }
+
/** A type tree that has attributes attached to it */
case class AttributedTypeTree(attribs: List[Tree], tpt: Tree)
extends TypTree {
@@ -712,7 +717,7 @@ trait Trees requires Global {
case Function(vparams, body) => (eliminated by lambdaLift)
case Assign(lhs, rhs) =>
case If(cond, thenp, elsep) =>
- case Match(selector, cases, check) =>
+ case Match(selector, cases) =>
case Return(expr) =>
case Try(block, catches, finalizer) =>
case Throw(expr) =>
@@ -726,6 +731,7 @@ trait Trees requires Global {
case Ident(name) =>
case Literal(value) =>
case TypeTree() => (introduced by refcheck)
+ case Attributed(constr, elements, arg) => (eliminated by typer)
case AttributedTypeTree(attribs, tpt) => (eliminated by uncurry)
case SingletonTypeTree(ref) => (eliminated by uncurry)
case SelectFromTypeTree(qualifier, selector) => (eliminated by uncurry)
@@ -758,7 +764,7 @@ trait Trees requires Global {
def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function
def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign
def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If
- def Match(tree: Tree, selector: Tree, cases: List[CaseDef], check: boolean): Match
+ def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match
def Return(tree: Tree, expr: Tree): Return
def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
def Throw(tree: Tree, expr: Tree): Throw
@@ -772,6 +778,7 @@ trait Trees requires Global {
def Ident(tree: Tree, name: Name): Ident
def Literal(tree: Tree, value: Constant): Literal
def TypeTree(tree: Tree): TypeTree
+ def Attributed(tree: Tree, constr: Tree, elements: List[Tree], arg: Tree): Attributed
def AttributedTypeTree(tree: Tree, attribs: List[Tree], tpt: Tree): AttributedTypeTree
def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree
def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree
@@ -827,8 +834,8 @@ trait Trees requires Global {
new Assign(lhs, rhs).copyAttrs(tree)
def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) =
new If(cond, thenp, elsep).copyAttrs(tree)
- def Match(tree: Tree, selector: Tree, cases: List[CaseDef], check: boolean) =
- new Match(selector, cases, check).copyAttrs(tree)
+ def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) =
+ new Match(selector, cases).copyAttrs(tree)
def Return(tree: Tree, expr: Tree) =
new Return(expr).copyAttrs(tree)
def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree) =
@@ -855,6 +862,8 @@ trait Trees requires Global {
new Literal(value).copyAttrs(tree)
def TypeTree(tree: Tree) =
new TypeTree().copyAttrs(tree)
+ def Attributed(tree: Tree, constr: Tree, elements: List[Tree], arg: Tree) =
+ new Attributed(constr, elements, arg)
def AttributedTypeTree(tree: Tree, attribs: List[Tree], tpt: Tree) =
new AttributedTypeTree(attribs, tpt)
def SingletonTypeTree(tree: Tree, ref: Tree) =
@@ -987,10 +996,10 @@ trait Trees requires Global {
if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t
case _ => copy.If(tree, cond, thenp, elsep)
}
- def Match(tree: Tree, selector: Tree, cases: List[CaseDef], check: boolean) = tree match {
- case t @ Match(selector0, cases0, check0)
- if (selector0 == selector) && (cases0 == cases) && (check0 == check) => t
- case _ => copy.Match(tree, selector, cases, check)
+ def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = tree match {
+ case t @ Match(selector0, cases0)
+ if (selector0 == selector) && (cases0 == cases) => t
+ case _ => copy.Match(tree, selector, cases)
}
def Return(tree: Tree, expr: Tree) = tree match {
case t @ Return(expr0)
@@ -1056,6 +1065,11 @@ trait Trees requires Global {
case t @ TypeTree() => t
case _ => copy.TypeTree(tree)
}
+ def Attributed(tree: Tree, constr: Tree, elements: List[Tree], arg: Tree) = tree match {
+ case t @ Attributed(constr0, elements0, arg0)
+ if (constr0==constr) && (elements0==elements) && (arg0==arg) => t
+ case _ => copy.Attributed(tree, constr, elements, arg)
+ }
def AttributedTypeTree(tree: Tree, attribs: List[Tree], tpt: Tree) = tree match {
case t @ AttributedTypeTree(attribs0, tpt0)
if (attribs0==attribs) && (tpt0==tpt) => t
@@ -1161,8 +1175,8 @@ trait Trees requires Global {
copy.Assign(tree, transform(lhs), transform(rhs))
case If(cond, thenp, elsep) =>
copy.If(tree, transform(cond), transform(thenp), transform(elsep))
- case Match(selector, cases, check) =>
- copy.Match(tree, transform(selector), transformCaseDefs(cases), check)
+ case Match(selector, cases) =>
+ copy.Match(tree, transform(selector), transformCaseDefs(cases))
case Return(expr) =>
copy.Return(tree, transform(expr))
case Try(block, catches, finalizer) =>
@@ -1189,6 +1203,8 @@ trait Trees requires Global {
copy.Literal(tree, value)
case TypeTree() =>
copy.TypeTree(tree)
+ case Attributed(constr, elements, arg) =>
+ copy.Attributed(tree, transform(constr), transformTrees(elements), transform(arg))
case AttributedTypeTree(attribs, tpt) =>
copy.AttributedTypeTree(tree, transformTrees(attribs), transform(tpt))
case SingletonTypeTree(ref) =>
@@ -1271,6 +1287,8 @@ trait Trees requires Global {
traverse(expr)
case Attribute(constr, elements) =>
traverse(constr); traverseTrees(elements)
+ case Attributed(constr: Tree, elements: List[Tree], arg: Tree) =>
+ traverse(constr); traverseTrees(elements); traverse(arg)
case DocDef(comment, definition) =>
traverse(definition)
case Template(parents, body) =>
@@ -1299,7 +1317,7 @@ trait Trees requires Global {
traverse(lhs); traverse(rhs)
case If(cond, thenp, elsep) =>
traverse(cond); traverse(thenp); traverse(elsep)
- case Match(selector, cases, _) =>
+ case Match(selector, cases) =>
traverse(selector); traverseTrees(cases)
case Return(expr) =>
traverse(expr)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 9a8810e330..aef8f96181 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -645,8 +645,9 @@ trait Parsers requires SyntaxAnalyzer {
}
}
- /** SimpleType ::= SimpleType TypeArgs
- * | SimpleType `#' Id
+ /** SimpleType ::= {`@' Attribute} SimpleType1
+ * SimpleType1 ::= SimpleType1 TypeArgs
+ * | SimpleType1 `#' Id
* | StableId
* | Path `.' type
* | `(' Type `)'
@@ -659,11 +660,7 @@ trait Parsers requires SyntaxAnalyzer {
* | `{' [ArgTypePattern `,' [ArgTypePatterns [`,']]] `}'
*/
def simpleType(isPattern: boolean): Tree = {
- val attribs =
- if(settings.Xplugtypes.value)
- typeAttributes
- else
- Nil
+ val attribs = typeAttributes()
val pos = in.currentPos
var t: Tree =
@@ -707,7 +704,10 @@ trait Parsers requires SyntaxAnalyzer {
done=true
}
- t.withAttributes(attribs)
+ if (settings.Xplugtypes.value) t.withAttributes(attribs)
+ else (t /: attribs) ((t, attr) => attr match {
+ case Attribute(constr, elements) => Attributed(constr, elements, t)
+ })
}
/** TypeArgs ::= `[' ArgTypes `]'
@@ -954,12 +954,10 @@ trait Parsers requires SyntaxAnalyzer {
}
} else if (in.token == MATCH) {
t = atPos(in.skipToken()) {
- val nocheck = isIdent && in.name == BANG
- if (nocheck) in.nextToken()
accept(LBRACE)
val cases = caseClauses()
accept(RBRACE)
- Match(t, cases, !nocheck)
+ Match(t, cases)
}
}
if ((mode & ClosureOK) != 0 && in.token == ARROW) {
@@ -2159,12 +2157,19 @@ trait Parsers requires SyntaxAnalyzer {
*
* Type attributes may be arbitrary expressions.
*/
- def typeAttributes: List[Tree] = {
+ def typeAttributes(): List[Tree] = {
val exps = new ListBuffer[Tree]
- while(in.token == LBRACKET) {
- accept(LBRACKET)
- exps ++= argExprs
- accept(RBRACKET)
+ if (settings.Xplugtypes.value) {
+ while(in.token == LBRACKET) {
+ accept(LBRACKET)
+ exps ++= argExprs
+ accept(RBRACKET)
+ }
+ } else {
+ while (in.token == AT) {
+ val pos = in.skipToken()
+ exps += attribute()
+ }
}
exps.toList
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index ca1eb1005c..f6cbead3ca 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -360,11 +360,18 @@ abstract class TreeBuilder {
def makeVisitor(cases: List[CaseDef], checkExhaustive: boolean): Tree =
makeVisitor(cases, checkExhaustive, "x$")
+ private def makeUnsealed(expr: Tree): Tree =
+ Attributed(New(scalaDot(definitions.UnsealedClass.name), List(List())), List(), expr)
+
+ private def checkAttr(expr: Tree, check: boolean) =
+ if (check) expr else makeUnsealed(expr)
+
/** Create visitor <x => x match cases> */
def makeVisitor(cases: List[CaseDef], checkExhaustive: boolean, prefix: String): Tree = {
val x = freshName(prefix)
+ val sel = if (checkExhaustive) Ident(x) else makeUnsealed(Ident(x))
Function(List(ValDef(Modifiers(PARAM | SYNTHETIC), x, TypeTree(), EmptyTree)),
- Match(Ident(x), cases, checkExhaustive))
+ Match(sel, cases))
}
/** Create tree for case definition &lt;case pat if guard => rhs&gt; */
@@ -395,7 +402,9 @@ abstract class TreeBuilder {
val pat1 = patvarTransformer.transform(pat)
val vars = getVariables(pat1)
val matchExpr = atPos(pat1.pos){
- Match(rhs, List(CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (._1) map Ident, true))), false)
+ Match(
+ makeUnsealed(rhs),
+ List(CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (._1) map Ident, true))))
}
vars match {
case List() =>
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 2da62c7806..3855438e6e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -894,7 +894,7 @@ abstract class GenICode extends SubComponent {
}
ctx1
- case Match(selector, cases, _) =>
+ case Match(selector, cases) =>
if (settings.debug.value)
log("Generating SWITCH statement.");
var ctx1 = genLoad(selector, ctx, INT)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 34e52699da..f1825e2b6e 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -122,9 +122,7 @@ abstract class GenJVM extends SubComponent {
val outfile = getFile(jclass, ".class")
jclass.writeTo(outfile)
val file = scala.tools.nsc.io.AbstractFile.getFile(outfile)
- informProgress("wrote " + outfile + " " +
- (if (file ne null) "" + file.file + " " + file.file.exists()
- else "no file"))
+ informProgress("wrote " + outfile)
}
var serialVUID: Option[Long] = None
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index 3b4a88e63c..c66c3e1ff8 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -1001,7 +1001,7 @@ print()
return Switch(selector, tags, bodies, defaultBody1, resultType);
*/
nCases = CaseDef(Ident(nme.WILDCARD), squeezedBlock(List(ValDef(root.symbol, selector)),defaultBody1)) :: nCases;
- Match(selector, nCases, false)
+ Match(selector, nCases)
}
@@ -1057,7 +1057,6 @@ print()
//Console.println("remain "+remainingCases+" carry covered "+ carryCovered + "real "+realRemainingCases)
if(!realRemainingCases.isEmpty) {
val word = if(realRemainingCases.size > 1) "cases " else "case "
- //Console.println(_h.print("non-exhaustive ", new StringBuilder()).toString())
cunit.warning(node.pos, "does not cover "+word+realRemainingCases.elements.mkString("{",",","}"))
//Console.println("full"); print()
//Console.println(_h.print("", new StringBuilder()).toString())
@@ -1214,8 +1213,7 @@ print()
nCases = CaseDef(Ident(nme.WILDCARD), defBody) :: nCases;
return Match(Apply(Select(selector.duplicate, defs.ScalaObjectClass_tag),
List()),
- nCases,
- false)
+ nCases)
}
/** why not use plain `if's? the reason is that a failing *guard* must still remain
diff --git a/src/compiler/scala/tools/nsc/models/Models.scala b/src/compiler/scala/tools/nsc/models/Models.scala
index d29dce02ab..1fe18a0ff5 100644
--- a/src/compiler/scala/tools/nsc/models/Models.scala
+++ b/src/compiler/scala/tools/nsc/models/Models.scala
@@ -404,7 +404,7 @@ abstract class Models {
flatten(expr0,filter)
case Try(block, catches, finalizer) =>
flatten(block, filter) ::: flatten(finalizer, filter) ::: flatten0(catches, filter)
- case Match(selector, cases, _) =>
+ case Match(selector, cases) =>
flatten(selector, filter) ::: flatten0(cases, filter)
case Apply(fun, args) =>
flatten(fun, filter) ::: flatten0(args, filter)
diff --git a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala
index efe79e2baf..9d2abb6aec 100644
--- a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala
+++ b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala
@@ -477,6 +477,7 @@ class SemanticTokens(val compiler: Global) {
case tree : DocDef => build(tree.definition);
case tree: Import => build(tree.expr)
case tree: AppliedTypeTree => ;
+ case tree: Attributed => ;
case tree: AttributedTypeTree => ;
case tree: SingletonTypeTree => ;
case tree: Super => ;
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index f2ed6bb6e1..c6fcbee6c7 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -106,6 +106,7 @@ trait Definitions requires SymbolTable {
def checkDefinedMethod = getMember(ScalaRunTimeModule, "checkDefined")
var RepeatedParamClass: Symbol = _
var ByNameParamClass: Symbol = _
+ var UnsealedClass: Symbol = _
val MaxTupleArity = 22
val TupleClass: Array[Symbol] = new Array(MaxTupleArity + 1)
@@ -782,6 +783,7 @@ trait Definitions requires SymbolTable {
ByNameParamClass = newCovariantPolyClass(
ScalaPackageClass, nme.BYNAME_PARAM_CLASS_NAME, tparam => AnyClass.typeConstructor)
/* <unapply> */
+ UnsealedClass = getClass("scala.unsealed")
OptionClass = getClass("scala.Option")
for (val i <- 1 to MaxTupleArity) {
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index b68d487d79..0f860ee5f3 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -56,18 +56,6 @@ trait Types requires SymbolTable {
/** The base class for all types */
abstract class Type {
- /** Add an attribute to this type */
- def withAttribute(attrib: Any) = withAttributes(List(attrib))
-
- /** Add a number of attributes to this type */
- def withAttributes(attribs: List[Any]): Type =
- attribs match {
- case Nil => this
- case _ => AttributedType(attribs, this)
- }
-
- /** Remove any attributes from this type */
- def withoutAttributes = this
/** Types for which asSeenFrom always is the identity, no matter what
* prefix or owner.
@@ -495,6 +483,19 @@ trait Types requires SymbolTable {
baseClasses.head.newOverloaded(this, members.toList)
}
}
+
+ /** Add an attribute to this type */
+ def withAttribute(attrib: Any) = withAttributes(List(attrib))
+
+ /** Add a number of attributes to this type */
+ def withAttributes(attribs: List[Any]): Type =
+ attribs match {
+ case Nil => this
+ case _ => AttributedType(attribs, this)
+ }
+
+ /** Remove any attributes from this type */
+ def withoutAttributes = this
}
// Subclasses ------------------------------------------------------------
@@ -1120,7 +1121,7 @@ trait Types requires SymbolTable {
override def symbol: Symbol = tp.symbol
override def singleDeref: Type = maybeRewrap(tp.singleDeref)
- override def widen: Type = maybeRewrap(tp.widen)
+ override def widen: Type = tp.widen
override def deconst: Type = maybeRewrap(tp.deconst)
override def bounds: TypeBounds = {
val oftp = tp.bounds
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index e10fdaf406..8d70c8360c 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -487,8 +487,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
tree1 match {
case If(cond, thenp, elsep) =>
copy.If(tree1, cond, adaptBranch(thenp), adaptBranch(elsep))
- case Match(selector, cases, check) =>
- copy.Match(tree1, selector, cases map adaptCase, check)
+ case Match(selector, cases) =>
+ copy.Match(tree1, selector, cases map adaptCase)
case Try(block, catches, finalizer) =>
copy.Try(tree1, adaptBranch(block), catches map adaptCase, finalizer)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 25f4695af7..de5e99c91e 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -468,7 +468,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
}
super.transform(copy.Apply(tree, sel, outerVal :: args))
- case Match(selector, cases, checkExhaustive) => // <----- transmatch hook
+ case Match(selector, cases) => // <----- transmatch hook
val tid = if (settings.debug.value) {
val q = unit.fresh.newName("tidmark")
Console.println("transforming patmat with tidmark "+q+" ncases = "+cases.length)
@@ -488,35 +488,49 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
}
*/
- val nselector = transform(selector)
+ var nselector = transform(selector)
assert(nselector.tpe =:= selector.tpe)
val ncases = transformCaseDefs(cases)
+ var checkExhaustive = true
+ def isUnsealedAttribute(tpe: Type) = tpe match {
+ case AttributedType(List(AttrInfo(atp, _, _)), _) if atp.symbol == UnsealedClass =>
+ true
+ case _ =>
+ false
+ }
+ nselector match {
+ case Typed(nselector1, tpt) if isUnsealedAttribute(tpt.tpe) =>
+ nselector = nselector1
+ checkExhaustive = false
+ case _ =>
+ }
+
ExplicitOuter.this.resultType = tree.tpe
//Console.println("TransMatcher currentOwner ="+currentOwner+")")
//Console.println("TransMatcher selector.tpe ="+selector.tpe+")")
//Console.println("TransMatcher resultType ="+resultType+")")
- val t_untyped = handlePattern(nselector, ncases, checkExhaustive, currentOwner, transform)
- try {
- //Console.println("t_untyped "+t_untyped.toString())
- val t = atPos(tree.pos) { localTyper.typed(t_untyped, resultType) }
-
- //t = transform(t)
- //val t = atPos(tree.pos) { typed(t_untyped, resultType) }
- //val t = atPos(tree.pos) { typed(t_untyped) }
- //Console.println("t typed "+t.toString())
- if (settings.debug.value)
- Console.println("finished translation of " + tid)
- t
- } catch {
- case e =>
- e.printStackTrace()
- //treeBrowser.browse(Seq.single(unit).elements)
- Console.println("[died while typechecking the translated pattern match:]")
- Console.println(t_untyped)
- null
- }
+ val t_untyped = handlePattern(nselector, ncases, checkExhaustive, currentOwner, transform)
+ try {
+ //Console.println("t_untyped "+t_untyped.toString())
+ val t = atPos(tree.pos) { localTyper.typed(t_untyped, resultType) }
+
+ //t = transform(t)
+ //val t = atPos(tree.pos) { typed(t_untyped, resultType) }
+ //val t = atPos(tree.pos) { typed(t_untyped) }
+ //Console.println("t typed "+t.toString())
+ if (settings.debug.value)
+ Console.println("finished translation of " + tid)
+ t
+ } catch {
+ case e =>
+ e.printStackTrace()
+ //treeBrowser.browse(Seq.single(unit).elements)
+ Console.println("[died while typechecking the translated pattern match:]")
+ Console.println(t_untyped)
+ null
+ }
case _ =>
val x = super.transform(tree)
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 6628751d30..c83430f265 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -213,8 +213,8 @@ abstract class TailCalls extends Transform
case If(cond, thenp, elsep) =>
copy.If(tree, cond, transform(thenp), transform(elsep));
- case Match(selector, cases, check) => //super.transform(tree);
- copy.Match(tree, transform(selector, mkContext(ctx, false)), transformTrees(cases).asInstanceOf[List[CaseDef]], check);
+ case Match(selector, cases) => //super.transform(tree);
+ copy.Match(tree, transform(selector, mkContext(ctx, false)), transformTrees(cases).asInstanceOf[List[CaseDef]]);
case Return(expr) => super.transform(tree)
case Try(block, catches, finalizer) =>
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 02d2d69c85..3fb78e63b2 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -244,7 +244,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
.setFlag(FINAL).setInfo(MethodType(formals, BooleanClass.tpe))
anonClass.info.decls enter isDefinedAtMethod
def idbody(idparam: Symbol) = fun.body match {
- case Match(_, cases, check) =>
+ case Match(_, cases) =>
val substParam = new TreeSymSubstituter(List(fun.vparams.head.symbol), List(idparam));
def transformCase(cdef: CaseDef): CaseDef =
substParam(
@@ -255,8 +255,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
Match(
Ident(idparam),
(cases map transformCase) :::
- List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))),
- check)
+ List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))))
}
members = DefDef(isDefinedAtMethod, vparamss => idbody(vparamss.head.head)) :: members;
}
@@ -471,7 +470,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
CaseDef(
Bind(exname, Ident(nme.WILDCARD)),
EmptyTree,
- Match(Ident(exname), cases, false))
+ Match(Ident(exname), cases))
}
if (settings.debug.value) log("rewrote try: " + catches + " ==> " + catchall);
val catches1 = localTyper.typedCases(
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 6dfba7ace7..0c1df47925 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -616,7 +616,7 @@ abstract class RefChecks extends InfoTransform {
Select(qual, nme.filter),
List(Function(
List(ValDef(_, pname, tpt, _)),
- Match(_, CaseDef(pat1, _, _) :: _, _))))
+ Match(_, CaseDef(pat1, _, _) :: _))))
if ((pname startsWith nme.CHECK_IF_REFUTABLE_STRING) &&
isIrrefutable(pat1, tpt.tpe)) =>
result = qual
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 9bd64801d8..f5999b3582 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -87,7 +87,7 @@ trait SyntheticMethods requires Analyzer {
Throw(New(TypeTree(IndexOutOfBoundsExceptionClass.tpe), List(List(
Select(Ident(vparamss.head.head), nme.toString_)
))))))
- }, false)))
+ })))
}
def moduleToStringMethod: Tree = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 42a3bd1831..9b905f6319 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -883,6 +883,9 @@ trait Typers requires Analyzer {
case DocDef(comment, defn) =>
addGetterSetter(defn) map (stat => DocDef(comment, stat))
+ case Attributed(constr, elements, defn) =>
+ addGetterSetter(defn) map (stat => Attributed(constr, elements, stat))
+
case _ =>
List(stat)
}
@@ -1512,6 +1515,54 @@ trait Typers requires Analyzer {
}
}
+ def typedAttribute(constr: Tree, elements: List[Tree]): AttrInfo = {
+ var attrError: Boolean = false;
+ def error(pos: PositionType, msg: String): Null = {
+ context.error(pos, msg)
+ attrError = true
+ null
+ }
+ def getConstant(tree: Tree): Constant = tree match {
+ case Literal(value) => value
+ case arg => error(arg.pos, "attribute argument needs to be a constant; found: "+arg)
+ }
+ val attrInfo =
+ typed(constr, EXPRmode | CONSTmode, AttributeClass.tpe) match {
+ case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
+ val constrArgs = args map getConstant
+ val attrScope = tpt.tpe.decls
+ .filter(sym => sym.isMethod && !sym.isConstructor && sym.hasFlag(JAVA));
+ val names = new collection.mutable.HashSet[Symbol]
+ names ++= attrScope.elements.filter(.isMethod)
+ if (args.length == 1) {
+ names.retain(sym => sym.name != nme.value)
+ }
+ val nvPairs = elements map {
+ case Assign(ntree @ Ident(name), rhs) => {
+ val sym = attrScope.lookup(name);
+ if (sym == NoSymbol) {
+ error(ntree.pos, "unknown attribute element name: " + name)
+ } else if (!names.contains(sym)) {
+ error(ntree.pos, "duplicate value for element " + name)
+ } else {
+ names -= sym
+ {sym.name, getConstant(typed(rhs, EXPRmode | CONSTmode, sym.tpe.resultType))}
+ }
+ }
+ }
+ for (val name <- names) {
+ if (!name.attributes.contains{AnnotationDefaultAttr.tpe, List(), List()}) {
+ error(constr.pos, "attribute " + tpt.tpe.symbol.fullNameString + " is missing element " + name.name)
+ }
+ }
+ if (tpt.tpe.symbol.hasFlag(JAVA) && settings.target.value == "jvm-1.4") {
+ context.unit.warning (constr.pos, "Java annotation will not be emitted in classfile unless you use the '-target:jvm-1.5' option")
+ }
+ AttrInfo(tpt.tpe, constrArgs, nvPairs)
+ }
+ if (attrError) AttrInfo(ErrorType, List(), List()) else attrInfo
+ }
+
/**
* @param tree ...
* @param mode ...
@@ -1870,11 +1921,29 @@ trait Typers requires Analyzer {
}
typer1.typedLabelDef(ldef)
- case DocDef(comment, defn) => {
+ case DocDef(comment, defn) =>
val ret = typed(defn, mode, pt)
- if (comments ne null) comments(defn . symbol) = comment;
+ if (comments ne null) comments(defn.symbol) = comment
ret
- }
+
+ case Attributed(constr, elements, arg) =>
+ val attrInfo = typedAttribute(constr, elements)
+ val arg1 = typed(arg, mode, pt)
+ def attrType =
+ TypeTree(arg1.tpe.withAttribute(attrInfo)) setOriginal tree
+ arg1 match {
+ case _: DefTree =>
+ if (!attrInfo.atp.isError) {
+ val attributed =
+ if (arg1.symbol.isModule) arg1.symbol.moduleClass else arg1.symbol
+ attributed.attributes = attrInfo :: attributed.attributes
+ }
+ arg1
+ case _ =>
+ if (arg1.isType) attrType
+ else Typed(arg1, attrType) setPos tree.pos setType attrType.tpe
+ }
+
case tree @ Block(_, _) =>
newTyper(makeNewScope(context, tree, context.owner))
.typedBlock(tree, mode, pt)
@@ -1979,10 +2048,10 @@ trait Typers requires Analyzer {
copy.If(tree, cond1, thenp1, elsep1) setType ptOrLub(List(thenp1.tpe, elsep1.tpe))
}
- case Match(selector, cases, check) =>
+ case Match(selector, cases) =>
val selector1 = typed(selector)
val cases1 = typedCases(tree, cases, selector1.tpe.widen, pt)
- copy.Match(tree, selector1, cases1, check) setType ptOrLub(cases1 map (.tpe))
+ copy.Match(tree, selector1, cases1) setType ptOrLub(cases1 map (.tpe))
case Return(expr) =>
val enclMethod = context.enclMethod
diff --git a/src/library/scala/unsealed.scala b/src/library/scala/unsealed.scala
new file mode 100755
index 0000000000..5ea51ae144
--- /dev/null
+++ b/src/library/scala/unsealed.scala
@@ -0,0 +1,18 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: remote.scala 9400 2006-11-28 17:22:45 +0000 (Tue, 28 Nov 2006) michelou $
+
+
+package scala
+
+/**
+ * An attribute that gets applied to a selector in a match expression.
+ * If it is present, exhaustiveness warnings for that expression will be suppressed.
+ */
+class unsealed extends Attribute {}