summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-04-19 15:01:46 -0700
committerPaul Phillips <paulp@improving.org>2013-04-20 15:25:53 -0700
commitc29405dfe1a24419ce4ce10500b5e8d05c581bee (patch)
treedca5ea3a915101613b6d007831d9240596b685f5 /src
parentd506bedc5ab83bf9af8cc0240e61a0c691f8508b (diff)
downloadscala-c29405dfe1a24419ce4ce10500b5e8d05c581bee.tar.gz
scala-c29405dfe1a24419ce4ce10500b5e8d05c581bee.tar.bz2
scala-c29405dfe1a24419ce4ce10500b5e8d05c581bee.zip
Simplify type bounds.
I started out looking to limit the noise from empty type bounds, i.e. the endless repetition of class A[T >: _root_.scala.Nothing <: _root_.scala.Any] This led me to be reminded of all the unnecessary and in fact damaging overreaches which are performed during parsing. Why should a type parameter for which no bounds are specified be immediately encoded with this giant tree: TypeBounds( Select(Select(Ident(nme.ROOTPKG), tpnme.scala_), tpnme.Nothing), Select(Select(Ident(nme.ROOTPKG), tpnme.scala_), tpnme.Any) ) ...which must then be manually recognized as empty type bounds? Truly, this is madness. - It deftly eliminates the possibility of recognizing whether the user wrote "class A[T]" or "class A[T >: Nothing]" or "class A[T <: Any]" or specified both bounds. The fact that these work out the same internally does not imply the information should be exterminated even before parsing completes. - It burdens everyone who must recognize type bounds trees, such as this author - It is far less efficient than the obvious encoding - It offers literally no advantage whatsoever Encode empty type bounds as TypeBounds(EmptyTree, EmptyTree) What could be simpler.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala18
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala22
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala9
4 files changed, 24 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 7671912651..2f981d23f6 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2222,16 +2222,18 @@ self =>
* }}}
*/
def typeBounds(): TypeBoundsTree = {
- val t = TypeBoundsTree(
- bound(SUPERTYPE, tpnme.Nothing),
- bound(SUBTYPE, tpnme.Any)
- )
- t setPos wrappingPos(List(t.hi, t.lo))
+ val lo = bound(SUPERTYPE)
+ val hi = bound(SUBTYPE)
+ val t = TypeBoundsTree(lo, hi)
+ val defined = List(t.hi, t.lo) filter (_.pos.isDefined)
+
+ if (defined.nonEmpty)
+ t setPos wrappingPos(defined)
+ else
+ t setPos o2p(in.offset)
}
- def bound(tok: Int, default: TypeName): Tree =
- if (in.token == tok) { in.nextToken(); typ() }
- else atPos(o2p(in.lastOffset)) { rootScalaDot(default) }
+ def bound(tok: Int): Tree = if (in.token == tok) { in.nextToken(); typ() } else EmptyTree
/* -------- DEFS ------------------------------------------- */
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index f1b1d1a9a7..786754ce4c 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -293,15 +293,8 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
if (in.token == QMARK) {
val pos = in.currentPos
in.nextToken()
- var lo: Tree = TypeTree(NothingClass.tpe)
- var hi: Tree = TypeTree(AnyClass.tpe)
- if (in.token == EXTENDS) {
- in.nextToken()
- hi = typ()
- } else if (in.token == SUPER) {
- in.nextToken()
- lo = typ()
- }
+ val hi = if (in.token == EXTENDS) { in.nextToken() ; typ() } else EmptyTree
+ val lo = if (in.token == SUPER) { in.nextToken() ; typ() } else EmptyTree
val tdef = atPos(pos) {
TypeDef(
Modifiers(Flags.JAVA | Flags.DEFERRED),
@@ -408,15 +401,8 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
def typeParam(): TypeDef =
atPos(in.currentPos) {
val name = identForType()
- val hi =
- if (in.token == EXTENDS) {
- in.nextToken()
- bound()
- } else {
- scalaDot(tpnme.Any)
- }
- TypeDef(Modifiers(Flags.JAVA | Flags.DEFERRED | Flags.PARAM), name, List(),
- TypeBoundsTree(scalaDot(tpnme.Nothing), hi))
+ val hi = if (in.token == EXTENDS) { in.nextToken() ; bound() } else EmptyTree
+ TypeDef(Modifiers(Flags.JAVA | Flags.DEFERRED | Flags.PARAM), name, Nil, TypeBoundsTree(EmptyTree, hi))
}
def bound(): Tree =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a7b68ee6f8..8cf47b500d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -5149,8 +5149,8 @@ trait Typers extends Adaptations with Tags {
}
def typedTypeBoundsTree(tree: TypeBoundsTree) = {
- val lo1 = typedType(tree.lo, mode)
- val hi1 = typedType(tree.hi, mode)
+ val lo1 = if (tree.lo.isEmpty) TypeTree(NothingTpe) else typedType(tree.lo, mode)
+ val hi1 = if (tree.hi.isEmpty) TypeTree(AnyTpe) else typedType(tree.hi, mode)
treeCopy.TypeBoundsTree(tree, lo1, hi1) setType TypeBounds(lo1.tpe, hi1.tpe)
}
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index 5b80889225..b8e73e51f3 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -421,7 +421,14 @@ trait Printers extends api.Printers { self: SymbolTable =>
print(tp); printRow(args, "[", ", ", "]")
case TypeBoundsTree(lo, hi) =>
- printOpt(" >: ", lo); printOpt(" <: ", hi)
+ // Avoid printing noisy empty typebounds everywhere
+ // Untyped empty bounds are not printed by printOpt,
+ // but after they are typed we have to exclude Nothing/Any.
+ if ((lo.tpe eq null) || !(lo.tpe =:= definitions.NothingTpe))
+ printOpt(" >: ", lo)
+
+ if ((hi.tpe eq null) || !(hi.tpe =:= definitions.AnyTpe))
+ printOpt(" <: ", hi)
case ExistentialTypeTree(tpt, whereClauses) =>
print(tpt)