From fbb13630d3c1dc9b8fdc503538d4ace5873f31c9 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 26 Apr 2013 13:30:59 -0700 Subject: Refactor DirectTest so java can be tested. There was no way to make a java compilation unit. Now there is. --- test/files/run/t5527.check | 2 +- test/files/run/t5603.check | 2 +- test/files/run/t6028.check | 2 +- test/files/run/t6288.check | 2 +- test/files/run/t6440.check | 2 +- test/files/run/t6555.check | 2 +- test/files/run/typetags_without_scala_reflect_typetag_lookup.check | 2 +- .../run/typetags_without_scala_reflect_typetag_manifest_interop.check | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/test/files/run/t5527.check b/test/files/run/t5527.check index 1518168c51..36bee9bb55 100644 --- a/test/files/run/t5527.check +++ b/test/files/run/t5527.check @@ -1,4 +1,4 @@ -[[syntax trees at end of parser]] // newSource1 +[[syntax trees at end of parser]] // newSource1.scala package { object UselessComments extends scala.AnyRef { def () = { diff --git a/test/files/run/t5603.check b/test/files/run/t5603.check index 5127d3c1c7..3f19a0a4b1 100644 --- a/test/files/run/t5603.check +++ b/test/files/run/t5603.check @@ -1,4 +1,4 @@ -[[syntax trees at end of parser]] // newSource1 +[[syntax trees at end of parser]] // newSource1.scala [0:241]package [0:0] { [0:82]abstract trait Greeting extends [15:82][83]scala.AnyRef { [15]def $init$() = [15]{ diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check index 94013efd36..613d25b075 100644 --- a/test/files/run/t6028.check +++ b/test/files/run/t6028.check @@ -1,4 +1,4 @@ -[[syntax trees at end of lambdalift]] // newSource1 +[[syntax trees at end of lambdalift]] // newSource1.scala package { class T extends Object { val T$$classParam: Int = _; diff --git a/test/files/run/t6288.check b/test/files/run/t6288.check index e6467edc95..e940975e44 100644 --- a/test/files/run/t6288.check +++ b/test/files/run/t6288.check @@ -1,4 +1,4 @@ -[[syntax trees at end of patmat]] // newSource1 +[[syntax trees at end of patmat]] // newSource1.scala [7]package [7] { [7]object Case3 extends [13][106]scala.AnyRef { [13]def (): [13]Case3.type = [13]{ diff --git a/test/files/run/t6440.check b/test/files/run/t6440.check index 69c253eab4..806279fb74 100644 --- a/test/files/run/t6440.check +++ b/test/files/run/t6440.check @@ -1,4 +1,4 @@ -pos: source-newSource1,line-9,offset=109 bad symbolic reference. A signature in U.class refers to term pack1 +pos: source-newSource1.scala,line-9,offset=109 bad symbolic reference. A signature in U.class refers to term pack1 in package which is not available. It may be completely missing from the current classpath, or the version on the classpath might be incompatible with the version used when compiling U.class. ERROR diff --git a/test/files/run/t6555.check b/test/files/run/t6555.check index 04117b7c2f..a18a8e8023 100644 --- a/test/files/run/t6555.check +++ b/test/files/run/t6555.check @@ -1,4 +1,4 @@ -[[syntax trees at end of specialize]] // newSource1 +[[syntax trees at end of specialize]] // newSource1.scala package { class Foo extends Object { def (): Foo = { diff --git a/test/files/run/typetags_without_scala_reflect_typetag_lookup.check b/test/files/run/typetags_without_scala_reflect_typetag_lookup.check index 8c558ced60..84e5435afe 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_lookup.check +++ b/test/files/run/typetags_without_scala_reflect_typetag_lookup.check @@ -1,2 +1,2 @@ -pos: source-newSource1,line-9,offset=466 could not find implicit value for evidence parameter of type reflect.runtime.package.universe.TypeTag[Int] ERROR +pos: source-newSource1.scala,line-9,offset=466 could not find implicit value for evidence parameter of type reflect.runtime.package.universe.TypeTag[Int] ERROR diff --git a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check index acfecce628..8c9d07d836 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check +++ b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check @@ -1,2 +1,2 @@ -pos: source-newSource1,line-9,offset=479 No Manifest available for App.this.T. ERROR +pos: source-newSource1.scala,line-9,offset=479 No Manifest available for App.this.T. ERROR -- cgit v1.2.3 From b2c67b328daeaf51eacdb0333db85a7287b5fe1f Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 26 Apr 2013 13:31:48 -0700 Subject: SI-7398 Add support for java8 default methods In classfile parser: mark symbols which represent interface methods yet have code attributes with new flag DEFAULTMETHOD. These must be kept distinct from regular method bodies so that an error can be issued when a regular concrete method is overridden without the override keyword, but not when the overridden method is a default. In java source parser: mark Modifiers of interface default methods with DEFAULTMETHOD flag. Writing the test was everything I dreamed, and more! However, % test/partest --debug test/files/run/t7398.scala Skipping java8-specific test under java version 1.7.0_21 testing: [...]/files/run/t7398.scala [ OK ] All of 1 tests were successful (elapsed time: 00:00:04) % test/partest --debug test/files/run/t7398.scala Attempting java8-specific test under java version 1.8.0-ea testing: [...]/files/run/t7398.scala [ OK ] All of 1 tests were successful (elapsed time: 00:00:13) --- bincompat-forward.whitelist.conf | 4 +++ .../scala/tools/nsc/javac/JavaParsers.scala | 6 ++++- .../nsc/symtab/classfile/ClassfileParser.scala | 6 +++++ .../scala/tools/nsc/typechecker/RefChecks.scala | 2 +- src/reflect/scala/reflect/internal/Flags.scala | 12 +++++---- test/files/run/t7398.scala | 31 ++++++++++++++++++++++ 6 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 test/files/run/t7398.scala (limited to 'test') diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 82f094bed7..88eabd4f8c 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -426,6 +426,10 @@ filter { { matchName="scala.reflect.internal.TreeInfo.effectivePatternArity" problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ModifierFlags.DEFAULTMETHOD" + problemName=MissingMethodProblem } ] } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 8aa9b81a72..0779e648cd 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -420,6 +420,9 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { case FINAL => flags |= Flags.FINAL in.nextToken + case DEFAULT => + flags |= Flags.DEFAULTMETHOD + in.nextToken() case NATIVE => addAnnot(NativeAttr) in.nextToken @@ -544,8 +547,9 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val vparams = formalParams() if (!isVoid) rtpt = optArrayBrackets(rtpt) optThrows() + val bodyOk = !inInterface || (mods hasFlag Flags.DEFAULTMETHOD) val body = - if (!inInterface && in.token == LBRACE) { + if (bodyOk && in.token == LBRACE) { methodBody() } else { if (parentToken == AT && in.token == DEFAULT) { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index fb2301de65..0ae2b501f0 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -931,6 +931,12 @@ abstract class ClassfileParser { case pkg => pkg.fullName(File.separatorChar)+File.separator+srcfileLeaf } srcfile0 = settings.outputDirs.srcFilesFor(in.file, srcpath).find(_.exists) + case tpnme.CodeATTR => + if (sym.owner.isInterface) { + sym setFlag DEFAULTMETHOD + log(s"$sym in ${sym.owner} is a java8+ default method.") + } + in.skip(attrLen) case _ => in.skip(attrLen) } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 7f8aeceeec..396a2716d2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -383,7 +383,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans overrideError("cannot be used here - classes can only override abstract types"); } else if (other.isEffectivelyFinal) { // (1.2) overrideError("cannot override final member"); - } else if (!other.isDeferred && !member.isAnyOverride && !member.isSynthetic) { // (*) + } else if (!other.isDeferred && !other.hasFlag(DEFAULTMETHOD) && !member.isAnyOverride && !member.isSynthetic) { // (*) // (*) Synthetic exclusion for (at least) default getters, fixes SI-5178. We cannot assign the OVERRIDE flag to // the default getter: one default getter might sometimes override, sometimes not. Example in comment on ticket. if (isNeitherInClass && !(other.owner isSubClass member.owner)) diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index 86cbba9c50..5ebe02d95d 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -59,9 +59,9 @@ import scala.collection.{ mutable, immutable } // 42: VBRIDGE // 43: VARARGS // 44: TRIEDCOOKING -// 45: -// 46: -// 47: +// 45: SYNCHRONIZED/M +// 46: ARTIFACT +// 47: DEFAULTMETHOD/M // 48: // 49: // 50: @@ -116,6 +116,8 @@ class ModifierFlags { final val LAZY = 1L << 31 // symbol is a lazy val. can't have MUTABLE unless transformed by typer final val PRESUPER = 1L << 37 // value is evaluated before super call final val DEFAULTINIT = 1L << 41 // symbol is initialized to the default value: used by -Xcheckinit + // ARTIFACT at #46 in 2.11+ + final val DEFAULTMETHOD = 1L << 47 // symbol is a java default method // Overridden. def flagToString(flag: Long): String = "" @@ -239,7 +241,7 @@ class Flags extends ModifierFlags { */ final val ExplicitFlags = PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED | - OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE | LAZY + OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE | LAZY | DEFAULTMETHOD /** The two bridge flags */ final val BridgeFlags = BRIDGE | VBRIDGE @@ -421,7 +423,7 @@ class Flags extends ModifierFlags { case TRIEDCOOKING => "" // (1L << 44) case SYNCHRONIZED => "" // (1L << 45) case 0x400000000000L => "" // (1L << 46) - case 0x800000000000L => "" // (1L << 47) + case DEFAULTMETHOD => "" // (1L << 47) case 0x1000000000000L => "" // (1L << 48) case 0x2000000000000L => "" // (1L << 49) case 0x4000000000000L => "" // (1L << 50) diff --git a/test/files/run/t7398.scala b/test/files/run/t7398.scala new file mode 100644 index 0000000000..e4090f7db3 --- /dev/null +++ b/test/files/run/t7398.scala @@ -0,0 +1,31 @@ +import scala.tools.partest._ + +object Test extends CompilerTest { + import global._ + + def javaVersion = scala.util.Properties.javaVersion + def isJavaEight = javaVersion startsWith "1.8" + // This way we auto-pass on non-java8 since there's nothing to check + override lazy val units = { + val res: List[CompilationUnit] = if (isJavaEight) javaCompilationUnits(global)(defaultMethodSource) else Nil + val word = if (isJavaEight) "Attempting" else "Skipping" + log(s"$word java8-specific test under java version $javaVersion") + res + } + + private def defaultMethodSource = """ +public interface Iterator { + boolean hasNext(); + E next(); + default void remove() { + throw new UnsupportedOperationException("remove"); + } + default void forEachRemaining(Consumer action) { + throw new UnsupportedOperationException("forEachRemaining"); + } +} + """ + + // We're only checking we can parse it. + def check(source: String, unit: global.CompilationUnit): Unit = () +} -- cgit v1.2.3