summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bincompat-backward.whitelist.conf26
-rw-r--r--project/plugins.sbt2
-rw-r--r--spec/04-basic-declarations-and-definitions.md6
-rw-r--r--spec/12-the-scala-standard-library.md4
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala61
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaScanners.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala60
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala9
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--test/files/neg/t0903.check1
-rw-r--r--test/files/neg/t1215.check1
-rw-r--r--test/files/neg/t3236-neg.check34
-rw-r--r--test/files/neg/t3236-neg/AnnotationTest.scala17
-rw-r--r--test/files/neg/t3236-neg/BooleanAnnotation.java7
-rw-r--r--test/files/neg/t3236-neg/Constants.java25
-rw-r--r--test/files/neg/t3236-neg/IntAnnotation.java7
-rw-r--r--test/files/neg/t3236-neg/ShortAnnotation.java7
-rw-r--r--test/files/neg/t3236-neg/StringAnnotation.java7
-rw-r--r--test/files/neg/t8763.check6
-rw-r--r--test/files/neg/t8763.scala11
-rw-r--r--test/files/neg/t9834.check9
-rw-r--r--test/files/neg/t9834.scala6
-rw-r--r--test/files/run/t3236/AnnotationTest.scala33
-rw-r--r--test/files/run/t3236/BooleanAnnotation.java7
-rw-r--r--test/files/run/t3236/ByteAnnotation.java7
-rw-r--r--test/files/run/t3236/CharAnnotation.java7
-rw-r--r--test/files/run/t3236/Constants.java34
-rw-r--r--test/files/run/t3236/DoubleAnnotation.java7
-rw-r--r--test/files/run/t3236/FloatAnnotation.java7
-rw-r--r--test/files/run/t3236/IntAnnotation.java7
-rw-r--r--test/files/run/t3236/LongAnnotation.java7
-rw-r--r--test/files/run/t3236/ShortAnnotation.java7
-rw-r--r--test/files/run/t3236/StringAnnotation.java7
-rw-r--r--test/files/run/t3236/Test.scala44
-rw-r--r--test/junit/scala/collection/immutable/RangeConsistencyTest.scala39
-rw-r--r--test/junit/scala/tools/testing/AssertUtil.scala9
36 files changed, 474 insertions, 58 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf
index 01777bc4ed..d4db9962e7 100644
--- a/bincompat-backward.whitelist.conf
+++ b/bincompat-backward.whitelist.conf
@@ -32,32 +32,6 @@ filter {
{
matchName="scala.sys.process.ProcessImpl#CompoundProcess.getExitValue"
problemName=DirectMissingMethodProblem
- },
- # these next seven can be removed once there is a fix for
- # https://github.com/typesafehub/migration-manager/issues/147
- {
- matchName="scala.collection.Iterator#Leading#1.hd_="
- problemName=DirectMissingMethodProblem
- },
- {
- matchName="scala.collection.Iterator#Leading#1.hd"
- problemName=DirectMissingMethodProblem
- },
- {
- matchName="scala.collection.Iterator#Leading#1.status_="
- problemName=DirectMissingMethodProblem
- },
- {
- matchName="scala.collection.Iterator#Leading#1.lookahead_="
- problemName=DirectMissingMethodProblem
- },
- {
- matchName="scala.collection.Iterator#Leading#1.status"
- problemName=DirectMissingMethodProblem
- },
- {
- matchName="scala.collection.Iterator#Leading#1.lookahead"
- problemName=DirectMissingMethodProblem
}
]
}
diff --git a/project/plugins.sbt b/project/plugins.sbt
index d2476d9207..80aef2c591 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -19,4 +19,4 @@ buildInfoKeys := Seq[BuildInfoKey](buildClasspath)
buildInfoPackage := "scalabuild"
-libraryDependencies += "com.typesafe" %% "mima-reporter" % "0.1.12"
+libraryDependencies += "com.typesafe" %% "mima-reporter" % "0.1.13"
diff --git a/spec/04-basic-declarations-and-definitions.md b/spec/04-basic-declarations-and-definitions.md
index 49ca80b124..53b34dedc5 100644
--- a/spec/04-basic-declarations-and-definitions.md
+++ b/spec/04-basic-declarations-and-definitions.md
@@ -404,7 +404,7 @@ function definitions. In this section we consider only type parameter
definitions with lower bounds `>: $L$` and upper bounds
`<: $U$` whereas a discussion of context bounds
`: $U$` and view bounds `<% $U$`
-is deferred to [here](07-implicit-parameters-and-views.html#context-bounds-and-view-bounds).
+is deferred to [here](07-implicits.html#context-bounds-and-view-bounds).
The most general form of a first-order type parameter is
`$@a_1 \ldots @a_n$ $\pm$ $t$ >: $L$ <: $U$`.
@@ -587,7 +587,7 @@ FunDef ::= FunSig [‘:’ Type] ‘=’ Expr
FunSig ::= id [FunTypeParamClause] ParamClauses
FunTypeParamClause ::= ‘[’ TypeParam {‘,’ TypeParam} ‘]’
ParamClauses ::= {ParamClause} [[nl] ‘(’ ‘implicit’ Params ‘)’]
-ParamClause ::= [nl] ‘(’ [Params] ‘)’}
+ParamClause ::= [nl] ‘(’ [Params] ‘)’
Params ::= Param {‘,’ Param}
Param ::= {Annotation} id [‘:’ ParamType] [‘=’ Expr]
ParamType ::= Type
@@ -686,7 +686,7 @@ The by-name modifier is disallowed for parameters of classes that
carry a `val` or `var` prefix, including parameters of case
classes for which a `val` prefix is implicitly generated. The
by-name modifier is also disallowed for
-[implicit parameters](07-implicit-parameters-and-views.html#implicit-parameters).
+[implicit parameters](07-implicits.html#implicit-parameters).
###### Example
The declaration
diff --git a/spec/12-the-scala-standard-library.md b/spec/12-the-scala-standard-library.md
index a1d4516a1f..e885dc7fb2 100644
--- a/spec/12-the-scala-standard-library.md
+++ b/spec/12-the-scala-standard-library.md
@@ -141,7 +141,7 @@ Byte - Short
whereas `Double` is the highest-ranked. Ranking does _not_
imply a [conformance relationship](03-types.html#conformance); for
instance `Int` is not a subtype of `Long`. However, object
-[`Predef`](#the-predef-object) defines [views](07-implicit-parameters-and-views.html#views)
+[`Predef`](#the-predef-object) defines [views](07-implicits.html#views)
from every numeric value type to all higher-ranked numeric value types.
Therefore, lower-ranked types are implicitly converted to higher-ranked types
when required by the [context](06-expressions.html#implicit-conversions).
@@ -467,7 +467,7 @@ val ys: Array[Object] = xs.asInstanceOf[Array[Object]] // OK
The instantiation of an array with a polymorphic element type $T$ requires
information about type $T$ at runtime.
-This information is synthesized by adding a [context bound](07-implicit-parameters-and-views.html#context-bounds-and-view-bounds)
+This information is synthesized by adding a [context bound](07-implicits.html#context-bounds-and-view-bounds)
of `scala.reflect.ClassTag` to type $T$.
An example is the
following implementation of method `mkArray`, which creates
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index e4bc055da4..947af55724 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -572,10 +572,48 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName): ValDef = {
val tpt1 = optArrayBrackets(tpt)
- if (in.token == EQUALS && !mods.isParameter) skipTo(COMMA, SEMI)
+
+ /** Tries to detect final static literals syntactically and returns a constant type replacement */
+ def optConstantTpe(): Tree = {
+ def constantTpe(const: Constant): Tree = TypeTree(ConstantType(const))
+
+ def forConst(const: Constant): Tree = {
+ if (in.token != SEMI) tpt1
+ else {
+ def isStringTyped = tpt1 match {
+ case Ident(TypeName("String")) => true
+ case _ => false
+ }
+ if (const.tag == StringTag && isStringTyped) constantTpe(const)
+ else if (tpt1.tpe != null && (const.tag == BooleanTag || const.isNumeric)) {
+ // for example, literal 'a' is ok for float. 127 is ok for byte, but 128 is not.
+ val converted = const.convertTo(tpt1.tpe)
+ if (converted == null) tpt1
+ else constantTpe(converted)
+ } else tpt1
+ }
+ }
+
+ in.nextToken() // EQUALS
+ if (mods.hasFlag(Flags.STATIC) && mods.isFinal) {
+ val neg = in.token match {
+ case MINUS | BANG => in.nextToken(); true
+ case _ => false
+ }
+ tryLiteral(neg).map(forConst).getOrElse(tpt1)
+ } else tpt1
+ }
+
+ val tpt2: Tree =
+ if (in.token == EQUALS && !mods.isParameter) {
+ val res = optConstantTpe()
+ skipTo(COMMA, SEMI)
+ res
+ } else tpt1
+
val mods1 = if (mods.isFinal) mods &~ Flags.FINAL else mods | Flags.MUTABLE
atPos(pos) {
- ValDef(mods1, name, tpt1, blankExpr)
+ ValDef(mods1, name, tpt2, blankExpr)
}
}
@@ -831,6 +869,25 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
case _ => in.nextToken(); syntaxError("illegal start of type declaration", skipIt = true); List(errorTypeTree)
}
+ def tryLiteral(negate: Boolean = false): Option[Constant] = {
+ val l = in.token match {
+ case TRUE => !negate
+ case FALSE => negate
+ case CHARLIT => in.name.charAt(0)
+ case INTLIT => in.intVal(negate).toInt
+ case LONGLIT => in.intVal(negate)
+ case FLOATLIT => in.floatVal(negate).toFloat
+ case DOUBLELIT => in.floatVal(negate)
+ case STRINGLIT => in.name.toString
+ case _ => null
+ }
+ if (l == null) None
+ else {
+ in.nextToken()
+ Some(Constant(l))
+ }
+ }
+
/** CompilationUnit ::= [package QualId semi] TopStatSeq
*/
def compilationUnit(): Tree = {
diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
index f77e53c54b..af9b63c8ae 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
@@ -89,6 +89,7 @@ trait JavaScanners extends ast.parser.ScannersCommon {
javanme.ELSEkw -> ELSE,
javanme.ENUMkw -> ENUM,
javanme.EXTENDSkw -> EXTENDS,
+ javanme.FALSEkw -> FALSE,
javanme.FINALkw -> FINAL,
javanme.FINALLYkw -> FINALLY,
javanme.FLOATkw -> FLOAT,
@@ -118,6 +119,7 @@ trait JavaScanners extends ast.parser.ScannersCommon {
javanme.THROWkw -> THROW,
javanme.THROWSkw -> THROWS,
javanme.TRANSIENTkw -> TRANSIENT,
+ javanme.TRUEkw -> TRUE,
javanme.TRYkw -> TRY,
javanme.VOIDkw -> VOID,
javanme.VOLATILEkw -> VOLATILE,
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e017c7d864..58a44d3ac0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4624,22 +4624,55 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val appStart = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null
val opeqStart = if (Statistics.canEnable) Statistics.startTimer(failedOpEqNanos) else null
- def onError(reportError: => Tree): Tree = fun match {
- case Select(qual, name)
- if !mode.inPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) && !qual.exists(_.isErroneous) =>
+ def isConversionCandidate(qual: Tree, name: Name): Boolean =
+ !mode.inPatternMode && nme.isOpAssignmentName(TermName(name.decode)) && !qual.exists(_.isErroneous)
+ def reportError(error: SilentTypeError): Tree = {
+ error.reportableErrors foreach context.issue
+ error.warnings foreach { case (p, m) => context.warning(p, m) }
+ args foreach (arg => typed(arg, mode, ErrorType))
+ setError(tree)
+ }
+ def advice1(convo: Tree, errors: List[AbsTypeError], err: SilentTypeError): List[AbsTypeError] =
+ errors.map { e =>
+ if (e.errPos == tree.pos) {
+ val header = f"${e.errMsg}%n Expression does not convert to assignment because:%n "
+ val expansion = f"%n expansion: ${show(convo)}"
+ NormalTypeError(tree, err.errors.flatMap(_.errMsg.lines.toList).mkString(header, f"%n ", expansion))
+ } else e
+ }
+ def advice2(errors: List[AbsTypeError]): List[AbsTypeError] =
+ errors.map { e =>
+ if (e.errPos == tree.pos) {
+ val msg = f"${e.errMsg}%n Expression does not convert to assignment because receiver is not assignable."
+ NormalTypeError(tree, msg)
+ } else e
+ }
+ def onError(error: SilentTypeError): Tree = fun match {
+ case Select(qual, name) if isConversionCandidate(qual, name) =>
val qual1 = typedQualifier(qual)
if (treeInfo.isVariableOrGetter(qual1)) {
if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart)
- convertToAssignment(fun, qual1, name, args)
+ val erred = qual1.isErroneous || args.exists(_.isErroneous)
+ if (erred) reportError(error) else {
+ val convo = convertToAssignment(fun, qual1, name, args)
+ silent(op = _.typed1(convo, mode, pt)) match {
+ case SilentResultValue(t) => t
+ case err: SilentTypeError => reportError(SilentTypeError(advice1(convo, error.errors, err), error.warnings))
+ }
+ }
}
else {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart)
- reportError
+ val Apply(Select(qual2, _), args2) = tree
+ val erred = qual2.isErroneous || args2.exists(_.isErroneous)
+ reportError {
+ if (erred) error else SilentTypeError(advice2(error.errors), error.warnings)
+ }
}
case _ =>
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart)
- reportError
+ reportError(error)
}
val silentResult = silent(
op = _.typed(fun, mode.forFunMode, funpt),
@@ -4664,13 +4697,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
tryTypedApply(fun2, args)
else
doTypedApply(tree, fun2, args, mode, pt)
- case err: SilentTypeError =>
- onError({
- err.reportableErrors foreach context.issue
- err.warnings foreach { case (p, m) => context.warning(p, m) }
- args foreach (arg => typed(arg, mode, ErrorType))
- setError(tree)
- })
+ case err: SilentTypeError => onError(err)
}
}
@@ -4713,7 +4740,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
Select(vble.duplicate, prefix) setPos fun.pos.focus, args) setPos tree.pos.makeTransparent
) setPos tree.pos
- def mkUpdate(table: Tree, indices: List[Tree]) = {
+ def mkUpdate(table: Tree, indices: List[Tree]) =
gen.evalOnceAll(table :: indices, context.owner, context.unit) {
case tab :: is =>
def mkCall(name: Name, extraArgs: Tree*) = (
@@ -4728,9 +4755,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
)
case _ => EmptyTree
}
- }
- val tree1 = qual match {
+ val assignment = qual match {
case Ident(_) =>
mkAssign(qual)
@@ -4746,7 +4772,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case _ => UnexpectedTreeAssignmentConversionError(qual)
}
}
- typed1(tree1, mode, pt)
+ assignment
}
def typedSuper(tree: Super) = {
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index ef3fa99971..f1b831bf75 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -114,13 +114,18 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
import NumericRange.defaultOrdering
override def min[T1 >: T](implicit ord: Ordering[T1]): T =
- if (ord eq defaultOrdering(num)) {
+ // We can take the fast path:
+ // - If the Integral of this NumericRange is also the requested Ordering
+ // (Integral <: Ordering). This can happen for custom Integral types.
+ // - The Ordering is the default Ordering of a well-known Integral type.
+ if ((ord eq num) || defaultOrdering.get(num).exists(ord eq _)) {
if (num.signum(step) > 0) head
else last
} else super.min(ord)
override def max[T1 >: T](implicit ord: Ordering[T1]): T =
- if (ord eq defaultOrdering(num)) {
+ // See comment for fast path in min().
+ if ((ord eq num) || defaultOrdering.get(num).exists(ord eq _)) {
if (num.signum(step) > 0) last
else head
} else super.max(ord)
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 2e820a68e0..15aa1a40fa 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -1110,6 +1110,7 @@ trait StdNames {
final val ELSEkw: TermName = kw("else")
final val ENUMkw: TermName = kw("enum")
final val EXTENDSkw: TermName = kw("extends")
+ final val FALSEkw: TermName = kw("false")
final val FINALkw: TermName = kw("final")
final val FINALLYkw: TermName = kw("finally")
final val FLOATkw: TermName = kw("float")
@@ -1139,6 +1140,7 @@ trait StdNames {
final val THROWkw: TermName = kw("throw")
final val THROWSkw: TermName = kw("throws")
final val TRANSIENTkw: TermName = kw("transient")
+ final val TRUEkw: TermName = kw("true")
final val TRYkw: TermName = kw("try")
final val VOIDkw: TermName = kw("void")
final val VOLATILEkw: TermName = kw("volatile")
diff --git a/test/files/neg/t0903.check b/test/files/neg/t0903.check
index 2dd05cd3ee..f9dc28bf16 100644
--- a/test/files/neg/t0903.check
+++ b/test/files/neg/t0903.check
@@ -1,4 +1,5 @@
t0903.scala:3: error: value += is not a member of Int
+ Expression does not convert to assignment because receiver is not assignable.
x += 1
^
t0903.scala:4: error: reassignment to val
diff --git a/test/files/neg/t1215.check b/test/files/neg/t1215.check
index 1f9dd6bf38..4cbd0d85f3 100644
--- a/test/files/neg/t1215.check
+++ b/test/files/neg/t1215.check
@@ -1,4 +1,5 @@
t1215.scala:2: error: value += is not a member of Int
+ Expression does not convert to assignment because receiver is not assignable.
val x = 1 += 1
^
one error found
diff --git a/test/files/neg/t3236-neg.check b/test/files/neg/t3236-neg.check
new file mode 100644
index 0000000000..ef28574d45
--- /dev/null
+++ b/test/files/neg/t3236-neg.check
@@ -0,0 +1,34 @@
+AnnotationTest.scala:3: error: annotation argument needs to be a constant; found: Constants.ConstIdent
+ @IntAnnotation(Constants.ConstIdent)
+ ^
+AnnotationTest.scala:4: error: annotation argument needs to be a constant; found: Constants.ConstSelect
+ @IntAnnotation(Constants.ConstSelect)
+ ^
+AnnotationTest.scala:6: error: annotation argument needs to be a constant; found: Constants.ConstOpExpr1
+ @IntAnnotation(Constants.ConstOpExpr1)
+ ^
+AnnotationTest.scala:7: error: annotation argument needs to be a constant; found: Constants.ConstOpExpr2
+ @IntAnnotation(Constants.ConstOpExpr2)
+ ^
+AnnotationTest.scala:8: error: annotation argument needs to be a constant; found: Constants.ConstOpExpr3
+ @BooleanAnnotation(Constants.ConstOpExpr3)
+ ^
+AnnotationTest.scala:9: error: annotation argument needs to be a constant; found: Constants.ConstOpExpr4
+ @IntAnnotation(Constants.ConstOpExpr4)
+ ^
+AnnotationTest.scala:10: error: annotation argument needs to be a constant; found: Constants.NonFinalConst
+ @IntAnnotation(Constants.NonFinalConst)
+ ^
+AnnotationTest.scala:11: error: value NonStaticConst is not a member of object Constants
+ @IntAnnotation(Constants.NonStaticConst)
+ ^
+AnnotationTest.scala:12: error: value NonConst is not a member of object Constants
+ @IntAnnotation(Constants.NonConst)
+ ^
+AnnotationTest.scala:13: error: annotation argument needs to be a constant; found: Constants.ConstCastExpr
+ @ShortAnnotation(Constants.ConstCastExpr)
+ ^
+AnnotationTest.scala:15: error: annotation argument needs to be a constant; found: Constants.StringAdd
+ @StringAnnotation(Constants.StringAdd)
+ ^
+11 errors found
diff --git a/test/files/neg/t3236-neg/AnnotationTest.scala b/test/files/neg/t3236-neg/AnnotationTest.scala
new file mode 100644
index 0000000000..aec2a99020
--- /dev/null
+++ b/test/files/neg/t3236-neg/AnnotationTest.scala
@@ -0,0 +1,17 @@
+trait AnnotationTest {
+ @IntAnnotation(Constants.ConstInt) // ok
+ @IntAnnotation(Constants.ConstIdent)
+ @IntAnnotation(Constants.ConstSelect)
+ @IntAnnotation(Constants.NegatedInt) // ok
+ @IntAnnotation(Constants.ConstOpExpr1)
+ @IntAnnotation(Constants.ConstOpExpr2)
+ @BooleanAnnotation(Constants.ConstOpExpr3)
+ @IntAnnotation(Constants.ConstOpExpr4)
+ @IntAnnotation(Constants.NonFinalConst)
+ @IntAnnotation(Constants.NonStaticConst)
+ @IntAnnotation(Constants.NonConst)
+ @ShortAnnotation(Constants.ConstCastExpr)
+ @StringAnnotation(Constants.ConstString) // ok
+ @StringAnnotation(Constants.StringAdd)
+ def test: Unit
+} \ No newline at end of file
diff --git a/test/files/neg/t3236-neg/BooleanAnnotation.java b/test/files/neg/t3236-neg/BooleanAnnotation.java
new file mode 100644
index 0000000000..7e57a5e0db
--- /dev/null
+++ b/test/files/neg/t3236-neg/BooleanAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface BooleanAnnotation {
+ boolean value();
+}
diff --git a/test/files/neg/t3236-neg/Constants.java b/test/files/neg/t3236-neg/Constants.java
new file mode 100644
index 0000000000..01d2d70dd7
--- /dev/null
+++ b/test/files/neg/t3236-neg/Constants.java
@@ -0,0 +1,25 @@
+// https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28
+public class Constants {
+ public static final int ConstInt = 1;
+
+ public static final int ConstIdent = ConstInt;
+ public static final int ConstSelect = Constants.ConstInt;
+
+ // this is a known limitation in scala's javac parser for constants, it will be treated as -1.
+ // the java compiler will flag an error.
+ public static final int NegatedInt = !1;
+
+ public static final int ConstOpExpr1 = 1 + 2;
+ public static final int ConstOpExpr2 = 1 << 2;
+ public static final boolean ConstOpExpr3 = 1 == 1;
+ public static final int ConstOpExpr4 = true ? 1 : 2;
+
+ public static int NonFinalConst = 1;
+ public final int NonStaticConst = 1;
+ public int NonConst = 1;
+
+ public static final short ConstCastExpr = (short)(1*2*3*4*5*6);
+
+ public static final String ConstString = "a";
+ public static final String StringAdd = "a" + 1;
+}
diff --git a/test/files/neg/t3236-neg/IntAnnotation.java b/test/files/neg/t3236-neg/IntAnnotation.java
new file mode 100644
index 0000000000..2ffad8890c
--- /dev/null
+++ b/test/files/neg/t3236-neg/IntAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IntAnnotation {
+ int value();
+}
diff --git a/test/files/neg/t3236-neg/ShortAnnotation.java b/test/files/neg/t3236-neg/ShortAnnotation.java
new file mode 100644
index 0000000000..f0a35892c7
--- /dev/null
+++ b/test/files/neg/t3236-neg/ShortAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ShortAnnotation {
+ short value();
+}
diff --git a/test/files/neg/t3236-neg/StringAnnotation.java b/test/files/neg/t3236-neg/StringAnnotation.java
new file mode 100644
index 0000000000..0fdc1ead38
--- /dev/null
+++ b/test/files/neg/t3236-neg/StringAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface StringAnnotation {
+ String value();
+}
diff --git a/test/files/neg/t8763.check b/test/files/neg/t8763.check
new file mode 100644
index 0000000000..4659e57be6
--- /dev/null
+++ b/test/files/neg/t8763.check
@@ -0,0 +1,6 @@
+t8763.scala:9: error: type mismatch;
+ found : Char
+ required: String
+ names_times(fields(0)) += fields(1).toLong
+ ^
+one error found
diff --git a/test/files/neg/t8763.scala b/test/files/neg/t8763.scala
new file mode 100644
index 0000000000..08ce1b471a
--- /dev/null
+++ b/test/files/neg/t8763.scala
@@ -0,0 +1,11 @@
+
+import collection.mutable
+
+object Foo {
+ def bar() {
+ val names_times = mutable.Map[String, mutable.Set[Long]]()
+ val line = ""
+ val Array(fields) = line.split("\t")
+ names_times(fields(0)) += fields(1).toLong
+ }
+}
diff --git a/test/files/neg/t9834.check b/test/files/neg/t9834.check
new file mode 100644
index 0000000000..d07eb7f155
--- /dev/null
+++ b/test/files/neg/t9834.check
@@ -0,0 +1,9 @@
+t9834.scala:5: error: value += is not a member of Int
+ Expression does not convert to assignment because:
+ type mismatch;
+ found : String
+ required: Int
+ expansion: x.update(x.apply().+("42"))
+ x() += "42"
+ ^
+one error found
diff --git a/test/files/neg/t9834.scala b/test/files/neg/t9834.scala
new file mode 100644
index 0000000000..1ecda7a2b8
--- /dev/null
+++ b/test/files/neg/t9834.scala
@@ -0,0 +1,6 @@
+
+object x { def apply() = 42 ; def update(i: Int) = () }
+
+trait Test {
+ x() += "42"
+}
diff --git a/test/files/run/t3236/AnnotationTest.scala b/test/files/run/t3236/AnnotationTest.scala
new file mode 100644
index 0000000000..c2f9ae7837
--- /dev/null
+++ b/test/files/run/t3236/AnnotationTest.scala
@@ -0,0 +1,33 @@
+trait AnnotationTest {
+ @BooleanAnnotation(Constants.BooleanTrue)
+ @ByteAnnotation(Constants.Byte)
+ @CharAnnotation(Constants.Char)
+ @ShortAnnotation(Constants.Short)
+ @IntAnnotation(Constants.Int)
+ @LongAnnotation(Constants.Long)
+ @FloatAnnotation(Constants.Float)
+ @DoubleAnnotation(Constants.Double)
+ @StringAnnotation(Constants.String)
+ def test1: Unit
+
+ @BooleanAnnotation(Constants.InvertedBoolean)
+ @ByteAnnotation(Constants.NegativeByte)
+ @ShortAnnotation(Constants.NegativeShort)
+ @IntAnnotation(Constants.NegativeInt)
+ @LongAnnotation(Constants.NegativeLong)
+ @FloatAnnotation(Constants.NegativeFloat)
+ @DoubleAnnotation(Constants.NegativeDouble)
+ @StringAnnotation(Constants.NegativeString)
+ def test2: Unit
+
+ @BooleanAnnotation(Constants.BooleanFalse)
+ @ByteAnnotation(Constants.LiteralCharAsByte)
+ @CharAnnotation(Constants.LiteralChar)
+ @ShortAnnotation(Constants.LiteralCharAsShort)
+ @IntAnnotation(Constants.LiteralCharAsInt)
+ @LongAnnotation(Constants.LiteralCharAsLong)
+ def test3: Unit
+
+ @LongAnnotation(Constants.LiteralIntAsLong)
+ def test4: Unit
+}
diff --git a/test/files/run/t3236/BooleanAnnotation.java b/test/files/run/t3236/BooleanAnnotation.java
new file mode 100644
index 0000000000..7e57a5e0db
--- /dev/null
+++ b/test/files/run/t3236/BooleanAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface BooleanAnnotation {
+ boolean value();
+}
diff --git a/test/files/run/t3236/ByteAnnotation.java b/test/files/run/t3236/ByteAnnotation.java
new file mode 100644
index 0000000000..c986fa5d27
--- /dev/null
+++ b/test/files/run/t3236/ByteAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ByteAnnotation {
+ byte value();
+}
diff --git a/test/files/run/t3236/CharAnnotation.java b/test/files/run/t3236/CharAnnotation.java
new file mode 100644
index 0000000000..1715f1b7de
--- /dev/null
+++ b/test/files/run/t3236/CharAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CharAnnotation {
+ char value();
+}
diff --git a/test/files/run/t3236/Constants.java b/test/files/run/t3236/Constants.java
new file mode 100644
index 0000000000..16b4001f76
--- /dev/null
+++ b/test/files/run/t3236/Constants.java
@@ -0,0 +1,34 @@
+public class Constants {
+ public static final boolean BooleanTrue = true;
+ public static final boolean BooleanFalse = false;
+ public static final boolean InvertedBoolean = !true;
+
+ public static final byte Byte = 23;
+ public static final byte NegativeByte = -42;
+ public static final byte LiteralCharAsByte = 'a';
+
+ public static final char Char = 33;
+ public static final char LiteralChar = 'b';
+
+ public static final short Short = 0x1234;
+ public static final short NegativeShort= -0x5678;
+ public static final short LiteralCharAsShort = 'c';
+
+ public static final int Int = 0xabcdef;
+ public static final int NegativeInt = -12345678;
+ public static final int LiteralCharAsInt = 'd';
+
+ public static final long Long = 0x1234567890abcdefL;
+ public static final long NegativeLong = -0xfedcba09876L;
+ public static final long LiteralCharAsLong = 'e';
+ public static final long LiteralIntAsLong = 0x12345678;
+
+ public static final float Float = 42.232323f;
+ public static final float NegativeFloat = -3.1415f;
+
+ public static final double Double = 23.4243598374594d;
+ public static final double NegativeDouble = -42.2324358934589734859d;
+
+ public static final String String = "testConstant";
+ public static final String NegativeString = "!#!$!grml%!%!$#@@@";
+}
diff --git a/test/files/run/t3236/DoubleAnnotation.java b/test/files/run/t3236/DoubleAnnotation.java
new file mode 100644
index 0000000000..1eb8223f4e
--- /dev/null
+++ b/test/files/run/t3236/DoubleAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DoubleAnnotation {
+ double value();
+}
diff --git a/test/files/run/t3236/FloatAnnotation.java b/test/files/run/t3236/FloatAnnotation.java
new file mode 100644
index 0000000000..c723a25fad
--- /dev/null
+++ b/test/files/run/t3236/FloatAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FloatAnnotation {
+ float value();
+}
diff --git a/test/files/run/t3236/IntAnnotation.java b/test/files/run/t3236/IntAnnotation.java
new file mode 100644
index 0000000000..2ffad8890c
--- /dev/null
+++ b/test/files/run/t3236/IntAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IntAnnotation {
+ int value();
+}
diff --git a/test/files/run/t3236/LongAnnotation.java b/test/files/run/t3236/LongAnnotation.java
new file mode 100644
index 0000000000..9f80b41398
--- /dev/null
+++ b/test/files/run/t3236/LongAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LongAnnotation {
+ long value();
+}
diff --git a/test/files/run/t3236/ShortAnnotation.java b/test/files/run/t3236/ShortAnnotation.java
new file mode 100644
index 0000000000..f0a35892c7
--- /dev/null
+++ b/test/files/run/t3236/ShortAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ShortAnnotation {
+ short value();
+}
diff --git a/test/files/run/t3236/StringAnnotation.java b/test/files/run/t3236/StringAnnotation.java
new file mode 100644
index 0000000000..0fdc1ead38
--- /dev/null
+++ b/test/files/run/t3236/StringAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface StringAnnotation {
+ String value();
+}
diff --git a/test/files/run/t3236/Test.scala b/test/files/run/t3236/Test.scala
new file mode 100644
index 0000000000..7e351e0b6b
--- /dev/null
+++ b/test/files/run/t3236/Test.scala
@@ -0,0 +1,44 @@
+import scala.language.reflectiveCalls
+
+object Test extends App {
+ val theClass = classOf[AnnotationTest]
+
+ def annotation[T <: java.lang.annotation.Annotation](annotationClass: Class[T], methodName: String): T =
+ theClass.getDeclaredMethod(methodName)
+ .getAnnotation[T](annotationClass)
+
+ def check[T, U <: java.lang.annotation.Annotation { def value(): T } ](annotationClass: Class[U], methodName: String, expected: T): Unit = {
+ val a = annotation(annotationClass, methodName)
+ assert(a != null, s"No annotation of type $annotationClass found on method $methodName")
+ assert(a.value() == expected, s"Actual value of annotation $a on $methodName was not of expected value $expected")
+ }
+
+ check(classOf[BooleanAnnotation], "test1", Constants.BooleanTrue)
+ check(classOf[ByteAnnotation], "test1", Constants.Byte)
+ check(classOf[CharAnnotation], "test1", Constants.Char)
+ check(classOf[ShortAnnotation], "test1", Constants.Short)
+ check(classOf[IntAnnotation], "test1", Constants.Int)
+ check(classOf[LongAnnotation], "test1", Constants.Long)
+ check(classOf[FloatAnnotation], "test1", Constants.Float)
+ check(classOf[DoubleAnnotation], "test1", Constants.Double)
+ check(classOf[StringAnnotation], "test1", Constants.String)
+
+ check(classOf[BooleanAnnotation], "test2", Constants.InvertedBoolean)
+ check(classOf[ByteAnnotation], "test2", Constants.NegativeByte)
+ // no negative char possible
+ check(classOf[ShortAnnotation], "test2", Constants.NegativeShort)
+ check(classOf[IntAnnotation], "test2", Constants.NegativeInt)
+ check(classOf[LongAnnotation], "test2", Constants.NegativeLong)
+ check(classOf[FloatAnnotation], "test2", Constants.NegativeFloat)
+ check(classOf[DoubleAnnotation], "test2", Constants.NegativeDouble)
+ check(classOf[StringAnnotation], "test2", Constants.NegativeString)
+
+ check(classOf[BooleanAnnotation], "test3", Constants.BooleanFalse)
+ check(classOf[ByteAnnotation], "test3", Constants.LiteralCharAsByte)
+ check(classOf[CharAnnotation], "test3", Constants.LiteralChar)
+ check(classOf[ShortAnnotation], "test3", Constants.LiteralCharAsShort)
+ check(classOf[IntAnnotation], "test3", Constants.LiteralCharAsInt)
+ check(classOf[LongAnnotation], "test3", Constants.LiteralCharAsLong)
+
+ check(classOf[LongAnnotation], "test4", Constants.LiteralIntAsLong)
+}
diff --git a/test/junit/scala/collection/immutable/RangeConsistencyTest.scala b/test/junit/scala/collection/immutable/RangeConsistencyTest.scala
index 760498c162..a997fd14ab 100644
--- a/test/junit/scala/collection/immutable/RangeConsistencyTest.scala
+++ b/test/junit/scala/collection/immutable/RangeConsistencyTest.scala
@@ -172,4 +172,43 @@ class RangeConsistencyTest {
assert(r.sum(possiblyNotDefaultNumeric) == Int.MinValue)
assert(nr.sum(possiblyNotDefaultNumeric) == Int.MinValue)
}
+
+ @Test
+ def test_SI10086() {
+ implicit val customIntegral =
+ new Numeric.IntIsIntegral with Ordering.IntOrdering {}
+
+ val nr = NumericRange(1, 10, 1)
+ assert(nr.min == 1)
+ assert(nr.max == 9)
+
+ // Also test with custom ordering.
+ assert(nr.min(customIntegral.reverse) == 9)
+ assert(nr.max(customIntegral.reverse) == 1)
+
+ case class A(v: Int)
+
+ implicit object aIsIntegral extends scala.math.Integral[A] {
+ def compare(x: A, y: A): Int = x.v.compare(y.v)
+ def fromInt(x: Int): A = A(x)
+ def minus(x: A, y: A): A = A(x.v - y.v)
+ def negate(x: A): A = A(-x.v)
+ def plus(x: A, y: A): A = A(x.v + y.v)
+ def times(x: A, y: A): A = A(x.v * y.v)
+ def quot(x: A, y: A): A = A(x.v / y.v)
+ def rem(x: A, y: A): A = A(x.v % y.v)
+ def toDouble(x: A): Double = x.v.toDouble
+ def toFloat(x: A): Float = x.v.toFloat
+ def toInt(x: A): Int = x.v
+ def toLong(x: A): Long = x.v.toLong
+ }
+
+ val r = NumericRange(A(1), A(10), A(1))
+ assert(r.min == A(1))
+ assert(r.max == A(9))
+
+ // Also test with custom ordering.
+ assert(r.min(aIsIntegral.reverse) == A(9))
+ assert(r.max(aIsIntegral.reverse) == A(1))
+ }
}
diff --git a/test/junit/scala/tools/testing/AssertUtil.scala b/test/junit/scala/tools/testing/AssertUtil.scala
index d798f2e53e..c9b2fb8e4d 100644
--- a/test/junit/scala/tools/testing/AssertUtil.scala
+++ b/test/junit/scala/tools/testing/AssertUtil.scala
@@ -3,6 +3,7 @@ package testing
import org.junit.Assert
import Assert._
+import scala.reflect.ClassTag
import scala.runtime.ScalaRunTime.stringOf
import scala.collection.{ GenIterable, IterableLike }
import scala.collection.JavaConverters._
@@ -40,15 +41,13 @@ object AssertUtil {
* and that its message satisfies the `checkMessage` predicate.
* Any other exception is propagated.
*/
- def assertThrows[T <: Throwable](body: => Any,
- checkMessage: String => Boolean = s => true)
- (implicit manifest: Manifest[T]): Unit = {
+ def assertThrows[T <: Throwable: ClassTag](body: => Any,
+ checkMessage: String => Boolean = s => true): Unit = {
try {
body
fail("Expression did not throw!")
} catch {
- case e: Throwable if (manifest.runtimeClass isAssignableFrom e.getClass) &&
- checkMessage(e.getMessage) =>
+ case e: T if checkMessage(e.getMessage) =>
}
}