diff options
Diffstat (limited to 'src/compiler/scala/tools')
9 files changed, 106 insertions, 91 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c35c0a1019..0cdba861a5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1263,8 +1263,8 @@ self => case CHARLIT => in.charVal case INTLIT => in.intVal(isNegated).toInt case LONGLIT => in.intVal(isNegated) - case FLOATLIT => in.floatVal(isNegated).toFloat - case DOUBLELIT => in.floatVal(isNegated) + case FLOATLIT => in.floatVal(isNegated) + case DOUBLELIT => in.doubleVal(isNegated) case STRINGLIT | STRINGPART => in.strVal.intern() case TRUE => true case FALSE => false diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 99713451ac..226c49ec07 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -983,23 +983,45 @@ trait Scanners extends ScannersCommon { def intVal: Long = intVal(negated = false) - /** Convert current strVal, base to double value + /** Convert current strVal, base to float value. */ - def floatVal(negated: Boolean): Double = { - val limit: Double = if (token == DOUBLELIT) Double.MaxValue else Float.MaxValue + def floatVal(negated: Boolean): Float = { try { - val value: Double = java.lang.Double.valueOf(strVal).doubleValue() - if (value > limit) + val value: Float = java.lang.Float.parseFloat(strVal) + if (value > Float.MaxValue) syntaxError("floating point number too large") + val zeroly = "0.fF" + if (value == 0.0f && strVal.exists(c => !zeroly.contains(c))) + syntaxError("floating point number too small") if (negated) -value else value } catch { case _: NumberFormatException => syntaxError("malformed floating point number") + 0.0f + } + } + + def floatVal: Float = floatVal(negated = false) + + /** Convert current strVal, base to double value. + */ + def doubleVal(negated: Boolean): Double = { + try { + val value: Double = java.lang.Double.parseDouble(strVal) + if (value > Double.MaxValue) + syntaxError("double precision floating point number too large") + val zeroly = "0.dD" + if (value == 0.0d && strVal.exists(c => !zeroly.contains(c))) + syntaxError("double precision floating point number too small") + if (negated) -value else value + } catch { + case _: NumberFormatException => + syntaxError("malformed double precision floating point number") 0.0 } } - def floatVal: Double = floatVal(negated = false) + def doubleVal: Double = doubleVal(negated = false) def checkNoLetter(): Unit = { if (isIdentifierPart(ch) && ch >= ' ') diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 342031b601..99263bf834 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -7,9 +7,10 @@ package scala package tools.nsc package reporters -import java.io.{ BufferedReader, PrintWriter } -import scala.reflect.internal.util._ -import StringOps._ +import java.io.{BufferedReader, PrintWriter} +import scala.reflect.internal.util.{Position, StringOps} +import Position.formatMessage +import StringOps.{countElementsAsString => countAs, trimAllTrailingSpace => trimTrailing} /** This class implements a Reporter that displays messages on a text console. */ @@ -26,47 +27,35 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr private def label(severity: Severity): String = severity match { case ERROR => "error" case WARNING => "warning" - case INFO => null + case INFO => "" } - protected def clabel(severity: Severity): String = { - val label0 = label(severity) - if (label0 eq null) "" else label0 + ": " + protected def clabel(severity: Severity): String = label(severity) match { + case "" => "" + case s => s"$s: " } - /** Returns the number of errors issued totally as a string. - */ - private def getCountString(severity: Severity): String = - StringOps.countElementsAsString((severity).count, label(severity)) - /** Prints the message. */ - def printMessage(msg: String) { - writer print trimAllTrailingSpace(msg) + "\n" + def printMessage(msg: String): Unit = { + writer.println(trimTrailing(msg)) writer.flush() } /** Prints the message with the given position indication. */ - def printMessage(posIn: Position, msg: String) { - printMessage(Position.formatMessage(posIn, msg, shortname)) - } - def print(pos: Position, msg: String, severity: Severity) { - printMessage(pos, clabel(severity) + msg) - } + def printMessage(posIn: Position, msg: String): Unit = printMessage(formatMessage(posIn, msg, shortname)) - /** Prints the column marker of the given position. - */ - def printColumnMarker(pos: Position) = - if (pos.isDefined) { printMessage(" " * (pos.column - 1) + "^") } + def print(pos: Position, msg: String, severity: Severity): Unit = printMessage(pos, s"${clabel(severity)}${msg}") - /** Prints the number of errors and warnings if their are non-zero. */ - def printSummary() { - if (WARNING.count > 0) printMessage(getCountString(WARNING) + " found") - if ( ERROR.count > 0) printMessage(getCountString(ERROR ) + " found") - } + /** Prints the column marker of the given position. */ + def printColumnMarker(pos: Position): Unit = if (pos.isDefined) printMessage(" " * (pos.column - 1) + "^") + + /** Prints the number of warnings and errors if there are any. */ + def printSummary(): Unit = + for (k <- List(WARNING, ERROR) if k.count > 0) printMessage(s"${countAs(k.count, label(k))} found") def display(pos: Position, msg: String, severity: Severity): Unit = { val ok = severity match { - case ERROR => ERROR.count <= settings.maxerrs.value + case ERROR => ERROR.count <= settings.maxerrs.value case WARNING => WARNING.count <= settings.maxwarns.value case _ => true } @@ -74,17 +63,19 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr } def displayPrompt(): Unit = { - writer.print("\na)bort, s)tack, r)esume: ") + writer.println() + writer.print("a)bort, s)tack, r)esume: ") writer.flush() if (reader != null) { - val response = reader.read().asInstanceOf[Char].toLower - if (response == 'a' || response == 's') { - (new Exception).printStackTrace() - if (response == 'a') - sys exit 1 - - writer.print("\n") - writer.flush() + reader.read match { + case 'a' | 'A' => + new Throwable().printStackTrace() + System.exit(1) + case 's' | 'S' => + new Throwable().printStackTrace() + writer.println() + writer.flush() + case _ => } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 2d8d591b6d..0910dca445 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -1211,7 +1211,7 @@ trait ContextErrors { "pass-by-name arguments not allowed for case class parameters" case AbstractVar => - "only classes can have declared but undefined members" + abstractVarMessage(sym) + "only traits and abstract classes can have declared but undefined members" + abstractVarMessage(sym) } issueSymbolTypeError(sym, msg) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index fde2f7bb03..d349597b14 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1194,7 +1194,8 @@ trait Contexts { self: Analyzer => } final def lookupCompanionOf(original: Symbol): Symbol = { - lookupScopeEntry(original) match { + if (original.isModuleClass) original.sourceModule + else lookupScopeEntry(original) match { case null => NoSymbol case entry => entry.owner.lookupCompanion(original) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index df014b5161..ea82739504 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -240,10 +240,6 @@ abstract class Duplicators extends Analyzer { result.symbol.updateAttachment(DelambdafyTarget) result - case fun: Function => - debuglog("Clearing the type and retyping Function: " + fun) - super.typed(fun.clearType, mode, pt) - case vdef @ ValDef(mods, name, tpt, rhs) => // log("vdef fixing tpe: " + tree.tpe + " with sym: " + tree.tpe.typeSymbol + " and " + invalidSyms) //if (mods.hasFlag(Flags.LAZY)) vdef.symbol.resetFlag(Flags.MUTABLE) // Martin to Iulian: lazy vars can now appear because they are no longer boxed; Please check that deleting this statement is OK. diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index e8147dbf3a..9dd260b274 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -495,21 +495,22 @@ trait Infer extends Checkable { } /** Return inferred type arguments, given type parameters, formal parameters, - * argument types, result type and expected result type. - * If this is not possible, throw a `NoInstance` exception. - * Undetermined type arguments are represented by `definitions.NothingTpe`. - * No check that inferred parameters conform to their bounds is made here. - * - * @param tparams the type parameters of the method - * @param formals the value parameter types of the method - * @param restpe the result type of the method - * @param argtpes the argument types of the application - * @param pt the expected return type of the application - * @return @see adjustTypeArgs - * - * @throws NoInstance - */ - def methTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type, + * argument types, result type and expected result type. + * If this is not possible, throw a `NoInstance` exception. + * Undetermined type arguments are represented by `definitions.NothingTpe`. + * No check that inferred parameters conform to their bounds is made here. + * + * @param fn the function for reporting, may be empty + * @param tparams the type parameters of the method + * @param formals the value parameter types of the method + * @param restpe the result type of the method + * @param argtpes the argument types of the application + * @param pt the expected return type of the application + * @return @see adjustTypeArgs + * + * @throws NoInstance + */ + def methTypeArgs(fn: Tree, tparams: List[Symbol], formals: List[Type], restpe: Type, argtpes: List[Type], pt: Type): AdjustedTypeArgs.Result = { val tvars = tparams map freshVar if (!sameLength(formals, argtpes)) @@ -559,21 +560,12 @@ trait Infer extends Checkable { val hasAny = pt :: restpe :: formals ::: argtpes ::: loBounds exists (_.dealiasWidenChain exists containsAny) !hasAny } - def argumentPosition(idx: Int): Position = context.tree match { - case x: ValOrDefDef => x.rhs match { - case Apply(fn, args) if idx < args.size => args(idx).pos - case _ => context.tree.pos - } - case _ => context.tree.pos - } - if (settings.warnInferAny && context.reportErrors && canWarnAboutAny) { - foreachWithIndex(targs) ((targ, idx) => - targ.typeSymbol match { - case sym @ (AnyClass | AnyValClass) => - reporter.warning(argumentPosition(idx), s"a type was inferred to be `${sym.name}`; this may indicate a programming error.") - case _ => - } - ) + if (settings.warnInferAny && context.reportErrors && !fn.isEmpty && canWarnAboutAny) { + targs.foreach(_.typeSymbol match { + case sym @ (AnyClass | AnyValClass) => + reporter.warning(fn.pos, s"a type was inferred to be `${sym.name}`; this may indicate a programming error.") + case _ => + }) } adjustTypeArgs(tparams, tvars, targs, restpe) } @@ -735,7 +727,7 @@ trait Infer extends Checkable { ) def tryInstantiating(args: List[Type]) = falseIfNoInstance { val restpe = mt resultType args - val AdjustedTypeArgs.Undets(okparams, okargs, leftUndet) = methTypeArgs(undetparams, formals, restpe, args, pt) + val AdjustedTypeArgs.Undets(okparams, okargs, leftUndet) = methTypeArgs(EmptyTree, undetparams, formals, restpe, args, pt) val restpeInst = restpe.instantiateTypeParams(okparams, okargs) // #2665: must use weak conformance, not regular one (follow the monomorphic case above) exprTypeArgs(leftUndet, restpeInst, pt, useWeaklyCompatible = true) match { @@ -989,7 +981,7 @@ trait Infer extends Checkable { val restpe = fn.tpe.resultType(argtpes) val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) = - methTypeArgs(undetparams, formals, restpe, argtpes, pt) + methTypeArgs(fn, undetparams, formals, restpe, argtpes, pt) if (checkBounds(fn, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")) { val treeSubst = new TreeTypeSubstituter(okparams, okargs) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 45dfb427f0..a787a7bc12 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1130,7 +1130,7 @@ abstract class RefChecks extends Transform { } /** Sensibility check examines flavors of equals. */ def checkSensible(pos: Position, fn: Tree, args: List[Tree]) = fn match { - case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 && isObjectOrAnyComparisonMethod(fn.symbol) && !currentOwner.isSynthetic => + case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 && isObjectOrAnyComparisonMethod(fn.symbol) && (!currentOwner.isSynthetic || currentOwner.isAnonymousFunction) => checkSensibleEquals(pos, qual, name, fn.symbol, args.head) case _ => } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 58a44d3ac0..837ccf7e06 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -864,11 +864,24 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case _ => } debuglog(s"fallback on implicits: ${tree}/$resetTree") - val tree1 = typed(resetTree, mode) - // Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that - // we pass `EmptyTree` as the `original`. intended? added in 2009 (53d98e7d42) by martin. - tree1 setType pluginsTyped(tree1.tpe, this, tree1, mode, pt) - if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt, EmptyTree) + // SO-10066 Need to patch the enclosing tree in the context to make translation of Dynamic + // work during fallback typechecking below. + val resetContext: Context = { + object substResetForOriginal extends Transformer { + override def transform(tree: Tree): Tree = { + if (tree eq original) resetTree + else super.transform(tree) + } + } + context.make(substResetForOriginal.transform(context.tree)) + } + typerWithLocalContext(resetContext) { typer1 => + val tree1 = typer1.typed(resetTree, mode) + // Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that + // we pass `EmptyTree` as the `original`. intended? added in 2009 (53d98e7d42) by martin. + tree1 setType pluginsTyped(tree1.tpe, typer1, tree1, mode, pt) + if (tree1.isEmpty) tree1 else typer1.adapt(tree1, mode, pt, EmptyTree) + } } ) else |