diff options
author | Martin Odersky <odersky@gmail.com> | 2006-12-04 17:41:36 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2006-12-04 17:41:36 +0000 |
commit | 67dfced37f9b5d7a2b7f80f4da7fb5716f557350 (patch) | |
tree | c62c6fafcd14d847d45baa8b6155d9c52b76cbfc | |
parent | 525018c3cab1aaeb6644e9dacae2ab36ffa28d13 (diff) | |
download | scala-67dfced37f9b5d7a2b7f80f4da7fb5716f557350.tar.gz scala-67dfced37f9b5d7a2b7f80f4da7fb5716f557350.tar.bz2 scala-67dfced37f9b5d7a2b7f80f4da7fb5716f557350.zip |
added infix type constructors
added &: infix constructor for pairs
optimization to remove redudant outer pointers
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Constructors.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 5 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala | 18 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala | 20 | ||||
-rw-r--r-- | src/library/scala/Function.scala | 2 | ||||
-rw-r--r-- | src/library/scala/Predef.scala | 48 | ||||
-rw-r--r-- | test/files/neg/bug845.check | 4 | ||||
-rw-r--r-- | test/files/neg/bug845.scala | 16 |
9 files changed, 83 insertions, 41 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 844d74cea5..23ba5df865 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1,4 +1,4 @@ -/* NSC -- new Scala compiler + /* NSC -- new Scala compiler * Copyright 2005-2006 LAMP/EPFL * @author Martin Odersky */ @@ -49,6 +49,7 @@ trait Types requires SymbolTable { private var checkMalformedSwitch = true private var globalVariance = 1 private final val healTypes = false + private final val LubGlbMargin = 0 val emptyTypeArray = new Array[Type](0) @@ -717,7 +718,7 @@ trait Types requires SymbolTable { case RefinedType(parents, decls) => assert(decls.isEmpty) //Console.println("compute closure of "+this+" => glb("+parents+")") - closureCache(j) = mergePrefixAndArgs(parents, -1, maxClosureDepth(parents)) match { + closureCache(j) = mergePrefixAndArgs(parents, -1, maxClosureDepth(parents) + LubGlbMargin) match { case Some(tp0) => tp0 case None => throw new MalformedClosure(parents) } @@ -2168,7 +2169,7 @@ trait Types requires SymbolTable { if (rest exists (t1 => t <:< t1)) rest else t :: rest } - def lub(ts: List[Type]): Type = lub(ts, maxClosureDepth(ts)) + def lub(ts: List[Type]): Type = lub(ts, maxClosureDepth(ts) + LubGlbMargin) /** The least upper bound wrt <:< of a list of types */ def lub(ts: List[Type], depth: int): Type = { @@ -2250,7 +2251,7 @@ trait Types requires SymbolTable { res } - def glb(ts: List[Type]): Type = glb(ts, maxClosureDepth(ts)) + def glb(ts: List[Type]): Type = glb(ts, maxClosureDepth(ts) + LubGlbMargin) /** The greatest lower bound wrt <:< of a list of types */ private def glb(ts: List[Type], depth: int): Type = { diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 9849af6dcf..54ea55dde8 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -74,7 +74,7 @@ abstract class Constructors extends Transform { } else if (tree.symbol.outerSource == clazz && !clazz.isImplClass) { thisRefSeen = false - gen.mkAttributedIdent(parameterNamed(nme.OUTER)) + gen.mkAttributedIdent(parameterNamed(nme.OUTER)) setPos tree.pos } else super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 9df54f371a..17b3798e34 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -227,8 +227,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { gen.mkRuntimeCall(nme.arrayValue, List(tree1, Literal(pt.typeArgs.head))) } else { - Apply(gen.mkAttributedRef(unboxMethod(pt.symbol)), List(tree)). - setPos(tree.pos) setType pt + atPos(tree.pos) { + Apply(gen.mkAttributedRef(unboxMethod(pt.symbol)), List(tree)) setType pt + } } } } diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 2080baff5c..70996371b8 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -37,6 +37,17 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter private def isInner(clazz: Symbol) = !clazz.isPackageClass && !clazz.outerClass.isStaticOwner + /** Does given <code>clazz</code> define an outer field? */ + def hasOuterField(clazz: Symbol) = { + def hasSameOuter(parent: Type) = + parent.symbol.isClass && + clazz.owner.isClass && + clazz.owner == parent.symbol.owner && + parent.prefix =:= clazz.owner.thisType + isInner(clazz) && !clazz.isTrait && + (clazz.info.parents.isEmpty || !hasSameOuter(clazz.info.parents.head)) + } + private def outerField(clazz: Symbol): Symbol = { val result = clazz.info.member(nme.getterToLocal(nme.OUTER)) if (result == NoSymbol) @@ -184,12 +195,12 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter outerAcc.expandName(clazz) val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType decls1 enter clazz.newOuterAccessor(clazz.pos).setInfo(MethodType(List(), restpe)) - if (!clazz.isTrait) // 2 - //todo: avoid outer field if superclass has same outer value? + if (hasOuterField(clazz)) { //2 decls1 enter ( clazz.newValue(clazz.pos, nme.getterToLocal(nme.OUTER)) setFlag (SYNTHETIC | PROTECTED | PARAMACCESSOR) setInfo clazz.outerClass.thisType) + } } if (!clazz.isTrait && !parents.isEmpty) { for (val mc <- clazz.mixinClasses) { @@ -513,7 +524,8 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter atOwner(tree, currentOwner) { if (!(currentClass hasFlag INTERFACE) || (currentClass hasFlag lateINTERFACE)) { if (isInner(currentClass)) { - if (!currentClass.isTrait) newDefs += outerFieldDef // (1a) + if (hasOuterField(currentClass)) + newDefs += outerFieldDef // (1a) newDefs += outerAccessorDef // (1) } if (!currentClass.isTrait) diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index 5871edbf10..2cceae8059 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -48,14 +48,20 @@ abstract class TreeCheckers extends Analyzer { case EmptyTree | TypeTree() => ; case _ => - if (!tpeOfTree.contains(tree)) { - tpeOfTree.update(tree, tree.tpe) - tree.tpe = null + try { + if (!tpeOfTree.contains(tree)) { + tpeOfTree.update(tree, tree.tpe) + tree.tpe = null + } + val newtree = super.typed(tree, mode, pt); + if ((newtree ne tree) && !newtree.isInstanceOf[Literal]) + error(tree.pos, "trees differ\n old: " + tree + " [" + tree.getClass() + + "]\n new: " + newtree + " [" + newtree.getClass() + "]") + } catch { + case ex: Throwable => + Console.println("exception while typing "+tree) + throw ex } - val newtree = super.typed(tree, mode, pt); - if ((newtree ne tree) && !newtree.isInstanceOf[Literal]) - error(tree.pos, "trees differ\n old: " + tree + " [" + tree.getClass() + - "]\n new: " + newtree + " [" + newtree.getClass() + "]") } tree } diff --git a/src/library/scala/Function.scala b/src/library/scala/Function.scala index 6f4c14ed55..12e124779b 100644 --- a/src/library/scala/Function.scala +++ b/src/library/scala/Function.scala @@ -16,7 +16,7 @@ package scala * @author Martin Odersky * @version 1.0, 29/11/2006 */ -object Function extends Application { +object Function { /** Given a sequence of functions <code>f<sub>1</sub></code>, ..., * <code>f<sub>n</sub></code>, return the function <code>f<sub>1</sub> diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 9985a4f855..1422aa6d0d 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -54,29 +54,7 @@ object Predef { type NoSuchElementException = java.util.NoSuchElementException type NumberFormatException = java.lang.NumberFormatException -/* - type ~[a, b] = Tuple2[a, b] - class FirstOfPair[a](x: a) { - def ~[b](y: b): Tuple2[a, b] = Tuple2(x, y) - } - implicit def any2firstOfPair[a](x: a): FirstOfPair[a] = new FirstOfPair(x) -*/ - - type Pair[+a, +b] = Tuple2[a, b] - def Pair[a, b](x: a, y: b) = Tuple2(x, y) - - type Triple[+a, +b, +c] = Tuple3[a, b, c] - def Triple[a, b, c](x: a, y: b, z: c) = Tuple3(x, y, z) - - def Tuple[a1](x1: a1) = Tuple1(x1) - def Tuple[a1, a2](x1: a1, x2: a2) = Tuple2(x1, x2) - def Tuple[a1, a2, a3](x1: a1, x2: a2, x3: a3) = Tuple3(x1, x2, x3) - def Tuple[a1, a2, a3, a4](x1: a1, x2: a2, x3: a3, x4: a4) = Tuple4(x1, x2, x3, x4) - def Tuple[a1, a2, a3, a4, a5](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5) = Tuple5(x1, x2, x3, x4, x5) - def Tuple[a1, a2, a3, a4, a5, a6](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6) = Tuple6(x1, x2, x3, x4, x5, x6) - def Tuple[a1, a2, a3, a4, a5, a6, a7](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7) = Tuple7(x1, x2, x3, x4, x5, x6, x7) - def Tuple[a1, a2, a3, a4, a5, a6, a7, a8](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7, x8: a8) = Tuple8(x1, x2, x3, x4, x5, x6, x7, x8) - def Tuple[a1, a2, a3, a4, a5, a6, a7, a8, a9](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7, x8: a8, x9: a9) = Tuple9(x1, x2, x3, x4, x5, x6, x7, x8, x9) + // --- Miscelleaneous ----------------------------------------------- val $scope = scala.xml.TopScope @@ -113,6 +91,30 @@ object Predef { throw new Error("assumption failed: " + message) } + // --- Tupling ---------------------------------------------- + + type Pair[+a, +b] = Tuple2[a, b] + def Pair[a, b](x: a, y: b) = Tuple2(x, y) + + type Triple[+a, +b, +c] = Tuple3[a, b, c] + def Triple[a, b, c](x: a, y: b, z: c) = Tuple3(x, y, z) + + type &: [+a, +b] = Tuple2[a, b] + class SndOfPair[+b](y: b) { + def &: [a](x: a): Tuple2[a, b] = Tuple2(x, y) + } + implicit def any2sndOfPair[b](x: b): SndOfPair[b] = new SndOfPair(x) + + def Tuple[a1](x1: a1) = Tuple1(x1) + def Tuple[a1, a2](x1: a1, x2: a2) = Tuple2(x1, x2) + def Tuple[a1, a2, a3](x1: a1, x2: a2, x3: a3) = Tuple3(x1, x2, x3) + def Tuple[a1, a2, a3, a4](x1: a1, x2: a2, x3: a3, x4: a4) = Tuple4(x1, x2, x3, x4) + def Tuple[a1, a2, a3, a4, a5](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5) = Tuple5(x1, x2, x3, x4, x5) + def Tuple[a1, a2, a3, a4, a5, a6](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6) = Tuple6(x1, x2, x3, x4, x5, x6) + def Tuple[a1, a2, a3, a4, a5, a6, a7](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7) = Tuple7(x1, x2, x3, x4, x5, x6, x7) + def Tuple[a1, a2, a3, a4, a5, a6, a7, a8](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7, x8: a8) = Tuple8(x1, x2, x3, x4, x5, x6, x7, x8) + def Tuple[a1, a2, a3, a4, a5, a6, a7, a8, a9](x1: a1, x2: a2, x3: a3, x4: a4, x5: a5, x6: a6, x7: a7, x8: a8, x9: a9) = Tuple9(x1, x2, x3, x4, x5, x6, x7, x8, x9) + // views ------------------------------------------------------------- implicit def identity[a](x: a): a = x diff --git a/test/files/neg/bug845.check b/test/files/neg/bug845.check new file mode 100644 index 0000000000..1750611993 --- /dev/null +++ b/test/files/neg/bug845.check @@ -0,0 +1,4 @@ +bug845.scala:4 error: only classes can have declared but undefined members + type Bar; + ^ +one error found diff --git a/test/files/neg/bug845.scala b/test/files/neg/bug845.scala new file mode 100644 index 0000000000..c8a2faa671 --- /dev/null +++ b/test/files/neg/bug845.scala @@ -0,0 +1,16 @@ +package test; + +object Test extends Application { + type Bar; + trait FooImpl; + + trait Bob { + def bar : Bar with FooImpl; + } + def ifn[A,B](a : A)(f : A => B) = + if (a != null) f(a) else null; + + val bob : Bob = null; + val bar = ifn(bob)(.bar); + assert(bar == null); +} |