diff options
-rw-r--r-- | sources/scalac/symtab/Modifiers.java | 1 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 6 | ||||
-rw-r--r-- | sources/scalac/transformer/LambdaLift.java | 83 | ||||
-rw-r--r-- | test/files/neg/bug52.check | 6 | ||||
-rw-r--r-- | test/files/neg/bug52.scala | 4 | ||||
-rw-r--r-- | test/files/neg/refine.check | 9 | ||||
-rw-r--r-- | test/files/pos/bug30.scala | 9 | ||||
-rw-r--r-- | test/files/pos/bug31.scala | 29 | ||||
-rw-r--r-- | test/files/pos/bug36.scala | 8 | ||||
-rw-r--r-- | test/files/pos/bug39.scala | 6 | ||||
-rw-r--r-- | test/files/pos/refine.scala | 6 | ||||
-rw-r--r-- | test/files/pos/seqtest2.scala | 13 | ||||
-rw-r--r-- | test/neg/bug52.check | 6 | ||||
-rw-r--r-- | test/neg/bug52.scala | 4 | ||||
-rw-r--r-- | test/neg/refine.check | 9 | ||||
-rw-r--r-- | test/pos/bug30.scala | 9 | ||||
-rw-r--r-- | test/pos/bug31.scala | 29 | ||||
-rw-r--r-- | test/pos/bug36.scala | 8 | ||||
-rw-r--r-- | test/pos/bug39.scala | 6 | ||||
-rw-r--r-- | test/pos/refine.scala | 6 | ||||
-rw-r--r-- | test/pos/seqtest2.scala | 13 |
21 files changed, 251 insertions, 19 deletions
diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java index 00509ad16b..5948dc2157 100644 --- a/sources/scalac/symtab/Modifiers.java +++ b/sources/scalac/symtab/Modifiers.java @@ -48,6 +48,7 @@ public interface Modifiers { int ACCESSOR = 0x04000000; // function is an access function for a // value or variable int BRIDGE = 0x08000000; // function is a bridge method. + int LIFTED = BRIDGE; // transient flag for lambdalift int SNDTIME = BRIDGE; // debug int INTERFACE = 0x10000000; // symbol is a Java interface diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index 430bcaa5e9..ae2960bb4e 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -29,7 +29,7 @@ public class Type implements Modifiers, Kinds, TypeTags { public case ThisType(Symbol sym); /** pre.sym.type - * sym represents a value + * sym represents a valueS */ public case SingleType(Type pre, Symbol sym) { assert this instanceof ExtSingleType; @@ -1272,7 +1272,9 @@ public class Type implements Modifiers, Kinds, TypeTags { case TypeRef(Type pre1, Symbol sym1, Type[] args1): switch (this) { case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym.name == sym1.name && pre.isSubType(pre1) && + boolean samepre = pre.isSameAs(pre1); + if ((samepre && sym == sym1 /* fast case */ || + !samepre && pre.isSubType(pre1) && sym == pre.rebind(sym1)) && isSubArgs(args, args1, sym.typeParams()) || sym.kind == TYPE && pre.memberInfo(sym).isSubType(that)) diff --git a/sources/scalac/transformer/LambdaLift.java b/sources/scalac/transformer/LambdaLift.java index 1e90f95624..a86c39c793 100644 --- a/sources/scalac/transformer/LambdaLift.java +++ b/sources/scalac/transformer/LambdaLift.java @@ -50,6 +50,7 @@ public class LambdaLift extends OwnerTransformer public void apply(Unit unit) { global.log(unit.source.toString()); free.initialize(unit); + currentOwner = global.definitions.ROOT_CLASS; unit.body = transformTemplateStats(unit.body, currentOwner); } @@ -315,42 +316,49 @@ public class LambdaLift extends OwnerTransformer tree.type = descr.transform(tree.type, currentOwner); //System.out.println(tree.type);//DEBUG switch (tree) { - case ClassDef(_, _, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl): + case Block(Tree[] stats): + for (int i = 0; i < stats.length; i++) + liftSymbol(stats[i]); + return copy.Block(tree, transform(stats)); + + case ClassDef(int mods, _, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Template impl): Symbol sym = tree.symbol(); - if (sym.isLocal()) { - Symbol[] newtparams = ftvsParams(sym.constructor()); - Symbol[] newparams = fvsParams(sym.constructor()); - liftSymbol(sym, newtparams, newparams); + if ((mods & LIFTED) != 0) { + ((ClassDef) tree).mods &= ~LIFTED; Tree tree1 = copy.ClassDef( tree, sym, - addTypeParams(transform(tparams, sym), newtparams), - new ValDef[][]{addParams(transform(vparams, sym)[0], newparams)}, + addTypeParams(transform(tparams, sym), newtparams(sym.constructor())), + new ValDef[][]{ + addParams(transform(vparams, sym)[0], newparams(sym.constructor()))}, transform(tpe, sym), transform(impl, sym)); liftedDefs.append(tree1); return Tree.Empty; } else { + assert !sym.isLocal() : sym; return copy.ClassDef( tree, sym, - transform(tparams, sym), transform(vparams, sym), transform(tpe, sym), + transform(tparams, sym), + transform(vparams, sym), + transform(tpe, sym), transform(impl, sym)); } - case DefDef(_, _, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Tree rhs): + case DefDef(int mods, _, TypeDef[] tparams, ValDef[][] vparams, Tree tpe, Tree rhs): Symbol sym = tree.symbol(); - if (sym.isLocal()) { - Symbol[] newtparams = ftvsParams(sym); - Symbol[] newparams = fvsParams(sym); - liftSymbol(sym, newtparams, newparams); + if ((mods & LIFTED) != 0) { + ((DefDef) tree).mods &= ~LIFTED; Tree tree1 = copy.DefDef( tree, sym, - addTypeParams(transform(tparams, sym), newtparams), - new ValDef[][]{addParams(transform(vparams, sym)[0], newparams)}, + addTypeParams(transform(tparams, sym), newtparams(sym)), + new ValDef[][]{ + addParams(transform(vparams, sym)[0], newparams(sym))}, transform(tpe, sym), transform(rhs, sym)); liftedDefs.append(tree1); return Tree.Empty; } else { + assert !sym.isLocal() : sym; return copy.DefDef( tree, sym, transform(tparams, sym), transform(vparams, sym), transform(tpe, sym), @@ -400,7 +408,8 @@ public class LambdaLift extends OwnerTransformer default: Tree[] targs = addFreeArgs( tree.pos, get(free.ftvs, fsym), Tree.EMPTY_ARRAY); - if (targs.length > 0) fn1 = gen.TypeApply(fn1, targs); + if (targs.length > 0) + fn1 = gen.TypeApply(fn1, targs); } Tree[] args1 = transform(args); return copy.Apply( @@ -451,11 +460,47 @@ public class LambdaLift extends OwnerTransformer return params; } - /** change symbol so that + Symbol[] newtparams(Symbol owner) { + Symbol[] tparams = owner.typeAt(descr.nextPhase).typeParams(); + int nfree = get(free.ftvs, owner).size(); + assert nfree == tparams.length - owner.type().typeParams().length + : owner + " " + nfree + " " + tparams.length + " " + owner.type().firstParams().length; + Symbol[] newtparams = new Symbol[nfree]; + System.arraycopy(tparams, tparams.length - nfree, newtparams, 0, nfree); + return newtparams; + } + + Symbol[] newparams(Symbol owner) { + Symbol[] params = owner.typeAt(descr.nextPhase).firstParams(); + int nfree = get(free.fvs, owner).size(); + assert nfree == params.length - owner.type().firstParams().length; + Symbol[] newparams = new Symbol[nfree]; + System.arraycopy(params, params.length - nfree, newparams, 0, nfree); + return newparams; + } + + /** change symbol of tree so that * owner = currentClass * newparams are added * enter symbol in scope of currentClass */ + void liftSymbol(Tree tree) { + switch (tree) { + case ClassDef(_, _, _, _, _, _): + ((ClassDef) tree).mods |= LIFTED; + Symbol sym = tree.symbol(); + assert sym.isLocal() : sym; + liftSymbol(sym, ftvsParams(sym.constructor()), fvsParams(sym.constructor())); + break; + + case DefDef(_, _, _, _, _, _): + ((DefDef) tree).mods |= LIFTED; + Symbol sym = tree.symbol(); + assert sym.isLocal() : sym; + liftSymbol(sym, ftvsParams(sym), fvsParams(sym)); + } + } + void liftSymbol(Symbol sym, Symbol[] newtparams, Symbol[] newparams) { Symbol enclClass = sym.owner().enclClass(); if (!sym.isPrimaryConstructor()) sym.setOwner(enclClass); @@ -491,6 +536,10 @@ public class LambdaLift extends OwnerTransformer } } + boolean isLocal() { + return currentOwner.kind == VAL && currentOwner.name != Name.EMPTY; + } + Type addParams(Type tp, Symbol[] newparams) { if (newparams.length == 0) return tp; switch (tp) { diff --git a/test/files/neg/bug52.check b/test/files/neg/bug52.check new file mode 100644 index 0000000000..cd4b5eccce --- /dev/null +++ b/test/files/neg/bug52.check @@ -0,0 +1,6 @@ +bug52.scala:3: type mismatch; + found : scala.Any + required: scala.Int + val y: Int = x(2); + ^ +one error found diff --git a/test/files/neg/bug52.scala b/test/files/neg/bug52.scala new file mode 100644 index 0000000000..e171022eb6 --- /dev/null +++ b/test/files/neg/bug52.scala @@ -0,0 +1,4 @@ +object test { + val x = if (2 == 3) (x: Int => 0) else (x: Int => ""); + val y: Int = x(2); +} diff --git a/test/files/neg/refine.check b/test/files/neg/refine.check new file mode 100644 index 0000000000..38d961bb34 --- /dev/null +++ b/test/files/neg/refine.check @@ -0,0 +1,9 @@ +refine.scala:3: method t overrides nothing + val x: Object { def t(): String } = new Object { + ^ +refine.scala:3: type mismatch; + found : scala.Object + required: scala.Object { def t(): java.lang.String } + val x: Object { def t(): String } = new Object { + ^ +two errors found diff --git a/test/files/pos/bug30.scala b/test/files/pos/bug30.scala new file mode 100644 index 0000000000..6d28e18c0d --- /dev/null +++ b/test/files/pos/bug30.scala @@ -0,0 +1,9 @@ +trait A { + def f(x: int): unit; + def f(x: String): unit; +} + +class B extends A { + def f(x: int): unit = (); + def f(x: String): unit = (); +} diff --git a/test/files/pos/bug31.scala b/test/files/pos/bug31.scala new file mode 100644 index 0000000000..607dd4ce4f --- /dev/null +++ b/test/files/pos/bug31.scala @@ -0,0 +1,29 @@ +object Main { + + trait Ensure[a] { + def ensure(postcondition: a => Boolean): a + } + + def require[a](def precondition: Boolean)(def command: a): Ensure[a] = + if (precondition) + new Ensure[a] { + def ensure(postcondition: a => Boolean): a = { + val result = command; + if (postcondition(result)) result + else error("Assertion error") + } + } + else + error("Assertion error"); + + def arb[a](s: List[a]) = + require (! s.isEmpty) { + s.head + } ensure (result => s contains result); + + def main(args: Array[String]) = { + val s = List(1, 2); + System.out.println(arb(s)) + } + +} diff --git a/test/files/pos/bug36.scala b/test/files/pos/bug36.scala new file mode 100644 index 0000000000..1d923b0017 --- /dev/null +++ b/test/files/pos/bug36.scala @@ -0,0 +1,8 @@ +object m { + + val xs: List[int] = Nil; + def f(i: int) = 0; + val v = xs map f; + + def m() = {} +} diff --git a/test/files/pos/bug39.scala b/test/files/pos/bug39.scala new file mode 100644 index 0000000000..a131bc0450 --- /dev/null +++ b/test/files/pos/bug39.scala @@ -0,0 +1,6 @@ +abstract class Extensible[A, This <: Extensible[A, This]](x: A, xs: This): This { + def mkObj(x: A, xs: This): This; +} +class Fixed[A](x: A, xs: Fixed[A]) extends Extensible[A, Fixed[A]](x, xs) { + def mkObj(x: A, xs: Fixed[A]) = new Fixed(x, xs); +} diff --git a/test/files/pos/refine.scala b/test/files/pos/refine.scala new file mode 100644 index 0000000000..255621ad43 --- /dev/null +++ b/test/files/pos/refine.scala @@ -0,0 +1,6 @@ +object test { + + val x: Object { def toString(): String } = new Object { + override def toString(): String = "1"; + } +} diff --git a/test/files/pos/seqtest2.scala b/test/files/pos/seqtest2.scala new file mode 100644 index 0000000000..903b270c95 --- /dev/null +++ b/test/files/pos/seqtest2.scala @@ -0,0 +1,13 @@ +object test { + + val b = List(1, 2, 3); + + def main(args: Array[String]) = + System.out.println( + b match { + case List(1, 2, 3) => true; + case _ => false; + } + ) + +} diff --git a/test/neg/bug52.check b/test/neg/bug52.check new file mode 100644 index 0000000000..cd4b5eccce --- /dev/null +++ b/test/neg/bug52.check @@ -0,0 +1,6 @@ +bug52.scala:3: type mismatch; + found : scala.Any + required: scala.Int + val y: Int = x(2); + ^ +one error found diff --git a/test/neg/bug52.scala b/test/neg/bug52.scala new file mode 100644 index 0000000000..e171022eb6 --- /dev/null +++ b/test/neg/bug52.scala @@ -0,0 +1,4 @@ +object test { + val x = if (2 == 3) (x: Int => 0) else (x: Int => ""); + val y: Int = x(2); +} diff --git a/test/neg/refine.check b/test/neg/refine.check new file mode 100644 index 0000000000..38d961bb34 --- /dev/null +++ b/test/neg/refine.check @@ -0,0 +1,9 @@ +refine.scala:3: method t overrides nothing + val x: Object { def t(): String } = new Object { + ^ +refine.scala:3: type mismatch; + found : scala.Object + required: scala.Object { def t(): java.lang.String } + val x: Object { def t(): String } = new Object { + ^ +two errors found diff --git a/test/pos/bug30.scala b/test/pos/bug30.scala new file mode 100644 index 0000000000..6d28e18c0d --- /dev/null +++ b/test/pos/bug30.scala @@ -0,0 +1,9 @@ +trait A { + def f(x: int): unit; + def f(x: String): unit; +} + +class B extends A { + def f(x: int): unit = (); + def f(x: String): unit = (); +} diff --git a/test/pos/bug31.scala b/test/pos/bug31.scala new file mode 100644 index 0000000000..607dd4ce4f --- /dev/null +++ b/test/pos/bug31.scala @@ -0,0 +1,29 @@ +object Main { + + trait Ensure[a] { + def ensure(postcondition: a => Boolean): a + } + + def require[a](def precondition: Boolean)(def command: a): Ensure[a] = + if (precondition) + new Ensure[a] { + def ensure(postcondition: a => Boolean): a = { + val result = command; + if (postcondition(result)) result + else error("Assertion error") + } + } + else + error("Assertion error"); + + def arb[a](s: List[a]) = + require (! s.isEmpty) { + s.head + } ensure (result => s contains result); + + def main(args: Array[String]) = { + val s = List(1, 2); + System.out.println(arb(s)) + } + +} diff --git a/test/pos/bug36.scala b/test/pos/bug36.scala new file mode 100644 index 0000000000..1d923b0017 --- /dev/null +++ b/test/pos/bug36.scala @@ -0,0 +1,8 @@ +object m { + + val xs: List[int] = Nil; + def f(i: int) = 0; + val v = xs map f; + + def m() = {} +} diff --git a/test/pos/bug39.scala b/test/pos/bug39.scala new file mode 100644 index 0000000000..a131bc0450 --- /dev/null +++ b/test/pos/bug39.scala @@ -0,0 +1,6 @@ +abstract class Extensible[A, This <: Extensible[A, This]](x: A, xs: This): This { + def mkObj(x: A, xs: This): This; +} +class Fixed[A](x: A, xs: Fixed[A]) extends Extensible[A, Fixed[A]](x, xs) { + def mkObj(x: A, xs: Fixed[A]) = new Fixed(x, xs); +} diff --git a/test/pos/refine.scala b/test/pos/refine.scala new file mode 100644 index 0000000000..255621ad43 --- /dev/null +++ b/test/pos/refine.scala @@ -0,0 +1,6 @@ +object test { + + val x: Object { def toString(): String } = new Object { + override def toString(): String = "1"; + } +} diff --git a/test/pos/seqtest2.scala b/test/pos/seqtest2.scala new file mode 100644 index 0000000000..903b270c95 --- /dev/null +++ b/test/pos/seqtest2.scala @@ -0,0 +1,13 @@ +object test { + + val b = List(1, 2, 3); + + def main(args: Array[String]) = + System.out.println( + b match { + case List(1, 2, 3) => true; + case _ => false; + } + ) + +} |