diff options
Diffstat (limited to 'src/compiler/scala/tools')
15 files changed, 153 insertions, 112 deletions
diff --git a/src/compiler/scala/tools/ant/templates/tool-windows.tmpl b/src/compiler/scala/tools/ant/templates/tool-windows.tmpl index 50e44fb669..338f2f1375 100644 --- a/src/compiler/scala/tools/ant/templates/tool-windows.tmpl +++ b/src/compiler/scala/tools/ant/templates/tool-windows.tmpl @@ -156,7 +156,7 @@ rem (see http://support.microsoft.com/?kbid=833431) rem set _SCALA_HOME=%~dps0.. :set_home set _BIN_DIR= - for %%i in (%~sf0) do set _BIN_DIR=%_BIN_DIR%%%~dpsi + for %%i in ("%~sf0") do set _BIN_DIR=%_BIN_DIR%%%~dpsi set _SCALA_HOME=%_BIN_DIR%.. goto :eof diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index 9cac497a85..ffe95ba9dc 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -47,7 +47,7 @@ class StandardCompileServer(fixPort: Int = 0) extends SocketServer(fixPort) { } def printMemoryStats() { - def mb(bytes: Long) = "%dMB".format(bytes / 1000000) + def mb(bytes: Long) = "%10.2fMB".format(bytes / 1048576.0) info("New session: total memory = %s, max memory = %s, free memory = %s".format( mb(totalMemory), mb(maxMemory), mb(freeMemory))) } diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 873a5947ed..40be302799 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -989,7 +989,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) ) private def formatExplain(pairs: (String, Any)*): String = ( - pairs.toList collect { case (k, v) if v != null => "%20s: %s".format(k, v) } mkString "\n" + pairs collect { case (k, v) if v != null => f"$k%20s: $v" } mkString "\n" ) /** Don't want to introduce new errors trying to report errors, @@ -1002,9 +1002,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val site = lastSeenContext.enclClassOrMethod.owner val pos_s = if (tree.pos.isDefined) s"line ${tree.pos.line} of ${tree.pos.source.file}" else "<unknown>" val context_s = try { + import scala.reflect.io.{File => SFile} // Taking 3 before, 3 after the fingered line. - val start = 0 max (tree.pos.line - 3) - val xs = scala.reflect.io.File(tree.pos.source.file.file).lines drop start take 7 + val start = 1 max (tree.pos.line - 3) + val xs = SFile(tree.pos.source.file.file).lines.drop(start-1).take(7) val strs = xs.zipWithIndex map { case (line, idx) => f"${start + idx}%6d $line" } strs.mkString("== Source file context for tree position ==\n\n", "\n", "") } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index d7d0f01741..0cdba861a5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2236,31 +2236,57 @@ self => * }}} */ def paramClauses(owner: Name, contextBounds: List[Tree], ofCaseClass: Boolean): List[List[ValDef]] = { - var implicitmod = 0 - var caseParam = ofCaseClass - def paramClause(): List[ValDef] = { - if (in.token == RPAREN) - return Nil - - if (in.token == IMPLICIT) { - in.nextToken() - implicitmod = Flags.IMPLICIT - } - commaSeparated(param(owner, implicitmod, caseParam )) - } - val vds = new ListBuffer[List[ValDef]] + var implicitSection = -1 + var implicitOffset = -1 + var warnAt = -1 + var caseParam = ofCaseClass + val vds = new ListBuffer[List[ValDef]] val start = in.offset + def paramClause(): List[ValDef] = if (in.token == RPAREN) Nil else { + val implicitmod = + if (in.token == IMPLICIT) { + if (implicitOffset == -1) { implicitOffset = in.offset ; implicitSection = vds.length } + else if (warnAt == -1) warnAt = in.offset + in.nextToken() + Flags.IMPLICIT + } else 0 + commaSeparated(param(owner, implicitmod, caseParam)) + } newLineOptWhenFollowedBy(LPAREN) - if (ofCaseClass && in.token != LPAREN) - syntaxError(in.lastOffset, "case classes without a parameter list are not allowed;\n"+ - "use either case objects or case classes with an explicit `()' as a parameter list.") - while (implicitmod == 0 && in.token == LPAREN) { + while (in.token == LPAREN) { in.nextToken() vds += paramClause() accept(RPAREN) caseParam = false newLineOptWhenFollowedBy(LPAREN) } + if (ofCaseClass) { + if (vds.isEmpty) + syntaxError(start, s"case classes must have a parameter list; try 'case class ${owner.encoded + }()' or 'case object ${owner.encoded}'") + else if (vds.head.nonEmpty && vds.head.head.mods.isImplicit) { + if (settings.isScala213) + syntaxError(start, s"case classes must have a non-implicit parameter list; try 'case class ${ + owner.encoded}()${ vds.map(vs => "(...)").mkString }'") + else { + deprecationWarning(start, s"case classes should have a non-implicit parameter list; adapting to 'case class ${ + owner.encoded}()${ vds.map(vs => "(...)").mkString }'", "2.12.2") + vds.insert(0, List.empty[ValDef]) + vds(1) = vds(1).map(vd => copyValDef(vd)(mods = vd.mods & ~Flags.CASEACCESSOR)) + if (implicitSection != -1) implicitSection += 1 + } + } + } + if (implicitSection != -1 && implicitSection != vds.length - 1) + syntaxError(implicitOffset, "an implicit parameter section must be last") + if (warnAt != -1) + syntaxError(warnAt, "multiple implicit parameter sections are not allowed") + else if (settings.warnExtraImplicit) { + // guard against anomalous class C(private implicit val x: Int)(implicit s: String) + val ttl = vds.count { case ValDef(mods, _, _, _) :: _ => mods.isImplicit ; case _ => false } + if (ttl > 1) + warning(in.offset, s"$ttl parameter sections are effectively implicit") + } val result = vds.toList if (owner == nme.CONSTRUCTOR && (result.isEmpty || (result.head take 1 exists (_.mods.isImplicit)))) { in.token match { diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index ccd0d4a9c9..226c49ec07 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -386,6 +386,17 @@ trait Scanners extends ScannersCommon { next copyFrom this this copyFrom prev } + } else if (token == COMMA) { + // SIP-27 Trailing Comma (multi-line only) support + // If a comma is followed by a new line & then a closing paren, bracket or brace + // then it is a trailing comma and is ignored + val saved = new ScannerData {} copyFrom this + fetchToken() + if (afterLineEnd() && (token == RPAREN || token == RBRACKET || token == RBRACE)) { + /* skip the trailing comma */ + } else if (token == EOF) { // e.g. when the REPL is parsing "val List(x, y, _*," + /* skip the trailing comma */ + } else this copyFrom saved } // print("["+this+"]") diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 9b9d94bb0f..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. */ @@ -20,66 +21,61 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr var shortname: Boolean = false /** maximal number of error messages to be printed */ + @deprecated("configured by settings.maxerrs", since="2.12.2") final val ERROR_LIMIT = 100 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) { - if (severity != ERROR || severity.count <= ERROR_LIMIT) - print(pos, msg, severity) + def display(pos: Position, msg: String, severity: Severity): Unit = { + val ok = severity match { + case ERROR => ERROR.count <= settings.maxerrs.value + case WARNING => WARNING.count <= settings.maxwarns.value + case _ => true + } + if (ok) print(pos, msg, severity) } 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/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index 822e0f16bf..92a5cbdd73 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -416,9 +416,9 @@ class MutableSettings(val errorFn: String => Unit) // Helper to generate a textual explanation of valid inputs private def getValidText: String = (min, max) match { case (IntMin, IntMax) => "can be any integer" - case (IntMin, x) => "must be less than or equal to "+x - case (x, IntMax) => "must be greater than or equal to "+x - case _ => "must be between %d and %d".format(min, max) + case (IntMin, x) => f"must be less than or equal to $x%d" + case (x, IntMax) => f"must be greater than or equal to $x%d" + case _ => f"must be between $min%d and $max%d" } // Ensure that the default value is actually valid @@ -431,7 +431,7 @@ class MutableSettings(val errorFn: String => Unit) } } - def errorMsg() = errorFn("invalid setting for -"+name+" "+getValidText) + def errorMsg() = errorFn(s"invalid setting for $name $getValidText") def tryToSet(args: List[String]) = if (args.isEmpty) errorAndValue("missing argument", None) @@ -444,7 +444,7 @@ class MutableSettings(val errorFn: String => Unit) if (value == default) Nil else List(name, value.toString) - withHelpSyntax(name + " <n>") + withHelpSyntax(s"$name <n>") } /** A setting represented by a boolean flag (false, unless set) */ diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 7be65431db..cce9a5b3a8 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -107,6 +107,8 @@ trait ScalaSettings extends AbsScalaSettings val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.") val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.") val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None) + val maxerrs = IntSetting ("-Xmaxerrs", "Maximum errors to print", 100, None, _ => None) + val maxwarns = IntSetting ("-Xmaxwarns", "Maximum warnings to print", 100, None, _ => None) val Xmigration = ScalaVersionSetting ("-Xmigration", "version", "Warn about constructs whose behavior may have changed since version.", initial = NoScalaVersion, default = Some(AnyScalaVersion)) val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.") val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.") diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala index 839e734abc..87534656f9 100644 --- a/src/compiler/scala/tools/nsc/settings/Warnings.scala +++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala @@ -25,6 +25,8 @@ trait Warnings { // currently considered too noisy for general use val warnUnusedImport = BooleanSetting("-Ywarn-unused-import", "Warn when imports are unused.") + val warnExtraImplicit = BooleanSetting("-Ywarn-extra-implicit", "Warn when more than one implicit parameter section is defined.") + // Experimental lint warnings that are turned off, but which could be turned on programmatically. // They are not activated by -Xlint and can't be enabled on the command line because they are not // created using the standard factory methods. 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 296d9c6bca..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 _ => } @@ -1158,6 +1158,7 @@ abstract class RefChecks extends Transform { } } checkUndesiredProperties(rtpe.typeSymbol, tree.pos) + checkUndesiredProperties(rtpe.typeSymbol.primaryConstructor, tree.pos) tree } 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 |