Browse Source

Minimize complete test file, add MEMBER token

Robin Maisch 4 years ago
parent
commit
4286a3c7de

+ 19 - 3
jplag.frontend.scala/src/main/scala/de/jplag/scala/Parser.scala

@@ -74,7 +74,7 @@ class Parser(consumer: ErrorConsumer) extends AbstractParser(consumer) {
                     // `f()` can also be written as `f`, so we simply don't see `f()` as a function call
                     // But Java style function calls with no args should still be recognized
                     TR(traverse = _ => {
-                        add(Apply, tree, fromEnd=false)
+                        add(Apply, fun, fromEnd=false)
                         apply(fun)
                         for (arg <- args) {
                             add(Argument, arg, fromEnd = false)
@@ -132,7 +132,16 @@ class Parser(consumer: ErrorConsumer) extends AbstractParser(consumer) {
                 case scala.meta.Pkg(_) => TR(Some(Package))
                 case scala.meta.Import(_) => TR(Some(ScalaTokenConstants.Import))
 
-                case Defn.Def(_) => TR(Some(MethodBegin), Some(MethodEnd))
+                case Defn.Def(_, name, typeParams, paramss, _, body) =>
+                    TR(traverse = _ => {
+                        add(MethodDef, name, fromEnd = false)
+                        for (tParam <- typeParams) add(TypeParameter, tParam, fromEnd = false)
+                        for (params <- paramss)
+                            for (param <- params) add(Parameter, param, fromEnd = false)
+                        add(MethodBegin, body, fromEnd = false)
+                        apply(body)
+                        add(MethodEnd, body, fromEnd = true)
+                    })
                 case Defn.Macro(_) => TR(Some(MacroBegin), Some(MacroEnd))
                 case Defn.Class(_) => TR(Some(ClassBegin), Some(ClassEnd))
                 case Defn.Object(_) => TR(Some(ObjectBegin), Some(ObjectEnd))
@@ -190,7 +199,13 @@ class Parser(consumer: ErrorConsumer) extends AbstractParser(consumer) {
                         apply(arg)
                     }
                 })
-                case Term.ApplyType(fun, typeArgs) => TR(traverse = _ => {
+                case Term.Select(refObj, member) =>
+                    TR(traverse = _ => {
+                        apply(refObj)
+                        add(ScalaTokenConstants.Member, member, fromEnd = false)
+                        apply(member)
+                    })
+                case Term.ApplyType(_, typeArgs) => TR(traverse = _ => {
                     add(Apply, tree, fromEnd = false)
                     for (typeArg <- typeArgs) add(TypeArgument, typeArg, fromEnd = false)
                 })
@@ -198,6 +213,7 @@ class Parser(consumer: ErrorConsumer) extends AbstractParser(consumer) {
                 case Self(_) => TR(Some(SelfType))
                 case Term.Block(_) => TR(Some(BlockStart), Some(BlockEnd))
                 case Enumerator.Generator(_) => TR(Some(EnumGenerator))
+                case meta.Type.Param(_) => TR(Some(TypeParameter))
                 case _ => TR()
             }
         }

+ 50 - 0
jplag.frontend.scala/src/main/scala/de/jplag/scala/ScalaToken.scala

@@ -0,0 +1,50 @@
+package de.jplag.scala
+
+import de.jplag.Token
+
+import scala.meta.inputs.Position
+
+class ScalaToken(tType: Int,
+                 file: java.lang.String,
+                 var line: Int,
+                 var column: Int,
+                 var length: Int)
+  extends Token(tType, file, line, column, length) {
+
+    def this(tType: ScalaTokenConstants.Value, file: String, pos: Position, fromEnd: Boolean) {
+        this(
+            tType.id,
+            file,
+            (if (fromEnd) pos.endLine else pos.startLine) + 1,
+            (if (fromEnd) pos.endColumn else pos.startColumn) + 1,
+            pos.text.length
+        )
+    }
+
+    override def toString: String = {
+        try {
+            ScalaTokenConstants(`type`).toString
+        } catch {
+            case _: Throwable => "Unknown!"
+        }
+    }
+
+    override def setLine(line: Int): Unit = this.line = line
+
+    override def setColumn(column: Int): Unit = this.column = column
+
+    override def setLength(length: Int): Unit = this.length = length
+
+    override def getLine: Int = this.line
+
+    override def getColumn: Int = this.column
+
+    override def getLength: Int = this.length
+
+    def numberOfTokens: Int = ScalaTokenConstants.maxId
+
+    /**
+     * @return a string representation depending on the type of the token.
+     */
+    override protected def type2string(): String = ScalaTokenConstants.apply(tType).toString
+}

+ 3 - 45
jplag.frontend.scala/src/main/scala/de/jplag/scala/ScalaTokenConstants.scala

@@ -12,6 +12,7 @@ object ScalaTokenConstants extends Enumeration with TokenConstants {
   val Import: Value = Value("IMPORT")
   val ClassBegin: Value = Value("CLASS{")
   val ClassEnd: Value = Value("}CLASS")
+  val MethodDef: Value = Value("METHOD")
   val MethodBegin: Value = Value("METHOD{")
   val MethodEnd: Value = Value("}METHOD")
   val VariableDefinition: Value = Value("VAR_DEF")
@@ -72,57 +73,14 @@ object ScalaTokenConstants extends Enumeration with TokenConstants {
   val Yield: Value = Value("YIELD")
 
   val Parameter: Value = Value("PARAM")
-  val Assignment: Value = Value("ASSIGN")
   val Argument: Value = Value("ARG")
   val NewObject: Value = Value("NEW()")
   val SelfType: Value = Value("SELF")
+  val TypeParameter: Value = Value("T_PARAM")
   val TypeArgument: Value = Value("T_ARG")
   val BlockStart: Value = Value("{")
   val BlockEnd: Value = Value("}")
   val EnumGenerator: Value = Value("ENUMERATE")
+  val Member: Value = Value("MEMBER")
 }
 
-class ScalaToken(tType: Int,
-                 file: java.lang.String,
-                 var line: Int,
-                 var column: Int,
-                 var length: Int)
-  extends Token(tType, file, line, column, length) {
-
-  def this(tType: ScalaTokenConstants.Value, file: String, pos: Position, fromEnd: Boolean) {
-    this(
-      tType.id,
-      file,
-      (if (fromEnd) pos.endLine else pos.startLine) + 1,
-      (if (fromEnd) pos.endColumn else pos.startColumn) + 1,
-      pos.text.length
-    )
-  }
-
-  override def toString: String = {
-    try {
-      ScalaTokenConstants(`type`).toString
-    } catch {
-      case _: Throwable => "Unknown!"
-    }
-  }
-
-  override def setLine(line: Int): Unit = this.line = line
-
-  override def setColumn(column: Int): Unit = this.column = column
-
-  override def setLength(length: Int): Unit = this.length = length
-
-  override def getLine: Int = this.line
-
-  override def getColumn: Int = this.column
-
-  override def getLength: Int = this.length
-
-  def numberOfTokens: Int = ScalaTokenConstants.maxId
-
-  /**
-   * @return a string representation depending on the type of the token.
-   */
-  override protected def type2string(): String = ScalaTokenConstants.apply(tType).toString
-}

+ 6 - 7
jplag.frontend.scala/src/test/java/de/jplag/scala/ScalaFrontendTest.java

@@ -1,6 +1,5 @@
 package de.jplag.scala;
 
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.File;
@@ -9,7 +8,6 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.StreamSupport;
@@ -161,18 +159,19 @@ class ScalaFrontendTest {
      * @param fileName The file name of the complete code example
      */
     private void testTokenCoverage(TokenList tokens, String fileName) {
-        var foundTokens = StreamSupport.stream(tokens.allTokens().spliterator(), true).mapToInt(Token::getType).sorted().distinct().boxed().toList();
-        // Exclude SEPARATOR_TOKEN, as it does not occur
-        var allTokens = IntStream.range(0, language.numberOfTokens()).filter(i -> i != TokenConstants.SEPARATOR_TOKEN).boxed().toList();
+        var foundTokens = StreamSupport.stream(tokens.allTokens().spliterator(), true).mapToInt(Token::getType).distinct().boxed().toList();
+        var allTokens = IntStream.range(0, language.numberOfTokens()).boxed().toList();
         allTokens = new ArrayList<>(allTokens);
 
         // Only non-found tokens are left
         allTokens.removeAll(foundTokens);
+        // Exclude SEPARATOR_TOKEN, as it does not occur
+        allTokens.remove((Integer) (TokenConstants.SEPARATOR_TOKEN));
 
         if (!allTokens.isEmpty()) {
             var notFoundTypes = allTokens.stream().map(ScalaTokenConstants::apply).toList();
-            fail("Some %d token types were not found in the complete code example '%s':\n%s"
-                    .formatted(notFoundTypes.size(), fileName, notFoundTypes));
+            fail("Some %d token types were not found in the complete code example '%s':\n%s".formatted(notFoundTypes.size(), fileName,
+                    notFoundTypes));
         }
 
     }

+ 33 - 6338
jplag.frontend.scala/src/test/resources/de/jplag/scala/Typers.scala

@@ -1,6384 +1,79 @@
-/*
- * Scala (https://www.scala-lang.org)
- *
- * Copyright EPFL and Lightbend, Inc.
- *
- * Licensed under Apache License 2.0
- * (http://www.apache.org/licenses/LICENSE-2.0).
- *
- * See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- */
+package mypackage
 
-package scala
-package tools.nsc
-package typechecker
+import scala.otherpackage
 
-import scala.annotation.tailrec
-import scala.collection.mutable
-import scala.reflect.internal.{Chars, TypesStats}
-import scala.reflect.internal.util.{FreshNameCreator, ListOfNil, Statistics}
-import scala.tools.nsc.Reporting.{MessageFilter, Suppression, WConf, WarningCategory}
-import scala.util.chaining._
-import mutable.ListBuffer
-import symtab.Flags._
-import Mode._
+trait MyTrait extends SuperTrait with OtherTrait {
+  self: SelfType =>
 
-/** A provider of methods to assign types to trees.
- *
- *  @author  Martin Odersky
- */
-trait Typers extends Adaptations with Tags with TypersTracking with PatternTypers {
-  self: Analyzer =>
+  final val valAssignee = assigned
 
-  import global._
-  import definitions._
-  import statistics._
-
-  final def forArgMode(fun: Tree, mode: Mode) =
-    if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
-
-  final val shortenImports = false
-
-  // All typechecked RHS of ValDefs for right-associative operator desugaring
   private val rightAssocValDefs = new mutable.AnyRefMap[Symbol, Tree]
-  // Symbols of ValDefs for right-associative operator desugaring which are passed by name and have been inlined
-  private val inlinedRightAssocValDefs = new mutable.HashSet[Symbol]
-
-  // For each class, we collect a mapping from constructor param accessors that are aliases of their superclass
-  // param accessors. At the end of the typer phase, when this information is available all the way up the superclass
-  // chain, this is used to determine which are true aliases, ones where the field can be elided from this class.
-  // And yes, if you were asking, this is yet another binary fragility, as we bake knowledge of the super class into
-  // this class.
-  private val superConstructorCalls: mutable.AnyRefMap[Symbol, collection.Map[Symbol, Symbol]] = perRunCaches.newAnyRefMap()
 
-  // allows override of the behavior of the resetTyper method w.r.t comments
-  def resetDocComments() = clearDocComments()
+  sealed abstract class MyClass[+T] {
+    def attribute: Boolean
 
-  def resetTyper(): Unit = {
-    //println("resetTyper called")
-    resetContexts()
-    resetImplicits()
-    resetDocComments()
-    rightAssocValDefs.clear()
-    inlinedRightAssocValDefs.clear()
-    superConstructorCalls.clear()
-  }
-
-  sealed abstract class SilentResult[+T] {
-    def isEmpty: Boolean
-    def nonEmpty = !isEmpty
-
-    @inline final def fold[U](none: => U)(f: T => U): U = this match {
-      case SilentResultValue(value) => f(value)
+    @inline final def methodWithTypeParam[U](none: => U)(f: T => U): U = this match {
+      case SubType(attr) => f(attr)
       case _                        => none
     }
-    @inline final def map[U](f: T => U): SilentResult[U] = this match {
-      case SilentResultValue(value) => SilentResultValue(f(value))
-      case x: SilentTypeError       => x
-    }
-    @inline final def filter(p: T => Boolean): SilentResult[T] = this match {
-      case SilentResultValue(value) if !p(value) => SilentTypeError(TypeErrorWrapper(new TypeError(NoPosition, "!p")))
-      case _                                     => this
-    }
-    @inline final def orElse[T1 >: T](f: Seq[AbsTypeError] => T1): T1 = this match {
-      case SilentResultValue(value) => value
-      case s : SilentTypeError      => f(s.reportableErrors)
-    }
-  }
-  class SilentTypeError private(val errors: List[AbsTypeError], val warnings: List[(Position, String, WarningCategory, Symbol)]) extends SilentResult[Nothing] {
-    override def isEmpty = true
-    def err: AbsTypeError = errors.head
-    def reportableErrors = errors match {
-      case (e1: AmbiguousImplicitTypeError) :: _ =>
-        List(e1) // DRYer error reporting for neg/t6436b.scala
-      case all =>
-        all
-    }
-  }
-  object SilentTypeError {
-    def apply(errors: AbsTypeError*): SilentTypeError = apply(errors.toList, Nil)
-    def apply(errors: List[AbsTypeError], warnings: List[(Position, String, WarningCategory, Symbol)]): SilentTypeError = new SilentTypeError(errors, warnings)
-    // todo: this extracts only one error, should be a separate extractor.
-    def unapply(error: SilentTypeError): Option[AbsTypeError] = error.errors.headOption
-  }
-
-  // todo: should include reporter warnings in SilentResultValue.
-  // e.g. tryTypedApply could print warnings on arguments when the typing succeeds.
-  case class SilentResultValue[+T](value: T) extends SilentResult[T] { override def isEmpty = false }
-
-  def newTyper(context: Context): Typer = new NormalTyper(context)
 
-  private class NormalTyper(context : Context) extends Typer(context)
-
-  // A transient flag to mark members of anonymous classes
-  // that are turned private by typedBlock
-  private final val SYNTHETIC_PRIVATE = TRANS_FLAG
-
-  private final val InterpolatorCodeRegex  = """\$\{\s*(.*?)\s*\}""".r
-  private final val InterpolatorIdentRegex = """\$[$\w]+""".r // note that \w doesn't include $
-
-  /** Check that type of given tree does not contain local or private
-   *  components.
-   */
-  object checkNoEscaping extends TypeMap {
-    private var owner: Symbol = _
-    private var scope: Scope = _
-    private var hiddenSymbols: List[Symbol] = _
-
-    /** Check that type `tree` does not refer to private
-     *  components unless itself is wrapped in something private
-     *  (`owner` tells where the type occurs).
-     */
-    def privates[T <: Tree](typer: Typer, owner: Symbol, tree: T): T =
-      if (owner.isJavaDefined) tree else check(typer, owner, EmptyScope, WildcardType, tree)
-
-    @tailrec
-    private def check[T <: Tree](typer: Typer, owner: Symbol, scope: Scope, pt: Type, tree: T): T = {
-      this.owner = owner
-      this.scope = scope
-      hiddenSymbols = Nil
-      import typer.TyperErrorGen._
-      val tp1 = apply(tree.tpe)
-      if (hiddenSymbols.isEmpty) tree setType tp1
-      else if (hiddenSymbols exists (_.isErroneous)) HiddenSymbolWithError(tree)
-      else if (isFullyDefined(pt)) tree setType pt
-      else if (tp1.typeSymbol.isAnonymousClass)
-        check(typer, owner, scope, pt, tree setType tp1.typeSymbol.classBound)
-      else if (owner == NoSymbol)
-        tree setType packSymbols(hiddenSymbols.reverse, tp1)
-      else if (!isPastTyper) { // privates
-        val badSymbol = hiddenSymbols.head
-        SymbolEscapesScopeError(tree, badSymbol)
-      } else tree
-    }
+  }
 
-    def addHidden(sym: Symbol) =
-      if (!(hiddenSymbols contains sym)) hiddenSymbols = sym :: hiddenSymbols
+  object MyObject extends SuperType {
 
     override def apply(t: Type): Type = {
       def checkNoEscape(sym: Symbol): Unit = {
-        if (sym.isPrivate && !sym.hasFlag(SYNTHETIC_PRIVATE)) {
-          var o = owner
-          while (o != NoSymbol && o != sym.owner && o != sym.owner.linkedClassOfClass &&
-            !o.isLocalToBlock && !o.isPrivate &&
-            !o.privateWithin.hasTransOwner(sym.owner))
-            o = o.owner
-          if (o == sym.owner || o == sym.owner.linkedClassOfClass)
-            addHidden(sym)
-        } else if (sym.owner.isTerm && !sym.isTypeParameterOrSkolem) {
-          var e = scope.lookupEntry(sym.name)
-          var found = false
-          while (!found && (e ne null) && e.owner == scope) {
-            if (e.sym == sym) {
-              found = true
-              addHidden(sym)
-            } else {
-              e = scope.lookupNextEntry(e)
-            }
-          }
-        }
+        while (o != NoSymbol && o != sym.owner && o != sym.owner.linkedClassOfClass &&
+          !o.isLocalToBlock && !o.isPrivate &&
+          !o.privateWithin.hasTransOwner(sym.owner))
+          o = o.owner
       }
-      mapOver(
-        t match {
-          case TypeRef(_, sym, args) =>
-            checkNoEscape(sym)
-            if (!hiddenSymbols.isEmpty && hiddenSymbols.head == sym &&
-              sym.isAliasType && sameLength(sym.typeParams, args)) {
-              hiddenSymbols = hiddenSymbols.tail
-              t.dealias
-            } else t
-          case SingleType(_, sym) =>
-            checkNoEscape(sym)
-            t
-          case _ =>
-            t
-        })
+
     }
   }
 
   private final val typerFreshNameCreators = perRunCaches.newAnyRefMap[Symbol, FreshNameCreator]()
-  def freshNameCreatorFor(context: Context) = typerFreshNameCreators.getOrElseUpdate(context.outermostContextAtCurrentPos.enclClassOrMethod.owner, new FreshNameCreator)
-
-  abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with PatternTyper with TyperContextErrors {
-    private def unit = context.unit
-    import typeDebug.ptTree
-    import TyperErrorGen._
-    implicit def fresh: FreshNameCreator = freshNameCreatorFor(context)
-
-    private def transformed: mutable.Map[Tree, Tree] = unit.transformed
-
-    val infer = new Inferencer {
-      def context = Typer.this.context
-      // See scala/bug#3281 re undoLog
-      override def isCoercible(tp: Type, pt: Type) = undoLog undo viewExists(tp, pt)
-    }
-
-    /** Overridden to false in scaladoc and/or interactive. */
-    def canAdaptConstantTypeToLiteral = true
-    def canTranslateEmptyListToNil    = true
-    def missingSelectErrorTree(tree: Tree, qual: Tree, name: Name): Tree = tree
 
-    // used to exempt synthetic accessors (i.e. those that are synthesized by the compiler to access a field)
-    // from skolemization because there's a weird bug that causes spurious type mismatches
-    // (it seems to have something to do with existential abstraction over values
-    // https://github.com/scala/scala-dev/issues/165
-    // when we're past typer, lazy accessors are synthetic, but before they are user-defined
-    // to make this hack less hacky, we could rework our flag assignment to allow for
-    // requiring both the ACCESSOR and the SYNTHETIC bits to trigger the exemption
-    private def isSyntheticAccessor(sym: Symbol) = sym.isAccessor && (!sym.isLazy || isPastTyper)
-
-    // when type checking during erasure, generate erased types in spots that aren't transformed by erasure
-    // (it erases in TypeTrees, but not in, e.g., the type a Function node)
-    def phasedAppliedType(sym: Symbol, args: List[Type]) = {
-      val tp = appliedType(sym, args)
-      if (phase.erasedTypes) erasure.specialScalaErasureFor(sym)(tp) else tp
-    }
+  abstract class MyClass2(constrArg: ParamType) extends SuperClass with Trait1 with Trait2 {
 
-    def typedDocDef(docDef: DocDef, mode: Mode, pt: Type): Tree =
-      typed(docDef.definition, mode, pt)
+    val anonymousSubclassObject = new scala.AnyVal {   }
 
-    /** Find implicit arguments and pass them to given tree.
-     */
     def applyImplicitArgs(fun: Tree): Tree = fun.tpe match {
       case MethodType(params, _) =>
-        val argResultsBuff = new ListBuffer[SearchResult]()
-        val argBuff = new ListBuffer[Tree]()
-        // paramFailed cannot be initialized with params.exists(_.tpe.isError) because that would
-        // hide some valid errors for params preceding the erroneous one.
-        var paramFailed = false
         var mkArg: (Name, Tree) => Tree = (_, tree) => tree
 
-        // DEPMETTODO: instantiate type vars that depend on earlier implicit args (see adapt (4.1))
-        //
-        // apply the substitutions (undet type param -> type) that were determined
-        // by implicit resolution of implicit arguments on the left of this argument
         for(param <- params) {
           var paramTp = param.tpe
-          for(ar <- argResultsBuff)
-            paramTp = paramTp.subst(ar.subst.from, ar.subst.to)
-
-          val res =
-            if (paramFailed || (paramTp.isErroneous && {paramFailed = true; true})) SearchFailure
-            else inferImplicitFor(paramTp, fun, context, reportAmbiguous = context.reportErrors)
-          argResultsBuff += res
-
-          if (res.isSuccess) {
-            argBuff += mkArg(param.name, res.tree)
-          } else {
-            mkArg = gen.mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args
-            if (!param.hasDefault && !paramFailed) {
-              context.reporter.reportFirstDivergentError(fun, param, paramTp)(context)
-              paramFailed = true
-            }
-            /* else {
-             TODO: alternative (to expose implicit search failure more) -->
-             resolve argument, do type inference, keep emitting positional args, infer type params based on default value for arg
-             for (ar <- argResultsBuff) ar.subst traverse defaultVal
-             val targs = exprTypeArgs(context.undetparams, defaultVal.tpe, paramTp)
-             substExpr(tree, tparams, targs, pt)
-            }*/
-          }
-        }
-
-        val args = argBuff.toList
-        for (ar <- argResultsBuff) {
-          ar.subst traverse fun
-          for (arg <- args) ar.subst traverse arg
         }
 
-        new ApplyToImplicitArgs(fun, args) setPos fun.pos
-      case ErrorType =>
-        fun
       case x => throw new MatchError(x)
     }
 
-    def viewExists(from: Type, to: Type): Boolean = (
-      !from.isError
-        && !to.isError
-        && context.implicitsEnabled
-        && (inferView(context.tree, from, to, reportAmbiguous = false) != EmptyTree)
-      // scala/bug#8230 / scala/bug#8463 We'd like to change this to `saveErrors = false`, but can't.
-      // For now, we can at least pass in `context.tree` rather then `EmptyTree` so as
-      // to avoid unpositioned type errors.
-      )
-
-    // Get rid of any special ProtoTypes, so that implicit search won't have to deal with them
-    private def normalizeProtoForView(proto: Type): Type = proto match {
-      case proto: OverloadedArgProto => proto.underlying
-      case pt                        => pt
-    }
-
-    /** Infer an implicit conversion (`view`) between two types.
-     *  @param tree             The tree which needs to be converted.
-     *  @param from             The source type of the conversion
-     *  @param to               The target type of the conversion
-     *  @param reportAmbiguous  Should ambiguous implicit errors be reported?
-     *                          False iff we search for a view to find out
-     *                          whether one type is coercible to another.
-     *  @param saveErrors       Should ambiguous and divergent implicit errors that were buffered
-     *                          during the inference of a view be put into the original buffer.
-     *                          False iff we don't care about them.
-     */
-    def inferView(tree: Tree, from: Type, to: Type, reportAmbiguous: Boolean = true, saveErrors: Boolean = true): Tree =
-      if (isPastTyper || from.isInstanceOf[MethodType] || from.isInstanceOf[OverloadedType] || from.isInstanceOf[PolyType]) EmptyTree
-      else {
-        debuglog(s"Inferring view from $from to $to for $tree (reportAmbiguous= $reportAmbiguous, saveErrors=$saveErrors)")
-
-        val fromNoAnnot = from.withoutAnnotations
-        val toNorm = normalizeProtoForView(to)
-        val result = inferImplicitView(fromNoAnnot, toNorm, tree, context, reportAmbiguous, saveErrors) match {
-          case fail if fail.isFailure => inferImplicitView(byNameType(fromNoAnnot), toNorm, tree, context, reportAmbiguous, saveErrors)
-          case ok => ok
-        }
-
-        if (result.subst != EmptyTreeTypeSubstituter) {
-          result.subst traverse tree
-          notifyUndetparamsInferred(result.subst.from, result.subst.to)
-        }
-        result.tree
-      }
-
-    import infer._
-
-    private var namerCache: Namer = null
-    def namer: Namer = {
-      if ((namerCache eq null) || namerCache.context != context)
-        namerCache = newNamer(context)
-      namerCache
-    }
-
-    var context = context0
-    def context1 = context
-
-    def dropExistential(tp: Type): Type = tp match {
-      case ExistentialType(tparams, _) =>
-        new SubstWildcardMap(tparams).apply(tp)
-      case TypeRef(_, sym, _) if sym.isAliasType =>
-        val tp0 = tp.dealias
-        if (tp eq tp0) {
-          devWarning(s"dropExistential did not progress dealiasing $tp, see scala/bug#7126")
-          tp
-        } else {
-          val tp1 = dropExistential(tp0)
-          if (tp1 eq tp0) tp else tp1
-        }
-      case _ => tp
-    }
-
-    private def errorNotClass(tpt: Tree, found: Type)  = { ClassTypeRequiredError(tpt, found); false }
-    private def errorNotStable(tpt: Tree, found: Type) = { TypeNotAStablePrefixError(tpt, found); false }
-
-    /** Check that `tpt` refers to a non-refinement class or module type */
-    def checkClassOrModuleType(tpt: Tree): Boolean = {
-      val tpe = unwrapToClass(tpt.tpe)
-      def isModule = tpe match {
-        case SingleType(_, sym) => sym.isModule
-        case _ => false
-      }
-      isNonRefinementClassType(tpe) || isModule || errorNotClass(tpt, tpe)
-    }
-
-    /** Check that `tpt` refers to a class type with a stable prefix. */
-    def checkStablePrefixClassType(tpt: Tree): Boolean = {
-      val tpe = unwrapToStableClass(tpt.tpe)
-      def prefixIsStable = {
-        def checkPre = tpe match {
-          case TypeRef(pre, _, _) => pre.isStable || errorNotStable(tpt, pre)
-          case _                  => false
-        }
-        // A type projection like X#Y can get by the stable check if the
-        // prefix is singleton-bounded, so peek at the tree too.
-        def checkTree = tpt match {
-          case SelectFromTypeTree(qual, _)  => isSingleType(qual.tpe) || errorNotClass(tpt, tpe)
-          case _                            => true
-        }
-        checkPre && checkTree
-      }
-
-      (    (isNonRefinementClassType(tpe) || errorNotClass(tpt, tpe))
-        && (isPastTyper || prefixIsStable)
-        )
-    }
-
-    /** Check that type `tp` is not a subtype of itself.
-     */
-    def checkNonCyclic(pos: Position, tp: Type): Boolean = {
-      def checkNotLocked(sym: Symbol) = {
-        sym.initialize.lockOK || { CyclicAliasingOrSubtypingError(pos, sym); false }
-      }
-      tp match {
-        case TypeRef(pre, sym, args) =>
-          checkNotLocked(sym) &&
-            ((!sym.isNonClassType) || checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym))
-        // @M! info for a type ref to a type parameter now returns a polytype
-        // @M was: checkNonCyclic(pos, pre.memberInfo(sym).subst(sym.typeParams, args), sym)
-
-        case SingleType(_, sym) =>
-          checkNotLocked(sym)
-        case st: SubType =>
-          checkNonCyclic(pos, st.supertype)
-        case ct: CompoundType =>
-          ct.parents forall (x => checkNonCyclic(pos, x))
-        case _ =>
-          true
-      }
-    }
-
-    def checkNonCyclic(pos: Position, tp: Type, lockedSym: Symbol): Boolean = try {
-      if (!lockedSym.lock(CyclicReferenceError(pos, tp, lockedSym))) false
-      else checkNonCyclic(pos, tp)
+    def tryCatchFinally() = try {
+      if (true) false
+      else otherMethod(arg)
+    } catch {
+      case ex: CyclicReference => throw ex
+      case _ => return true
     } finally {
-      lockedSym.unlock()
-    }
-
-    def checkNonCyclic(sym: Symbol): Unit = {
-      if (!checkNonCyclic(sym.pos, sym.tpe_*)) sym.setInfo(ErrorType)
-    }
-
-    def checkNonCyclic(defn: Tree, tpt: Tree): Unit = {
-      if (!checkNonCyclic(defn.pos, tpt.tpe, defn.symbol)) {
-        tpt setType ErrorType
-        defn.symbol.setInfo(ErrorType)
-      }
-    }
-
-    def reenterValueParams(vparamss: List[List[ValDef]]): Unit = {
-      for (vparams <- vparamss)
-        for (vparam <- vparams)
-          context.scope enter vparam.symbol
-    }
-
-    def reenterTypeParams(tparams: List[TypeDef]): List[Symbol] =
-      for (tparam <- tparams) yield {
-        context.scope enter tparam.symbol
-        tparam.symbol.deSkolemize
-      }
-
-    /** The qualifying class
-     *  of a this or super with prefix `qual`.
-     *  packageOk is equal false when qualifying class symbol
-     */
-    def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean, immediate: Boolean) =
-      context.enclClass.owner.ownersIterator.find(o => qual.isEmpty || o.isClass && o.name == qual) match {
-        case Some(c) if packageOK || !c.isPackageClass => c
-        case _ =>
-          QualifyingClassError(tree, qual)
-          // Delay `setError` in namer, scala/bug#10748
-          if (immediate) setError(tree) else unit.toCheck += (() => setError(tree))
-          NoSymbol
-      }
-
-    /** The typer for an expression, depending on where we are. If we are before a superclass
-     *  call, this is a typer over a constructor context; otherwise it is the current typer.
-     */
-    final def constrTyperIf(inConstr: Boolean): Typer =
-      if (inConstr) {
-        assert(context.undetparams.isEmpty, context.undetparams)
-        newTyper(context.makeConstructorContext)
-      } else this
-
-    @inline
-    final def withCondConstrTyper[T](inConstr: Boolean)(f: Typer => T): T =
-      if (inConstr) {
-        assert(context.undetparams.isEmpty, context.undetparams)
-        val c = context.makeConstructorContext
-        typerWithLocalContext(c)(f)
-      } else {
-        f(this)
-      }
-
-    @inline
-    final def typerWithCondLocalContext[T](c: => Context)(cond: Boolean)(f: Typer => T): T =
-      if (cond) typerWithLocalContext(c)(f) else f(this)
-
-    @inline
-    final def typerWithLocalContext[T](c: Context)(f: Typer => T): T = {
-      try f(newTyper(c))
-      finally c.reporter.propagateErrorsTo(context.reporter)
-    }
-
-    /** The typer for a label definition. If this is part of a template we
-     *  first have to enter the label definition.
-     */
-    def labelTyper(ldef: LabelDef): Typer =
-      if (ldef.symbol == NoSymbol) { // labeldef is part of template
-        val typer1 = newTyper(context.makeNewScope(ldef, context.owner))
-        typer1.enterLabelDef(ldef)
-        typer1
-      } else this
-
-    /** Is symbol defined and not stale?
-     */
-    def reallyExists(sym: Symbol) = {
-      if (isStale(sym)) sym.setInfo(NoType)
-      sym.exists
-    }
-
-    /** A symbol is stale if it is toplevel, to be loaded from a classfile, and
-     *  the classfile is produced from a sourcefile which is compiled in the current run.
-     */
-    def isStale(sym: Symbol): Boolean = {
-      sym.rawInfo.isInstanceOf[loaders.ClassfileLoader] && {
-        sym.rawInfo.load(sym)
-        (sym.sourceFile ne null) &&
-          (currentRun.compiledFiles contains sym.sourceFile.path)
-      }
-    }
-
-    /** Does the context of tree `tree` require a stable type?
-     */
-    private def isStableContext(tree: Tree, mode: Mode, pt: Type) = {
-      def ptSym = pt.typeSymbol
-      def expectsStable = (
-        pt.isStable
-          || mode.inQualMode && !tree.symbol.isConstant
-          || !(tree.tpe <:< pt) && (ptSym.isAbstractType && pt.lowerBound.isStable || ptSym.isRefinementClass)
-        )
-
-      (    isNarrowable(tree.tpe)
-        && mode.typingExprNotLhs
-        && expectsStable
-        )
-    }
-
-    /** Make symbol accessible. This means:
-     *  If symbol refers to package object, insert `.package` as second to last selector.
-     *  (exception for some symbols in scala package which are dealiased immediately)
-     *  Call checkAccessible, which sets tree's attributes.
-     *  Also note that checkAccessible looks up sym on pre without checking that pre is well-formed
-     *  (illegal type applications in pre will be skipped -- that's why typedSelect wraps the resulting tree in a TreeWithDeferredChecks)
-     *  @return modified tree and new prefix type
-     */
-    private def makeAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Any /*Type | (Tree, Type)*/ =
-      if (!unit.isJava && context.isInPackageObject(sym, pre.typeSymbol)) {
-        val qual = typedQualifier { atPos(tree.pos.makeTransparent) {
-          tree match {
-            case Ident(_) =>
-              val packageObject =
-                if (!sym.isOverloaded && sym.owner.isModuleClass) sym.owner.sourceModule // historical optimization, perhaps no longer needed
-                else pre.typeSymbol.packageObject
-              Ident(packageObject)
-            case Select(qual, _)             => Select(qual, nme.PACKAGEkw)
-            case SelectFromTypeTree(qual, _) => Select(qual, nme.PACKAGEkw)
-            case x                           => throw new MatchError(x)
-          }
-        }}
-        val tree1 = atPos(tree.pos) {
-          tree match {
-            case Ident(name)                 => Select(qual, name)
-            case Select(_, name)             => Select(qual, name)
-            case SelectFromTypeTree(_, name) => SelectFromTypeTree(qual, name)
-            case x                           => throw new MatchError(x)
-          }
-        }
-        (checkAccessible(tree1, sym, qual.tpe, qual, unit.isJava), qual.tpe)
-      } else {
-        checkAccessible(tree, sym, pre, site, unit.isJava)
-      }
-
-    /** Post-process an identifier or selection node, performing the following:
-     *  1. Check that non-function pattern expressions are stable (ignoring volatility concerns -- scala/bug#6815)
-     *       (and narrow the type of modules: a module reference in a pattern has type Foo.type, not "object Foo")
-     *  2. Check that packages and static modules are not used as values
-     *  3. Turn tree type into stable type if possible and required by context.
-     *  4. Give getClass calls a more precise type based on the type of the target of the call.
-     */
-    protected def stabilize(tree: Tree, pre: Type, mode: Mode, pt: Type): Tree = {
-
-      // Side effect time! Don't be an idiot like me and think you
-      // can move "val sym = tree.symbol" before this line, because
-      // inferExprAlternative side-effects the tree's symbol.
-      if (tree.symbol.isOverloaded && !mode.inFunMode)
-        inferExprAlternative(tree, pt)
-
-      val sym = tree.symbol
-      val isStableIdPattern = mode.typingPatternNotConstructor && tree.isTerm
-
-      def isModuleTypedExpr = (
-        treeInfo.admitsTypeSelection(tree)
-          && (isStableContext(tree, mode, pt) || sym.isModuleNotMethod)
-        )
-      def isStableValueRequired = (
-        isStableIdPattern
-          || mode.in(all = EXPRmode, none = QUALmode) && !phase.erasedTypes
-        )
-      // To fully benefit from special casing the return type of
-      // getClass, we have to catch it immediately so expressions like
-      // x.getClass().newInstance() are typed with the type of x. TODO: If the
-      // type of the qualifier is inaccessible, we can cause private types to
-      // escape scope here, e.g. pos/t1107. I'm not sure how to properly handle
-      // this so for now it requires the type symbol be public.
-      def isGetClassCall = isGetClass(sym) && pre.typeSymbol.isPublic
-
-      def narrowIf(tree: Tree, condition: Boolean) =
-        if (condition) tree setType singleType(pre, sym) else tree
-
-      def checkStable(tree: Tree): Tree =
-        if (treeInfo.isStableIdentifierPattern(tree)) tree
-        else UnstableTreeError(tree)
-
-      if (tree.isErrorTyped)
-        tree
-      else if (!sym.isValue && isStableValueRequired) // (2)
-        NotAValueError(tree, sym)
-      else if (isStableIdPattern)                     // (1)
-      // A module reference in a pattern has type Foo.type, not "object Foo"
-        narrowIf(checkStable(tree), sym.isModuleNotMethod)
-      else if (isModuleTypedExpr)                     // (3)
-        narrowIf(tree, true)
-      else if (isGetClassCall)                        // (4)
-        tree setType MethodType(Nil, getClassReturnType(pre))
-      else
-        tree
-    }
-
-    private def isNarrowable(tpe: Type): Boolean = unwrapWrapperTypes(tpe) match {
-      case TypeRef(_, _, _) | RefinedType(_, _) => true
-      case _                                    => !phase.erasedTypes
-    }
-
-    def stabilizeFun(tree: Tree, mode: Mode, pt: Type): Tree = {
-      val sym = tree.symbol
-      val pre = tree match {
-        case Select(qual, _) => qual.tpe
-        case _               => NoPrefix
-      }
-      def stabilizable = (
-        pre.isStable
-          && sym.tpe.params.isEmpty
-          && (isStableContext(tree, mode, pt) || sym.isModule)
-        )
-      tree.tpe match {
-        case MethodType(_, _) if stabilizable => tree setType MethodType(Nil, singleType(pre, sym)) // TODO: should this be a NullaryMethodType?
-        case _                                => tree
-      }
-    }
-
-    @deprecated("Use the overload accepting a Type.", "2.12.9")
-    def member(qual: Tree, name: Name): Symbol = member(qual.tpe, name)
-    /** The member with given name of given qualifier type */
-    def member(qual: Type, name: Name): Symbol = {
-      def callSiteWithinClass(clazz: Symbol) = context.enclClass.owner hasTransOwner clazz
-      val includeLocals = qual match {
-        case ThisType(clazz) if callSiteWithinClass(clazz)                => true
-        case SuperType(clazz, _) if callSiteWithinClass(clazz.typeSymbol) => true
-        case _                                                            => phase.next.erasedTypes
-      }
-      if (includeLocals) qual member name
-      else qual nonLocalMember name
-    }
-
-    def silent[T](op: Typer => T,
-                  reportAmbiguousErrors: Boolean = context.ambiguousErrors,
-                  newtree: Tree = context.tree): SilentResult[T] = {
-      val findMemberStart = if (settings.areStatisticsEnabled) statistics.startCounter(findMemberFailed) else null
-      val subtypeStart = if (settings.areStatisticsEnabled) statistics.startCounter(subtypeFailed) else null
-      val failedSilentStart = if (settings.areStatisticsEnabled) statistics.startTimer(failedSilentNanos) else null
-      def stopStats() = {
-        if (settings.areStatisticsEnabled) statistics.stopCounter(findMemberFailed, findMemberStart)
-        if (settings.areStatisticsEnabled) statistics.stopCounter(subtypeFailed, subtypeStart)
-        if (settings.areStatisticsEnabled) statistics.stopTimer(failedSilentNanos, failedSilentStart)
-      }
-      @inline def wrapResult(reporter: ContextReporter, result: T) =
-        if (reporter.hasErrors) {
-          stopStats()
-          SilentTypeError(reporter.errors.toList, reporter.warnings.toList)
-        } else SilentResultValue(result)
-
-      try {
-        if (context.reportErrors ||
-          reportAmbiguousErrors != context.ambiguousErrors ||
-          newtree != context.tree) {
-          val context1 = context.makeSilent(reportAmbiguousErrors, newtree)
-          context1.undetparams = context.undetparams
-          context1.savedTypeBounds = context.savedTypeBounds
-          context1.pendingStabilizers = context.pendingStabilizers
-          val typer1 = newTyper(context1)
-          val result = op(typer1)
-          context.undetparams = context1.undetparams
-          context.savedTypeBounds = context1.savedTypeBounds
-          context.pendingStabilizers = context1.pendingStabilizers
-
-          // If we have a successful result, emit any warnings it created.
-          if (!context1.reporter.hasErrors)
-            context1.reporter.emitWarnings()
-
-          wrapResult(context1.reporter, result)
-        } else {
-          assert(context.bufferErrors || isPastTyper, "silent mode is not available past typer")
-
-          context.reporter.withFreshErrorBuffer {
-            wrapResult(context.reporter, op(this))
-          }
-        }
-      } catch {
-        case ex: CyclicReference => throw ex
-        case ex: TypeError =>
-          // fallback in case TypeError is still thrown
-          // @H this happens for example in cps annotation checker
-          stopStats()
-          SilentTypeError(TypeErrorWrapper(ex))
-      }
-    }
-
-    /** Check whether feature given by `featureTrait` is enabled.
-     *  If it is not, issue an error or a warning depending on whether the feature is required.
-     *  @param  construct  A string expression that is substituted for "#" in the feature description string
-     *  @param  immediate  When set, feature check is run immediately, otherwise it is run
-     *                     at the end of the typechecking run for the enclosing unit. This
-     *                     is done to avoid potential cyclic reference errors by implicits
-     *                     that are forced too early.
-     *  @return if feature check is run immediately: true if feature is enabled, false otherwise
-     *          if feature check is delayed or suppressed because we are past typer: true
-     */
-    def checkFeature(pos: Position, featureTrait: Symbol, construct: => String = "", immediate: Boolean = false): Boolean =
-      isPastTyper || {
-        val nestedOwners =
-          featureTrait.owner.ownerChain.takeWhile(_ != languageFeatureModule.moduleClass).reverse
-        val featureName = nestedOwners.map(s => s"${s.name}.").mkString + featureTrait.name
-        def action(): Boolean = {
-          def hasImport = inferImplicitByType(featureTrait.tpe, context).isSuccess
-          def hasOption = settings.language.contains(featureName)
-          hasOption || hasImport || {
-            val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) =
-              featureTrait.getAnnotation(LanguageFeatureAnnot): @unchecked
-            context.featureWarning(pos, featureName, featureDesc, featureTrait, construct, required)
-            false
-          }
-        }
-        if (immediate) {
-          action()
-        } else {
-          unit.toCheck += (() => action())
-          true
-        }
-      }
-
-    def checkExistentialsFeature(pos: Position, tpe: Type, prefix: String) = tpe match {
-      case extp: ExistentialType if !extp.isRepresentableWithWildcards && !tpe.isError =>
-        checkFeature(pos, currentRun.runDefinitions.ExistentialsFeature, prefix+" "+tpe)
-      case _ =>
+      cleanUp()
     }
 
-
-    /** Perform the following adaptations of expression, pattern or type `tree` wrt to
-     *  given mode `mode` and given prototype `pt`:
-     *  (-1) For expressions with annotated types, let AnnotationCheckers decide what to do
-     *  (0) Convert expressions with constant types to literals (unless in interactive/scaladoc mode)
-     *  (1) Resolve overloading, unless mode contains FUNmode
-     *  (2) Apply parameterless functions
-     *  (3) Apply polymorphic types to fresh instances of their type parameters and
-     *      store these instances in context.undetparams,
-     *      unless followed by explicit type application.
-     *  (4) Do the following to unapplied methods used as values:
-     *  (4.1) If the method has only implicit parameters, pass implicit arguments (see adaptToImplicitMethod)
-     *  (4.2) otherwise, if the method is 0-ary and it can be auto-applied (see checkCanAutoApply), apply it to ()
-     *  (4.3) otherwise, if the method is not a constructor, and can be eta-expanded (see checkCanEtaExpand), eta-expand
-     *  otherwise issue an error
-     *  (5) Convert constructors in a pattern as follows:
-     *  (5.1) If constructor refers to a case class factory, set tree's type to the unique
-     *        instance of its primary constructor that is a subtype of the expected type.
-     *  (5.2) If constructor refers to an extractor, convert to application of
-     *        unapply or unapplySeq method.
-     *
-     *  (6) Convert all other types to TypeTree nodes.
-     *  (7) When in TYPEmode but not FUNmode or HKmode, check that types are fully parameterized
-     *      (7.1) In HKmode, higher-kinded types are allowed, but they must have the expected kind-arity
-     *  (8) When in both EXPRmode and FUNmode, add apply method calls to values of object type.
-     *  (9) If there are undetermined type variables and not POLYmode, infer expression instance
-     *  Then, if tree's type is not a subtype of expected type, try the following adaptations:
-     *  (10) If the expected type is Byte, Short or Char, and the expression
-     *      is an integer fitting in the range of that type, convert it to that type.
-     *  (11) Widen numeric literals to their expected type, if necessary
-     *  (12) When in mode EXPRmode, convert E to { E; () } if expected type is scala.Unit.
-     *  (13) When in mode EXPRmode, apply AnnotationChecker conversion if expected type is annotated.
-     *  (14) When in mode EXPRmode, do SAM conversion
-     *  (15) When in mode EXPRmode, apply a view
-     *  If all this fails, error
-     *
-     *  Note: the `original` tree parameter is for re-typing implicit method invocations (see below)
-     *  and should not be used otherwise. TODO: can it be replaced with a tree attachment?
-     */
-    protected def adapt(tree: Tree, mode: Mode, pt: Type, original: Tree = EmptyTree): Tree = {
-      def hasUndets           = !context.undetparams.isEmpty
-      def hasUndetsInMonoMode = hasUndets && !mode.inPolyMode
-
-      def adaptToImplicitMethod(mt: MethodType): Tree = {
-        if (hasUndets) { // (9) -- should revisit dropped condition `hasUndetsInMonoMode`
-          // dropped so that type args of implicit method are inferred even if polymorphic expressions are allowed
-          // needed for implicits in 2.8 collection library -- maybe once #3346 is fixed, we can reinstate the condition?
-          context.undetparams = inferExprInstance(tree, context.extractUndetparams(), pt,
-            // approximate types that depend on arguments since dependency on implicit argument is like dependency on type parameter
-            mt.approximate,
-            keepNothings = false,
-            useWeaklyCompatible = true) // #3808
-        }
-
-        // avoid throwing spurious DivergentImplicit errors
-        if (context.reporter.hasErrors)
-          setError(tree)
-        else
-          withCondConstrTyper(treeInfo.isSelfOrSuperConstrCall(tree))(typer1 =>
-            if (original != EmptyTree && !pt.isWildcard) {
-              typer1 silent { tpr =>
-                val withImplicitArgs = tpr.applyImplicitArgs(tree)
-                if (tpr.context.reporter.hasErrors) tree // silent will wrap it in SilentTypeError anyway
-                else tpr.typed(withImplicitArgs, mode, pt)
-              } orElse { originalErrors =>
-                // Re-try typing (applying to implicit args) without expected type. Add in 53d98e7d42 to
-                // for better error message (scala/bug#2180, https://www.scala-lang.org/old/node/3453.html)
-                val resetTree = resetAttrs(original)
-                resetTree match {
-                  case treeInfo.Applied(fun, _, _) =>
-                    if (fun.symbol != null && fun.symbol.isError)
-                    // scala/bug#9041 Without this, we leak error symbols past the typer!
-                    // because the fallback typechecking notices the error-symbol,
-                    // refuses to re-attempt typechecking, and presumes that someone
-                    // else was responsible for issuing the related type error!
-                      fun.setSymbol(NoSymbol)
-                  case _ =>
-                }
-                debuglog(s"fallback on implicits: $tree/$resetTree")
-                // scala/bug#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 AstTransformer {
-                    override def transform(tree: Tree): Tree = {
-                      if (tree eq original) resetTree
-                      else super.transform(tree)
-                    }
-                  }
-                  context.make(substResetForOriginal.transform(context.tree))
-                }
-                typerWithLocalContext(resetContext) { typer1 =>
-                  typer1.silent { 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, original = EmptyTree)
-                  } orElse { _ =>
-                    originalErrors.foreach(context.issue)
-                    setError(tree)
-                  }
-                }
-              }
-            }
-            else
-              typer1.typed(typer1.applyImplicitArgs(tree), mode, pt)
-          )
-      }
-
-      def adaptMethodTypeToExpr(mt: MethodType): Tree = {
-        val meth =
-          tree match {
-            // a partial named application is a block (see comment in EtaExpansion)
-            // How about user-written blocks? Can they ever have a MethodType?
-            case Block(_, tree1) => tree1.symbol
-            case _               => tree.symbol
-          }
-
-
-        val arity = mt.params.length
-
-        def warnTree = original orElse tree
-
-        def warnEtaZero(): Boolean = {
-          if (!settings.warnEtaZero) return true
-          context.warning(tree.pos,
-            s"""An unapplied 0-arity method was eta-expanded (due to the expected type $pt), rather than applied to `()`.
-               |Write ${Apply(warnTree, Nil)} to invoke method ${meth.decodedName}, or change the expected type.""".stripMargin,
-            WarningCategory.LintEtaZero)
-          true
-        }
-
-        def warnEtaSam(): Boolean = {
-          if (!settings.warnEtaSam) return true
-          val sam = samOf(pt)
-          val samClazz = sam.owner
-          // TODO: we allow a Java class as a SAM type, whereas Java only allows the @FunctionalInterface on interfaces -- align?
-          if (sam.exists && (!samClazz.hasFlag(JAVA) || samClazz.hasFlag(INTERFACE)) && !samClazz.hasAnnotation(definitions.FunctionalInterfaceClass))
-            context.warning(tree.pos,
-              s"""Eta-expansion performed to meet expected type $pt, which is SAM-equivalent to ${samToFunctionType(pt)},
-                 |even though $samClazz is not annotated with `@FunctionalInterface`;
-                 |to suppress warning, add the annotation or write out the equivalent function literal.""".stripMargin,
-              WarningCategory.LintEtaSam)
-          true
-        }
-
-        // note that isFunctionProto(pt) does not work properly for Function0
-        lazy val ptUnderlying =
-          (pt match {
-            case oapt: OverloadedArgProto => oapt.underlying
-            case pt                       => pt
-          }).dealiasWiden
-
-        // (4.3) condition for eta-expansion by arity & -Xsource level
-        //
-        // for arity == 0:
-        //   - if Function0 is expected -- SAM types do not eta-expand because it could be an accidental SAM scala/bug#9489
-        // for arity > 0:
-        //   - 2.13: if function or sam type is expected
-        //   - 3.0: unconditionally
-        //
-        // warnings:
-        //   - for arity == 0: eta-expansion of zero-arg methods was deprecated (scala/bug#7187)
-        //   - for arity > 0: expected type is a SAM that is not annotated with `@FunctionalInterface`
-        def checkCanEtaExpand(): Boolean = {
-          def expectingSamOfArity = {
-            val sam = samOf(ptUnderlying)
-            sam.exists && sam.info.params.lengthIs == arity
-          }
-
-          val expectingFunctionOfArity = {
-            val ptSym = ptUnderlying.typeSymbolDirect
-            (ptSym eq FunctionClass(arity)) || (arity > 0 && (ptSym eq FunctionClass(1))) // allowing for tupling conversion
-          }
-
-          if (arity == 0)
-            expectingFunctionOfArity && warnEtaZero()
-          else
-            expectingFunctionOfArity || expectingSamOfArity && warnEtaSam() || currentRun.isScala3
-        }
-
-        def matchNullaryLoosely: Boolean = {
-          def test(sym: Symbol) = sym.isJavaDefined || sym.owner == AnyClass
-          test(meth) || meth.overrides.exists(test)
-        }
-
-        // (4.2) condition for auto-application
-        //
-        // Currently the condition is more involved to give slack to Scala methods overriding Java-defined ones;
-        // I (moors) think we should resolve that by introducing slack in overriding e.g. a Java-defined `def toString()` by a Scala-defined `def toString`.
-        // This also works better for dealing with accessors overriding Java-defined methods. The current strategy in methodSig is problematic:
-        // > // Add a () parameter section if this overrides some method with () parameters
-        // > val vparamSymssOrEmptyParamsFromOverride =
-        // This means an accessor that overrides a Java-defined method gets a MethodType instead of a NullaryMethodType, which breaks lots of assumptions about accessors)
-        def checkCanAutoApply(): Boolean = {
-          if (!isPastTyper && !matchNullaryLoosely) {
-            context.deprecationWarning(tree.pos, NoSymbol, s"Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method ${meth.decodedName},\n" +
-              s"or remove the empty argument list from its definition (Java-defined methods are exempt).\n"+
-              s"In Scala 3, an unapplied method like this will be eta-expanded into a function.", "2.13.3")
-          }
-          true
-        }
-
-        if (!meth.isConstructor && checkCanEtaExpand()) typedEtaExpansion(tree, mode, pt)
-        else if (arity == 0 && checkCanAutoApply()) {
-          val apply = Apply(tree, Nil).setPos(tree.pos).updateAttachment(AutoApplicationAttachment)
-          if (tree.hasAttachment[PostfixAttachment.type]) apply.updateAttachment(InfixAttachment)
-          adapt(typed(apply), mode, pt, original)
-        } else
-          if (context.implicitsEnabled) MissingArgsForMethodTpeError(tree, meth) // `context.implicitsEnabled` implies we are not in a pattern
-          else UnstableTreeError(tree)
-      }
-
-      def adaptType(): Tree = {
-        // @M When not typing a type constructor (!context.inTypeConstructorAllowed)
-        // or raw type, types must be of kind *,
-        // and thus parameterized types must be applied to their type arguments
-        // @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't?
-        def properTypeRequired = (
-          tree.hasSymbolField
-            && !context.inTypeConstructorAllowed
-            && !context.unit.isJava
-          )
-        // @M: don't check tree.tpe.symbol.typeParams. check tree.tpe.typeParams!!!
-        // (e.g., m[Int] --> tree.tpe.symbol.typeParams.length == 1, tree.tpe.typeParams.length == 0!)
-        // @M: removed check for tree.hasSymbolField and replace tree.symbol by tree.tpe.symbol
-        // (TypeTree's must also be checked here, and they don't directly have a symbol)
-        def kindArityMismatch = (
-          context.inTypeConstructorAllowed
-            && !sameLength(tree.tpe.typeParams, pt.typeParams)
-          )
-        // Note that we treat Any and Nothing as kind-polymorphic.
-        // We can't perform this check when typing type arguments to an overloaded method before the overload is resolved
-        // (or in the case of an error type) -- this is indicated by pt == WildcardType (see case TypeApply in typed1).
-        def kindArityMismatchOk = tree.tpe.typeSymbol match {
-          case NothingClass | AnyClass => true
-          case _                       => pt == WildcardType
-        }
-
-        // todo. It would make sense when mode.inFunMode to instead use
-        //    tree setType tree.tpe.normalize
-        // when typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...))
-        // because otherwise Ident will have its tpe set to a TypeRef, not to a PolyType, and `typedTypeApply` will fail
-        // but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else
-        if (mode.inFunMode)
-          tree
-        else if (properTypeRequired && tree.symbol.typeParams.nonEmpty)  // (7)
-          MissingTypeParametersError(tree)
-        else if (kindArityMismatch && !kindArityMismatchOk)  // (7.1) @M: check kind-arity
-          KindArityMismatchError(tree, pt)
-        else tree match { // (6)
-          case TypeTree() => tree
-          case _          => TypeTree(tree.tpe) setOriginal tree
-        }
-      }
-
-      def insertApply(): Tree = {
-        assert(!context.inTypeConstructorAllowed, mode) //@M
-        val adapted = adaptToName(unmarkDynamicRewrite(tree), nme.apply)
-        val qual = gen.stabilize(adapted)
-        val t = atPos(tree.pos)(Select(qual setPos tree.pos.makeTransparent, nme.apply))
-        wrapErrors(t, _.typed(t, mode, pt))
-      }
-      def adaptConstant(value: Constant): Tree = {
-        val sym = tree.symbol
-        if (sym != null && sym.isDeprecated)
-          context.deprecationWarning(tree.pos, sym)
-        tree match {
-          case Literal(`value`) => tree
-          case _ =>
-            // If the original tree is not a literal, make it available to plugins in an attachment
-            treeCopy.Literal(tree, value).updateAttachment(OriginalTreeAttachment(tree))
-        }
+    def yieldingMethodWithGuard(values: List[Int]): List[Int] =
+      for (value <- values if value > 0) yield {
+        value
       }
 
-      // Ignore type errors raised in later phases that are due to mismatching types with existential skolems
-      // We have lift crashing in 2.9 with an adapt failure in the pattern matcher.
-      // Here's my hypothesis why this happens. The pattern matcher defines a variable of type
-      //
-      //   val x: T = expr
-      //
-      // where T is the type of expr, but T contains existential skolems ts.
-      // In that case, this value definition does not typecheck.
-      // The value definition
-      //
-      //   val x: T forSome { ts } = expr
-      //
-      // would typecheck. Or one can simply leave out the type of the `val`:
-      //
-      //   val x = expr
-      //
-      // scala/bug#6029 shows another case where we also fail (in uncurry), but this time the expected
-      // type is an existential type.
-      //
-      // The reason for both failures have to do with the way we (don't) transform
-      // skolem types along with the trees that contain them. We'd need a
-      // radically different approach to do it. But before investing a lot of time to
-      // to do this (I have already sunk 3 full days with in the end futile attempts
-      // to consistently transform skolems and fix 6029), I'd like to
-      // investigate ways to avoid skolems completely.
-      //
-      // upd. The same problem happens when we try to typecheck the result of macro expansion against its expected type
-      // (which is the return type of the macro definition instantiated in the context of expandee):
-      //
-      //   Test.scala:2: error: type mismatch;
-      //     found   : $u.Expr[Class[_ <: Object]]
-      //     required: reflect.runtime.universe.Expr[Class[?0(in value <local Test>)]] where type ?0(in value <local Test>) <: Object
-      //     scala.reflect.runtime.universe.reify(new Object().getClass)
-      //                                         ^
-      // Therefore following Martin's advice I use this logic to recover from skolem errors after macro expansions
-      // (by adding the ` || tree.attachments.get[MacroExpansionAttachment].isDefined` clause to the conditional above).
-      //
-      def adaptMismatchedSkolems() = {
-        def canIgnoreMismatch = (
-          !context.reportErrors && isPastTyper
-            || tree.hasAttachment[MacroExpansionAttachment]
+    def validateParentClasses(parents: List[Tree], selfType: Type, clazzIsTrait: Boolean): Unit = {
+      (parent.tpe :: ps).collectFirst {
+        case p if hasTraitParams(p.typeSymbol) =>
+          p.typeSymbol.attachments.get[DottyParameterisedTrait].foreach(attach =>
+            pending += ParentIsScala3TraitError(parent, p.typeSymbol, attach.params, psym)
           )
-        def bound = pt match {
-          case ExistentialType(qs, _) => qs
-          case _                      => Nil
-        }
-        def msg = sm"""
-                      |Recovering from existential or skolem type error in
-                      |  $tree
-                      |with type: ${tree.tpe}
-                      |       pt: $pt
-                      |  context: ${context.tree}
-                      |  adapted
-          """.trim
-
-        val boundOrSkolems = if (canIgnoreMismatch) bound ++ pt.skolemsExceptMethodTypeParams else Nil
-        boundOrSkolems match {
-          case Nil => AdaptTypeError(tree, tree.tpe, pt)
-          case _   => logResult(msg)(adapt(tree, mode, deriveTypeWithWildcards(boundOrSkolems)(pt), original = EmptyTree))
-        }
-      }
-
-      def adaptExprNotFunMode(): Tree = {
-        def lastTry(err: AbsTypeError = null): Tree = {
-          debuglog("error tree = " + tree)
-          if (settings.isDebug && settings.explaintypes.value) explainTypes(tree.tpe, pt)
-          if (err ne null) context.issue(err)
-          if (tree.tpe.isErroneous || pt.isErroneous) setError(tree)
-          else adaptMismatchedSkolems()
-        }
-
-        // TODO: should we even get to fallbackAfterVanillaAdapt for an ill-typed tree?
-        if (mode.typingExprNotFun && !tree.tpe.isErroneous) {
-          @inline def tpdPos(transformed: Tree) = typedPos(tree.pos, mode, pt)(transformed)
-          @inline def tpd(transformed: Tree)    = typed(transformed, mode, pt)
-
-          @inline def warnValueDiscard(): Unit = if (!isPastTyper && settings.warnValueDiscard.value) {
-            def isThisTypeResult = (tree, tree.tpe) match {
-              case (Apply(Select(receiver, _), _), SingleType(_, sym)) => sym == receiver.symbol
-              case _ => false
-            }
-            if (!isThisTypeResult && !explicitlyUnit(tree)) context.warning(tree.pos, "discarded non-Unit value", WarningCategory.WFlagValueDiscard)
-          }
-          @inline def warnNumericWiden(tpSym: Symbol, ptSym: Symbol): Unit =
-            if (!isPastTyper) {
-              val isInharmonic = (
-                (tpSym == IntClass && ptSym == FloatClass)
-                  || (tpSym == LongClass && (ptSym == FloatClass || ptSym == DoubleClass))
-                )
-              if (isInharmonic)
-              // not `context.deprecationWarning` because they are not buffered in silent mode
-                context.warning(tree.pos, s"Widening conversion from ${tpSym.name} to ${ptSym.name} is deprecated because it loses precision. Write `.to${ptSym.name}` instead.", WarningCategory.Deprecation)
-              else if (settings.warnNumericWiden.value) context.warning(tree.pos, "implicit numeric widening", WarningCategory.WFlagNumericWiden)
-            }
-
-          // The <: Any requirement inhibits attempts to adapt continuation types to non-continuation types.
-          val anyTyped = tree.tpe <:< AnyTpe
-
-          pt.dealias match {
-            case TypeRef(_, UnitClass, _) if anyTyped => // (12)
-              warnValueDiscard() ; tpdPos(gen.mkUnitBlock(tree))
-            case TypeRef(_, numValueCls, _) if anyTyped && isNumericValueClass(numValueCls) && isNumericSubType(tree.tpe, pt) => // (10) (11)
-              warnNumericWiden(tree.tpe.widen.typeSymbol, numValueCls) ; tpdPos(Select(tree, s"to${numValueCls.name}"))
-            case dealiased if dealiased.annotations.nonEmpty && canAdaptAnnotations(tree, this, mode, pt) => // (13)
-              tpd(adaptAnnotations(tree, this, mode, pt))
-            case _ =>
-              if (hasUndets) instantiate(tree, mode, pt)
-              else {
-                // (14) sam conversion
-                // TODO: figure out how to avoid partially duplicating typedFunction (samMatchingFunction)
-                // Could we infer the SAM type, assign it to the tree and add the attachment,
-                // all in one fell swoop at the end of typedFunction?
-                val didInferSamType = inferSamType(tree, pt, mode)
-
-                if (didInferSamType) tree
-                else {  // (15) implicit view application
-                  val coercion =
-                    if (context.implicitsEnabled) inferView(tree, tree.tpe, pt)
-                    else EmptyTree
-                  if (coercion ne EmptyTree) {
-                    def msg = s"inferred view from ${tree.tpe} to $pt via $coercion: ${coercion.tpe}"
-                    if (settings.logImplicitConv.value) context.echo(tree.pos, msg)
-                    else debuglog(msg)
-
-                    val viewApplied = new ApplyImplicitView(coercion, List(tree)) setPos tree.pos
-                    val silentContext = context.makeImplicit(context.ambiguousErrors)
-                    val typedView = newTyper(silentContext).typed(viewApplied, mode, pt)
-
-                    silentContext.reporter.firstError match {
-                      case None => typedView
-                      case Some(err) => lastTry(err)
-                    }
-                  } else lastTry()
-                }
-              }
-          }
-        } else lastTry()
-      }
-
-
-      def vanillaAdapt(tree: Tree) = {
-        def applyPossible = {
-          def applyMeth = member(adaptToName(tree, nme.apply).tpe, nme.apply)
-          def hasPolymorphicApply = applyMeth.alternatives exists (_.tpe.typeParams.nonEmpty)
-          def hasMonomorphicApply = applyMeth.alternatives exists (_.tpe.paramSectionCount > 0)
-
-          def badDynamicApply() = {
-            tree match {
-              case Apply(fun, _) => DynamicRewriteError(tree, ApplyWithoutArgsError(tree, fun))
-              case _             => ()
-            }
-            false
-          }
-          if (acceptsApplyDynamic(tree.tpe))
-            !isDynamicRewrite(tree) || badDynamicApply()
-          else if (mode.inTappMode)
-            tree.tpe.typeParams.isEmpty && hasPolymorphicApply
-          else
-            hasMonomorphicApply
-        }
-        def shouldInsertApply(tree: Tree) = mode.typingExprFun && {
-          tree.tpe match {
-            case _: MethodType | _: OverloadedType | _: PolyType => false
-            case _                                               => applyPossible
-          }
-        }
-        if (tree.isType) // (6)
-          adaptType()
-        else if (mode.typingExprNotFun &&
-          treeInfo.isMacroApplication(tree) &&
-          !isMacroExpansionSuppressed(tree))
-          macroExpand(this, tree, mode, pt)
-        else if (mode.typingConstructorPattern)
-          typedConstructorPattern(tree, pt)
-        else if (shouldInsertApply(tree)) // (8)
-          insertApply()
-        else if (hasUndetsInMonoMode) // (9)
-        // This used to have
-        //     assert(!context.inTypeConstructorAllowed, context)
-        // but that's not guaranteed to be true in the face of erroneous code; errors in typedApply might mean we
-        // never get around to inferring them, and they leak out and wind up here.
-          instantiatePossiblyExpectingUnit(tree, mode, pt)
-        else if (isScalaRepeatedParamType(tree.tpe) && !isScalaRepeatedParamType(pt))
-        // TODO: we really shouldn't use T* as a first class types (e.g. for repeated case fields),
-        //  but we can't allow T* to conform to other types (see isCompatible) because that breaks overload resolution
-          adapt(tree.setType(repeatedToSeq(tree.tpe)), mode, pt, original = EmptyTree)
-        else if (tree.tpe <:< pt)
-          tree
-        else if (mode.inPatternMode && { inferModulePattern(tree, pt); isPopulated(tree.tpe, approximateAbstracts(pt)) })
-          tree
-        else {
-          val constFolded = constfold(tree, pt, context.owner)
-          if (constFolded.tpe <:< pt) adapt(constFolded, mode, pt, original) // set stage for (0)
-          else adaptExprNotFunMode() // (10) -- (15)
-        }
-      }
-
-      // begin adapt
-      if (isMacroImplRef(tree)) {
-        if (treeInfo.isMacroApplication(tree)) adapt(unmarkMacroImplRef(tree), mode, pt, original)
-        else tree
-      } else tree.tpe match {
-        case AnnotatedType(_, _) if canAdaptAnnotations(tree, this, mode, pt) => // (-1)
-          adaptAnnotations(tree, this, mode, pt)
-        case ct @ FoldableConstantType(value) if mode.inNone(TYPEmode | FUNmode) && (ct <:< pt) && canAdaptConstantTypeToLiteral => // (0)
-          adaptConstant(value)
-        case OverloadedType(_, _) if !mode.inFunMode => // (1)
-          inferExprAlternative(tree, pt)
-          adaptAfterOverloadResolution(tree, mode, pt, original)
-        case NullaryMethodType(restpe) => // (2)
-          if (hasUndets && settings.lintUniversalMethods && (isCastSymbol(tree.symbol) || isTypeTestSymbol(tree.symbol)) && context.undetparams.exists(_.owner == tree.symbol))
-            context.warning(tree.pos, s"missing type argument to ${tree.symbol}", WarningCategory.LintAdaptedArgs)
-          val resTpDeconst = // keep constant types when they are safe to fold. erasure eliminates constant types modulo some exceptions, so keep those.
-            if (isBeforeErasure && tree.symbol.isAccessor && tree.symbol.hasFlag(STABLE) && treeInfo.isExprSafeToInline(tree)) restpe
-            else restpe.deconst
-          adapt(tree setType resTpDeconst, mode, pt, original)
-        case TypeRef(_, ByNameParamClass, arg :: Nil) if mode.inExprMode => // (2)
-          adapt(tree setType arg, mode, pt, original)
-        case tp if mode.typingExprNotLhs && isExistentialType(tp) && !isSyntheticAccessor(context.owner) =>
-          adapt(tree setType tp.dealias.skolemizeExistential(context.owner, tree), mode, pt, original)
-        case PolyType(tparams, restpe) if mode.inNone(TAPPmode | PATTERNmode) && !context.inTypeConstructorAllowed => // (3)
-          // assert((mode & HKmode) == 0) //@M a PolyType in HKmode represents an anonymous type function,
-          // we're in HKmode since a higher-kinded type is expected --> hence, don't implicitly apply it to type params!
-          // ticket #2197 triggered turning the assert into a guard
-          // I guess this assert wasn't violated before because type aliases weren't expanded as eagerly
-          //  (the only way to get a PolyType for an anonymous type function is by normalisation, which applies eta-expansion)
-          // -- are we sure we want to expand aliases this early?
-          // -- what caused this change in behaviour??
-          val tparams1 = cloneSymbols(tparams)
-          val tree1 =
-            if (tree.isType) tree
-            else TypeApply(tree, tparams1.map(tparam => TypeTree(tparam.tpeHK).setPos(tree.pos.focus))).setPos(tree.pos)
-
-          context.undetparams ++= tparams1
-          notifyUndetparamsAdded(tparams1)
-          adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt, original)
-
-        case mt: MethodType if mode.typingExprNotFunNotLhs && mt.isImplicit => // (4.1)
-          adaptToImplicitMethod(mt)
-        case mt: MethodType if mode.typingExprNotFunNotLhs && !hasUndetsInMonoMode && !treeInfo.isMacroApplicationOrBlock(tree) => // (4.2) - (4.3)
-          adaptMethodTypeToExpr(mt)
-        case _ =>
-          vanillaAdapt(tree)
-      }
-    }
-
-    // This just exists to help keep track of the spots where we have to adapt a tree after
-    // overload resolution. These proved hard to find during the fix for scala/bug#8267.
-    def adaptAfterOverloadResolution(tree: Tree, mode: Mode, pt: Type = WildcardType, original: Tree = EmptyTree): Tree = {
-      adapt(tree, mode, pt, original)
-    }
-
-    def instantiate(tree: Tree, mode: Mode, pt: Type): Tree = {
-      inferExprInstance(tree, context.extractUndetparams(), pt, useWeaklyCompatible = true)
-      adapt(tree, mode, pt)
-    }
-    /** If the expected type is Unit: try instantiating type arguments
-     *  with expected type Unit, but if that fails, try again with pt = WildcardType
-     *  and discard the expression.
-     */
-    def instantiateExpectingUnit(tree: Tree, mode: Mode): Tree = {
-      val savedUndetparams = context.undetparams
-      silent(_.instantiate(tree, mode, UnitTpe)) orElse { _ =>
-        context.undetparams = savedUndetparams
-        val valueDiscard = atPos(tree.pos)(gen.mkUnitBlock(instantiate(tree, mode, WildcardType)))
-        typed(valueDiscard, mode, UnitTpe)
-      }
-    }
-
-    def instantiatePossiblyExpectingUnit(tree: Tree, mode: Mode, pt: Type): Tree = {
-      if (mode.typingExprNotFun && pt.typeSymbol == UnitClass && !tree.tpe.isInstanceOf[MethodType])
-        instantiateExpectingUnit(tree, mode)
-      else
-        instantiate(tree, mode, pt)
-    }
-
-    private def isAdaptableWithView(qual: Tree) = {
-      val qtpe = qual.tpe.widen
-      (    !isPastTyper
-        && qual.isTerm
-        && !qual.isInstanceOf[Super]
-        && ((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue)
-        && !qtpe.isError
-        && !qtpe.typeSymbol.isBottomClass
-        && !qtpe.isWildcard
-        && !qual.isInstanceOf[ApplyImplicitView] // don't chain views
-        && (context.implicitsEnabled || context.enrichmentEnabled)
-        // Elaborating `context.implicitsEnabled`:
-        // don't try to adapt a top-level type that's the subject of an implicit search
-        // this happens because, if isView, typedImplicit tries to apply the "current" implicit value to
-        // a value that needs to be coerced, so we check whether the implicit value has an `apply` method.
-        // (If we allow this, we get divergence, e.g., starting at `conforms` during ant quick.bin)
-        // Note: implicit arguments are still inferred (this kind of "chaining" is allowed)
-        )
-    }
-
-    def adaptToMember(qual: Tree, searchTemplate: Type, reportAmbiguous: Boolean = true, saveErrors: Boolean = true): Tree = {
-      if (isAdaptableWithView(qual)) {
-        qual.tpe.dealiasWiden match {
-          case et: ExistentialType =>
-            qual setType et.skolemizeExistential(context.owner, qual) // open the existential
-          case _ =>
-        }
-        inferView(qual, qual.tpe, searchTemplate, reportAmbiguous, saveErrors) match {
-          case EmptyTree  => qual
-          case coercion   =>
-            if (settings.logImplicitConv.value)
-              context.echo(qual.pos, s"applied implicit conversion from ${qual.tpe} to ${searchTemplate} = ${coercion.symbol.defString}")
-
-            typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual))))
-        }
-      }
-      else qual
-    }
-
-    /** Try to apply an implicit conversion to `qual` to that it contains
-     *  a method `name` which can be applied to arguments `args` with expected type `pt`.
-     *  If `pt` is defined, there is a fallback to try again with pt = ?.
-     *  This helps avoiding propagating result information too far and solves
-     *  #1756.
-     *  If no conversion is found, return `qual` unchanged.
-     *
-     */
-    def adaptToArguments(qual: Tree, name: Name, args: List[Tree], pt: Type, reportAmbiguous: Boolean = true, saveErrors: Boolean = true): Tree = {
-      def doAdapt(restpe: Type) =
-      //util.trace("adaptToArgs "+qual+", name = "+name+", argtpes = "+(args map (_.tpe))+", pt = "+pt+" = ")
-        adaptToMember(qual, HasMethodMatching(name, args map (_.tpe), normalizeProtoForView(restpe)), reportAmbiguous, saveErrors)
-
-      if (pt.isWildcard)
-        doAdapt(pt)
-      else silent(_ => doAdapt(pt)) filter (_ != qual) orElse (_ =>
-        logResult(s"fallback on implicits in adaptToArguments: $qual.$name")(doAdapt(WildcardType))
-        )
-    }
-
-    /** Try to apply an implicit conversion to `qual` so that it contains
-     *  a method `name`. If that's ambiguous try taking arguments into
-     *  account using `adaptToArguments`.
-     */
-    def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Mode, reportAmbiguous: Boolean = true, saveErrors: Boolean = true): Tree = {
-      def onError(reportError: => Tree): Tree = context.tree match {
-        case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty =>
-          silent(_.typedArgs(args.map(_.duplicate), mode))
-            .filter(!_.exists(_.isErrorTyped))
-            .fold(reportError)(adaptToArguments(qual, name, _, WildcardType, reportAmbiguous, saveErrors))
-        case _ =>
-          reportError
-      }
-
-      silent(_.adaptToMember(qual, HasMember(name), reportAmbiguous = false)) orElse (errs =>
-        onError {
-          if (reportAmbiguous) errs foreach (context issue _)
-          setError(tree)
-        }
-        )
-    }
-
-    /** Try to apply an implicit conversion to `qual` to that it contains a
-     *  member `name` of arbitrary type.
-     *  If no conversion is found, return `qual` unchanged.
-     */
-    def adaptToName(qual: Tree, name: Name) =
-      if (member(qual.tpe, name) != NoSymbol) qual
-      else adaptToMember(qual, HasMember(name))
-
-    private def validateNoCaseAncestor(clazz: Symbol) = {
-      if (!phase.erasedTypes) {
-        for (ancestor <- clazz.ancestors find (_.isCase)) {
-          context.error(clazz.pos, (
-            "case %s has case ancestor %s, but case-to-case inheritance is prohibited."+
-              " To overcome this limitation, use extractors to pattern match on non-leaf nodes."
-            ).format(clazz, ancestor.fullName))
-        }
-      }
-    }
-
-    private def checkEphemeral(clazz: Symbol, body: List[Tree]) = {
-      // NOTE: Code appears to be messy in this method for good reason: it clearly
-      // communicates the fact that it implements rather ad-hoc, arbitrary and
-      // non-regular set of rules that identify features that interact badly with
-      // value classes. This code can be cleaned up a lot once implementation
-      // restrictions are addressed.
-      val isValueClass = !clazz.isTrait
-      def where = if (isValueClass) "value class" else "universal trait extending from class Any"
-      def implRestriction(tree: Tree, what: String) =
-        context.error(tree.pos, s"implementation restriction: $what is not allowed in $where" +
-          "\nThis restriction is planned to be removed in subsequent releases.")
-      /**
-       * Deeply traverses the tree in search of constructs that are not allowed
-       * in value classes (at any nesting level).
-       *
-       * All restrictions this object imposes are probably not fundamental but require
-       * fair amount of work and testing. We are conservative for now when it comes
-       * to allowing language features to interact with value classes.
-       *  */
-      object checkEphemeralDeep extends Traverser {
-        override def traverse(tree: Tree): Unit = if (isValueClass) {
-          tree match {
-            case _: ModuleDef =>
-              //see https://github.com/scala/bug/issues/6359
-              implRestriction(tree, "nested object")
-            //see https://github.com/scala/bug/issues/6444
-            //see https://github.com/scala/bug/issues/6463
-            case cd: ClassDef if !cd.symbol.isAnonymousClass => // Don't warn about partial functions, etc. scala/bug#7571
-              implRestriction(tree, "nested class") // avoiding Type Tests that might check the $outer pointer.
-            case Select(sup @ Super(qual, mix), selector) if selector != nme.CONSTRUCTOR && qual.symbol == clazz && mix != tpnme.EMPTY =>
-              //see https://github.com/scala/bug/issues/6483
-              implRestriction(sup, "qualified super reference")
-            case _ =>
-          }
-          super.traverse(tree)
-        }
-      }
-      for (stat <- body) {
-        def notAllowed(what: String) = context.error(stat.pos, s"$what is not allowed in $where")
-        stat match {
-          // see https://github.com/scala/bug/issues/6444
-          // see https://github.com/scala/bug/issues/6463
-          case ClassDef(mods, _, _, _) if isValueClass =>
-            implRestriction(stat, s"nested ${ if (mods.isTrait) "trait" else "class" }")
-          case _: Import | _: ClassDef | _: TypeDef | EmptyTree => // OK
-          case DefDef(_, name, _, _, _, rhs) =>
-            if (stat.symbol.isAuxiliaryConstructor)
-              notAllowed("secondary constructor")
-            else if (isValueClass && (name == nme.equals_ || name == nme.hashCode_) && !stat.symbol.isSynthetic)
-              notAllowed(s"redefinition of $name method. See SIP-15, criterion 4.")
-            else if (stat.symbol != null && stat.symbol.isParamAccessor)
-              notAllowed("additional parameter")
-            checkEphemeralDeep.traverse(rhs)
-          case _: ValDef =>
-            notAllowed("field definition")
-          case _: ModuleDef =>
-            //see https://github.com/scala/bug/issues/6359
-            implRestriction(stat, "nested object")
-          case _ =>
-            notAllowed("this statement")
-        }
-      }
-    }
-
-    private def validateDerivedValueClass(clazz: Symbol, body: List[Tree]) = {
-      if (clazz.isTrait)
-        context.error(clazz.pos, "only classes (not traits) are allowed to extend AnyVal")
-      if (!clazz.isStatic)
-        context.error(clazz.pos, "value class may not be a "+
-          (if (clazz.owner.isTerm) "local class" else "member of another class"))
-      if (!clazz.isPrimitiveValueClass) {
-        clazz.primaryConstructor.paramss match {
-          case List(List(_)) =>
-            val decls = clazz.info.decls
-            val paramAccessor = clazz.constrParamAccessors.head
-            if (paramAccessor.isMutable)
-              context.error(paramAccessor.pos, "value class parameter must not be a var")
-            val accessor = decls.toList.find(x => x.isMethod && x.accessedOrSelf == paramAccessor)
-            accessor match {
-              case None =>
-                context.error(paramAccessor.pos, "value class parameter must be a val and not be private[this]")
-              case Some(acc) if acc.isProtectedLocal =>
-                context.error(paramAccessor.pos, "value class parameter must not be protected[this]")
-              case Some(acc) =>
-                /* check all base classes, since derived value classes might lurk in refinement parents */
-                if (acc.tpe.typeSymbol.baseClasses exists (_.isDerivedValueClass))
-                  context.error(acc.pos, "value class may not wrap another user-defined value class")
-                def referencesUnderlying(sym: Symbol) = sym != null && sym.accessedOrSelf == paramAccessor
-                checkEphemeral(clazz, body.filterNot(stat => referencesUnderlying(stat.symbol)))
-            }
-          case _ =>
-            context.error(clazz.pos, "value class needs to have exactly one val parameter")
-        }
-      }
-
-      for (tparam <- clazz.typeParams)
-        if (tparam hasAnnotation definitions.SpecializedClass)
-          context.error(tparam.pos, "type parameter of value class may not be specialized")
-    }
-
-    private def warnMultiargInfix(tree: Tree): Unit =
-      context.warning(tree.pos, "multiarg infix syntax looks like a tuple and will be deprecated", WarningCategory.LintMultiargInfix)
-
-    /** Typechecks a parent type reference.
-     *
-     *  This typecheck is harder than it might look, because it should honor early
-     *  definitions and also perform type argument inference with the help of super call
-     *  arguments provided in `encodedtpt`.
-     *
-     *  The method is called in batches (batch = 1 time per each parent type referenced),
-     *  two batches per definition: once from namer, when entering a ClassDef or a ModuleDef
-     *  and once from typer, when typechecking the definition.
-     *
-     *  ***Arguments***
-     *
-     *  `encodedtpt` represents the parent type reference wrapped in an `Apply` node
-     *  which indicates value arguments (i.e. type macro arguments or super constructor call arguments)
-     *  If no value arguments are provided by the user, the `Apply` node is still
-     *  there, but its `args` will be set to `Nil`.
-     *  This argument is synthesized by `tools.nsc.ast.Parsers.templateParents`.
-     *
-     *  `templ` is an enclosing template, which contains a primary constructor synthesized by the parser.
-     *  Such a constructor is a DefDef which contains early initializers and maybe a super constructor call
-     *  (I wrote "maybe" because trait constructors don't call super constructors).
-     *  This argument is synthesized by `tools.nsc.ast.Trees.Template`.
-     *
-     *  `inMixinPosition` indicates whether the reference is not the first in the
-     *  list of parents (and therefore cannot be a class) or the opposite.
-     *
-     *  ***Return value and side effects***
-     *
-     *  Returns a `TypeTree` representing a resolved parent type.
-     *  If the typechecked parent reference implies non-nullary and non-empty argument list,
-     *  this argument list is attached to the returned value in SuperArgsAttachment.
-     *  The attachment is necessary for the subsequent typecheck to fixup a super constructor call
-     *  in the body of the primary constructor (see `typedTemplate` for details).
-     *
-     *  This method might invoke `typedPrimaryConstrBody`, hence it might cause the side effects
-     *  described in the docs of that method. It might also attribute the Super(_, _) reference
-     *  (if present) inside the primary constructor of `templ`.
-     *
-     *  ***Example***
-     *
-     *  For the following definition:
-     *
-     *    class D extends {
-     *      val x = 2
-     *      val y = 4
-     *    } with B(x)(3) with C(y) with T
-     *
-     *  this method will be called six times:
-     *
-     *    (3 times from the namer)
-     *    typedParentType(Apply(Apply(Ident(B), List(Ident(x))), List(3)), templ, inMixinPosition = false)
-     *    typedParentType(Apply(Ident(C), List(Ident(y))), templ, inMixinPosition = true)
-     *    typedParentType(Apply(Ident(T), List()), templ, inMixinPosition = true)
-     *
-     *    (3 times from the typer)
-     *    <the same three calls>
-     */
-    private def typedParentType(encodedtpt: Tree, templ: Template, inMixinPosition: Boolean): Tree = {
-      val app @ treeInfo.Applied(core, _, argss) = treeInfo.dissectApplied(encodedtpt)
-      val decodedtpt = app.callee
-      val argssAreTrivial = argss == Nil || argss == ListOfNil
-
-      // we cannot avoid cyclic references with `initialize` here, because when type macros arrive,
-      // we'll have to check the probe for isTypeMacro anyways.
-      // therefore I think it's reasonable to trade a more specific "inherits itself" error
-      // for a generic, yet understandable "cyclic reference" error
-      var probe = typedTypeConstructor(core.duplicate).tpe.typeSymbol
-      if (probe == null) probe = NoSymbol
-      probe.initialize
-
-      def cookIfNeeded(tpt: Tree) = if (context.unit.isJava) tpt modifyType rawToExistential else tpt
-      cookIfNeeded(if (probe.isTrait || inMixinPosition) {
-        if (!argssAreTrivial) {
-          if (probe.isTrait) ConstrArgsInParentWhichIsTraitError(encodedtpt, probe)
-          else () // a class in a mixin position - this warrants an error in `validateParentClasses`
-          // therefore here we do nothing, e.g. don't check that the # of ctor arguments
-          // matches the # of ctor parameters or stuff like that
-        }
-        typedType(decodedtpt)
-      } else {
-        val supertpt = typedTypeConstructor(decodedtpt)
-        val supertparams = if (supertpt.hasSymbolField) supertpt.symbol.typeParams else Nil
-        def inferParentTypeArgs: Tree = {
-          typedPrimaryConstrBody(templ) {
-            val supertpe = PolyType(supertparams, appliedType(supertpt.tpe, supertparams map (_.tpeHK)))
-            val supercall = New(supertpe, mmap(argss)(_.duplicate))
-            val treeInfo.Applied(Select(ctor, nme.CONSTRUCTOR), _, _) = supercall: @unchecked
-            ctor setType supertpe // this is an essential hack, otherwise it will occasionally fail to typecheck
-            atPos(supertpt.pos.focus)(supercall)
-          } match {
-            case EmptyTree => MissingTypeArgumentsParentTpeError(supertpt); supertpt
-            case tpt       => TypeTree(tpt.tpe) setPos supertpt.pos  // scala/bug#7224: don't .focus positions of the TypeTree of a parent that exists in source
-          }
-        }
-
-        val supertptWithTargs = if (supertparams.isEmpty || context.unit.isJava) supertpt else inferParentTypeArgs
-
-        // this is the place where we tell the typer what argss should be used for the super call
-        // if argss are nullary or empty, then (see the docs for `typedPrimaryConstrBody`)
-        // the super call dummy is already good enough, so we don't need to do anything
-        if (argssAreTrivial) supertptWithTargs else supertptWithTargs updateAttachment SuperArgsAttachment(argss)
-      })
-    }
-
-    /** Typechecks the mishmash of trees that happen to be stuffed into the primary constructor of a given template.
-     *  Before commencing the typecheck, replaces the `pendingSuperCall` dummy with the result of `actualSuperCall`.
-     *  `actualSuperCall` can return `EmptyTree`, in which case the dummy is replaced with a literal unit.
-     *
-     *  ***Return value and side effects***
-     *
-     *  If a super call is present in the primary constructor and is not erased by the transform, returns it typechecked.
-     *  Otherwise (e.g. if the primary constructor is missing or the super call isn't there) returns `EmptyTree`.
-     *
-     *  As a side effect, this method attributes the underlying fields of early vals.
-     *  Early vals aren't typechecked anywhere else, so it's essential to call `typedPrimaryConstrBody`
-     *  at least once per definition. It'd be great to disentangle this logic at some point.
-     *
-     *  ***Example***
-     *
-     *  For the following definition:
-     *
-     *    class D extends {
-     *      val x = 2
-     *      val y = 4
-     *    } with B(x)(3) with C(y) with T
-     *
-     *  the primary constructor of `templ` will be:
-     *
-     *    Block(List(
-     *      ValDef(NoMods, x, TypeTree(), 2)
-     *      ValDef(NoMods, y, TypeTree(), 4)
-     *      global.pendingSuperCall,
-     *      Literal(Constant(())))
-     *
-     *  Note the `pendingSuperCall` part. This is the representation of a fill-me-in-later supercall dummy,
-     *  which encodes the fact that supercall argss are unknown during parsing and need to be transplanted
-     *  from one of the parent types. Read more about why the argss are unknown in `tools.nsc.ast.Trees.Template`.
-     */
-    private def typedPrimaryConstrBody(templ: Template)(actualSuperCall: => Tree): Tree =
-      treeInfo.firstConstructor(templ.body) match {
-        case ctor @ DefDef(_, _, _, vparamss, _, cbody @ Block(cstats, cunit)) =>
-          val (preSuperStats, superCall) = {
-            val (stats, rest) = cstats span (x => !treeInfo.isSuperConstrCall(x))
-            (stats map (_.duplicate), if (rest.isEmpty) EmptyTree else rest.head.duplicate)
-          }
-          val superCall1 = (superCall match {
-            case global.pendingSuperCall => actualSuperCall
-            case EmptyTree               => EmptyTree
-            case x                       => throw new MatchError(x)
-          }) orElse cunit
-          val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall1)
-          val clazz = context.owner
-          assert(clazz != NoSymbol, templ)
-          // scala/bug#9086 The position of this symbol is material: implicit search will avoid triggering
-          //         cyclic errors in an implicit search in argument to the super constructor call on
-          //         account of the "ignore symbols without complete info that succeed the implicit search"
-          //         in this source file. See `ImplicitSearch#isValid` and `ImplicitInfo#isCyclicOrErroneous`.
-          val dummy = context.outer.owner.newLocalDummy(context.owner.pos)
-          val cscope = context.outer.makeNewScope(ctor, dummy)
-          if (dummy.isTopLevel) currentRun.symSource(dummy) = currentUnit.source.file
-          val cbody2 = { // called both during completion AND typing.
-            val typer1 = newTyper(cscope)
-            // XXX: see about using the class's symbol....
-            clazz.unsafeTypeParams foreach (sym => typer1.context.scope.enter(sym))
-            typer1.namer.enterValueParams(vparamss map (_.map(_.duplicate)))
-            typer1.typed(cbody1)
-          }
-
-          val preSuperVals = treeInfo.preSuperFields(templ.body)
-          if (preSuperVals.isEmpty && preSuperStats.nonEmpty)
-            devWarning("Wanted to zip empty presuper val list with " + preSuperStats)
-          else
-            foreach2(preSuperStats, preSuperVals)((ldef, gdef) => gdef.tpt setType ldef.symbol.tpe)
-
-          if (superCall1 == cunit) EmptyTree
-          else cbody2 match { // ???
-            case Block(_, expr) => expr
-            case tree => tree
-          }
-        case _ =>
-          EmptyTree
-      }
-
-    /** Makes sure that the first type tree in the list of parent types is always a class.
-     *  If the first parent is a trait, prepend its supertype to the list until it's a class.
-     */
-    private def normalizeFirstParent(parents: List[Tree]): List[Tree] = {
-      @annotation.tailrec
-      def explode0(parents: List[Tree]): List[Tree] = {
-        val supertpt :: rest = parents: @unchecked // parents is always non-empty here - it only grows
-        if (supertpt.tpe.typeSymbol == AnyClass) {
-          supertpt setType AnyRefTpe
-          parents
-        } else if (treeInfo isTraitRef supertpt) {
-          val supertpt1  = typedType(supertpt)
-          def supersuper = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus
-          if (supertpt1.isErrorTyped) rest
-          else explode0(supersuper :: supertpt1 :: rest)
-        } else parents
       }
-
-      def explode(parents: List[Tree]) =
-        if (treeInfo isTraitRef parents.head) explode0(parents)
-        else parents
-
-      if (parents.isEmpty) Nil else explode(parents)
-    }
-
-    /** Certain parents are added in the parser before it is known whether
-     *  that class also declared them as parents. For instance, this is an
-     *  error unless we take corrective action here:
-     *
-     *    case class Foo() extends Serializable
-     *
-     *  So we strip the duplicates before typer.
-     */
-    private def fixDuplicateSyntheticParents(parents: List[Tree]): List[Tree] = parents match {
-      case Nil      => Nil
-      case x :: xs  =>
-        val sym = x.symbol
-        x :: fixDuplicateSyntheticParents(
-          if (isPossibleSyntheticParent(sym)) xs.filter(_.symbol != sym)
-          else xs
-        )
     }
 
-    def typedParentTypes(templ: Template): List[Tree] = templ.parents match {
-      case Nil => List(atPos(templ.pos)(TypeTree(AnyRefTpe)))
-      case first :: rest =>
-        try {
-          val supertpts = fixDuplicateSyntheticParents(normalizeFirstParent(
-            typedParentType(first, templ, inMixinPosition = false) +:
-              (rest map (typedParentType(_, templ, inMixinPosition = true)))))
-
-          // if that is required to infer the targs of a super call
-          // typedParentType calls typedPrimaryConstrBody to do the inferring typecheck
-          // as a side effect, that typecheck also assigns types to the fields underlying early vals
-          // however if inference is not required, the typecheck doesn't happen
-          // and therefore early fields have their type trees not assigned
-          // here we detect this situation and take preventive measures
-          if (treeInfo.hasUntypedPreSuperFields(templ.body))
-            typedPrimaryConstrBody(templ)(EmptyTree)
-
-          supertpts mapConserve (tpt => checkNoEscaping.privates(this, context.owner, tpt))
-        }
-        catch {
-          case ex: TypeError if !global.propagateCyclicReferences =>
-            // fallback in case of cyclic errors
-            // @H none of the tests enter here but I couldn't rule it out
-            // upd. @E when a definition inherits itself, we end up here
-            // because `typedParentType` triggers `initialize` for parent types symbols
-            log("Type error calculating parents in template " + templ)
-            log("Error: " + ex)
-            ParentTypesError(templ, ex)
-            List(TypeTree(AnyRefTpe))
-        }
-    }
-
-    /** <p>Check that</p>
-     *  <ul>
-     *    <li>all parents are class types,</li>
-     *    <li>first parent class is not a mixin; following classes are mixins,</li>
-     *    <li>final classes are not inherited,</li>
-     *    <li>
-     *      sealed classes are only inherited by classes which are
-     *      nested within definition of base class, or that occur within same
-     *      statement sequence,
-     *    </li>
-     *    <li>self-type of current class is a subtype of self-type of each parent class.</li>
-     *    <li>no two parents define same symbol.</li>
-     *  </ul>
-     */
-    def validateParentClasses(parents: List[Tree], selfType: Type, clazzIsTrait: Boolean): Unit = {
-      val pending = ListBuffer[AbsTypeError]()
-      def validateDynamicParent(parent: Symbol, parentPos: Position) =
-        if (parent == DynamicClass) checkFeature(parentPos, currentRun.runDefinitions.DynamicsFeature)
-
-      def validateParentClass(parent: Tree, superclazz: Symbol) =
-        if (!parent.isErrorTyped) {
-          val psym = parent.tpe.typeSymbol.initialize
 
-          if (!context.unit.isJava)
-            checkStablePrefixClassType(parent)
-
-          if (psym != superclazz) {
-            if (context.unit.isJava && psym.isJavaAnnotation) {
-              // allowed
-            } else if (psym.isTrait) {
-              val ps = psym.info.parents
-              if (!ps.isEmpty && !superclazz.isSubClass(ps.head.typeSymbol))
-                pending += ParentSuperSubclassError(parent, superclazz, ps.head.typeSymbol, psym)
-              if (!clazzIsTrait) {
-                def hasTraitParams(sym: Symbol) =
-                  sym.isScala3Defined && sym.isTrait && sym.hasAttachment[DottyParameterisedTrait]
-                // TODO perhaps there can be a flag to skip this when we know there can be no Scala 3 definitions
-                // or otherwise use an optimised representation for trait parameters
-                (parent.tpe :: ps).collectFirst {
-                  case p if hasTraitParams(p.typeSymbol) =>
-                    p.typeSymbol.attachments.get[DottyParameterisedTrait].foreach( attach =>
-                      pending += ParentIsScala3TraitError(parent, p.typeSymbol, attach.params, psym)
-                    )
-                }
-              }
-            } else {
-              pending += ParentNotATraitMixinError(parent, psym)
-            }
-          }
-
-          if (psym.isFinal)
-            pending += ParentFinalInheritanceError(parent, psym)
-
-          val sameSourceFile = context.unit.source.file == psym.sourceFile
-
-          if (!isPastTyper && psym.hasDeprecatedInheritanceAnnotation &&
-            !sameSourceFile && !context.owner.ownerChain.exists(_.isDeprecated)) {
-            val version = psym.deprecatedInheritanceVersion.getOrElse("")
-            val since   = if (version.isEmpty) version else s" (since $version)"
-            val message = psym.deprecatedInheritanceMessage.map(msg => s": $msg").getOrElse("")
-            val report  = s"inheritance from ${psym.fullLocationString} is deprecated$since$message"
-            context.deprecationWarning(parent.pos, psym, report, version)
-          }
-
-          val parentTypeOfThis = parent.tpe.dealias.typeOfThis
-
-          if (!phase.erasedTypes &&
-            !context.owner.isSynthetic &&   // don't check synthetic concrete classes for virtuals (part of DEVIRTUALIZE)
-            !context.unit.isJava &&         // don't check self types for Java (scala/bug#11917)
-            !selfType.isErroneous &&
-            !parent.tpe.isErroneous &&
-            !(selfType <:< parentTypeOfThis)
-          ) {
-            pending += ParentSelfTypeConformanceError(parent, selfType)
-            if (settings.explaintypes.value) explainTypes(selfType, parentTypeOfThis)
-          }
-
-          if (parents exists (p => p != parent && p.tpe.typeSymbol == psym && !psym.isError))
-            pending += ParentInheritedTwiceError(parent, psym)
-
-          validateDynamicParent(psym, parent.pos)
-        }
-
-      if (!parents.isEmpty && parents.forall(!_.isErrorTyped)) {
-        val superclazz = parents.head.tpe.typeSymbol
-        for (p <- parents) validateParentClass(p, superclazz)
-      }
-
-      pending.foreach(ErrorUtils.issueTypeError)
-    }
-
-    def checkFinitary(classinfo: ClassInfoType): Unit = {
-      val clazz = classinfo.typeSymbol
-
-      for (tparam <- clazz.typeParams) {
-        if (classinfo.expansiveRefs(tparam) contains tparam) {
-          val newinfo = ClassInfoType(
-            classinfo.parents map (_.instantiateTypeParams(List(tparam), List(AnyRefTpe))),
-            classinfo.decls,
-            clazz)
-          updatePolyClassInfo(clazz, newinfo)
-          FinitaryError(tparam)
-        }
-      }
-    }
-
-    private def updatePolyClassInfo(clazz: Symbol, newinfo: ClassInfoType): clazz.type = {
-      clazz.setInfo {
-        clazz.info match {
-          case PolyType(tparams, _) => PolyType(tparams, newinfo)
-          case _ => newinfo
-        }
-      }
-    }
-
-    def typedClassDef(cdef: ClassDef): Tree = {
-      val clazz = cdef.symbol
-      currentRun.profiler.beforeTypedImplDef(clazz)
-      try {
-        val typedMods = typedModifiers(cdef.mods)
-        assert(clazz != NoSymbol, cdef)
-        reenterTypeParams(cdef.tparams)
-        val tparams1 = cdef.tparams.mapConserve(typedTypeDef)
-        val impl1 = newTyper(context.make(cdef.impl, clazz, newScope)).typedTemplate(cdef.impl, typedParentTypes(cdef.impl))
-        val impl2 = finishMethodSynthesis(impl1, clazz, context)
-        if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.typeSymbol == AnyClass)
-          checkEphemeral(clazz, impl2.body)
-
-        warnTypeParameterShadow(tparams1, clazz)
-
-        if (!isPastTyper) {
-          for (ann <- clazz.getAnnotation(DeprecatedAttr)) {
-            val m = companionSymbolOf(clazz, context)
-            if (m != NoSymbol)
-              m.moduleClass.addAnnotation(AnnotationInfo(ann.atp, ann.args, Nil))
-          }
-        }
-        treeCopy.ClassDef(cdef, typedMods, cdef.name, tparams1, impl2)
-          .setType(NoType)
-      } finally {
-        currentRun.profiler.afterTypedImplDef(clazz)
-      }
-    }
-
-    def typedModuleDef(mdef: ModuleDef): Tree = {
-      // initialize all constructors of the linked class: the type completer (Namer.methodSig)
-      // might add default getters to this object. example: "object T; class T(x: Int = 1)"
-      val linkedClass = companionSymbolOf(mdef.symbol, context)
-      if (linkedClass != NoSymbol)
-        linkedClass.info.decl(nme.CONSTRUCTOR).alternatives foreach (_.initialize)
-
-      val clazz = mdef.symbol.moduleClass
-      currentRun.profiler.beforeTypedImplDef(clazz)
-      try {
-
-        val typedMods = typedModifiers(mdef.mods)
-        assert(clazz != NoSymbol, mdef)
-        val noSerializable = (
-          (linkedClass eq NoSymbol)
-            || linkedClass.isErroneous
-            || !linkedClass.isSerializable
-            || clazz.isSerializable
-          )
-        val impl1 = newTyper(context.make(mdef.impl, clazz, newScope)).typedTemplate(mdef.impl, {
-          typedParentTypes(mdef.impl) ++ (
-            if (noSerializable) Nil
-            else {
-              clazz.makeSerializable()
-              TypeTree(SerializableTpe).setPos(clazz.pos.focus) :: Nil
-            }
-            )
-        })
-
-        val impl2 = finishMethodSynthesis(impl1, clazz, context)
-
-        if (mdef.symbol == PredefModule)
-          ensurePredefParentsAreInSameSourceFile(impl2)
-
-        treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType
-      } finally {
-        currentRun.profiler.afterTypedImplDef(clazz)
-      }
-    }
-
-    private def ensurePredefParentsAreInSameSourceFile(template: Template) = {
-      val PredefModuleFile = PredefModule.associatedFile
-      if (template.parents.exists(p => p.symbol != AnyRefClass && p.symbol.associatedFile != PredefModuleFile))
-        context.error(template.pos, s"All parents of Predef must be defined in $PredefModuleFile.")
-    }
-    /** In order to override this in the TreeCheckers Typer so synthetics aren't re-added
-     *  all the time, it is exposed here the module/class typing methods go through it.
-     *  ...but it turns out it's also the ideal spot for namer/typer coordination for
-     *  the tricky method synthesis scenarios, so we'll make it that.
-     */
-    protected def finishMethodSynthesis(templ: Template, clazz: Symbol, context: Context): Template = {
-      addSyntheticMethods(templ, clazz, context)
-    }
-    /** For flatMapping a list of trees when you want the DocDefs and Annotated
-     *  to be transparent.
-     */
-    def rewrappingWrapperTrees(f: Tree => List[Tree]): Tree => List[Tree] = {
-      case dd @ DocDef(comment, defn) => f(defn) map (stat => DocDef(comment, stat) setPos dd.pos)
-      case Annotated(annot, defn)     => f(defn) map (stat => Annotated(annot, stat))
-      case tree                       => f(tree)
-    }
-
-    protected def enterSyms(txt: Context, trees: List[Tree]) = {
-      var txt0 = txt
-      for (tree <- trees) txt0 = enterSym(txt0, tree)
-    }
-
-    protected def enterSym(txt: Context, tree: Tree): Context =
-      if (txt eq context) namer enterSym tree
-      else newNamer(txt) enterSym tree
-
-    def typedTemplate(templ0: Template, parents1: List[Tree]): Template = {
-      val templ = templ0
-      // please FIXME: uncommenting this line breaks everything
-      // val templ = treeCopy.Template(templ0, templ0.body, templ0.self, templ0.parents)
-      val clazz = context.owner
-
-      val parentTypes = parents1.map(_.tpe)
-
-      // The parents may have been normalized by typedParentTypes.
-      // We must update the info as well, or we won't find the super constructor for our now-first parent class
-      // Consider `class C ; trait T extends C ; trait U extends T`
-      // `U`'s info will start with parent `T`, but `typedParentTypes` will return `List(C, T)` (`== parents1`)
-      // now, the super call in the primary ctor will fail to find `C`'s ctor, since it bases its search on
-      // `U`'s info, not the trees.
-      //
-      // For correctness and performance, we restrict this rewrite to anonymous classes,
-      // as others have their parents in order already (it seems!), and we certainly
-      // don't want to accidentally rewire superclasses for e.g. the primitive value classes.
-      //
-      // TODO: Find an example of a named class needing this rewrite, I tried but couldn't find one.
-      if (clazz.isAnonymousClass && clazz.info.parents != parentTypes) {
-        //        println(s"updating parents of $clazz from ${clazz.info.parents} to $parentTypes")
-        updatePolyClassInfo(clazz, ClassInfoType(parentTypes, clazz.info.decls, clazz))
-      }
-
-      clazz.annotations.foreach(_.completeInfo())
-      if (templ.symbol == NoSymbol)
-        templ setSymbol clazz.newLocalDummy(templ.pos)
-      val self1 = (templ.self: @unchecked) match {
-        case vd @ ValDef(_, _, tpt, EmptyTree) =>
-          val tpt1 = checkNoEscaping.privates(
-            this,
-            clazz.thisSym,
-            treeCopy.TypeTree(tpt).setOriginal(tpt) setType vd.symbol.tpe
-          )
-          copyValDef(vd)(tpt = tpt1, rhs = EmptyTree) setType NoType
-      }
-      // was:
-      //          val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt))
-      //          treeCopy.ValDef(vd, mods, name, tpt1, EmptyTree) setType NoType
-      // but this leads to cycles for existential self types ==> #2545
-      if (self1.name != nme.WILDCARD)
-        context.scope enter self1.symbol
-
-      val selfType =
-        if (clazz.isAnonymousClass && !phase.erasedTypes)
-          intersectionType(clazz.info.parents, clazz.owner)
-        else
-          clazz.typeOfThis
-
-      // the following is necessary for templates generated later
-      assert(clazz.info.decls != EmptyScope, clazz)
-      val body1 = pluginsEnterStats(this, namer.expandMacroAnnotations(templ.body))
-      enterSyms(context.outer.make(templ, clazz, clazz.info.decls), body1)
-      if (!templ.isErrorTyped) // if `parentTypes` has invalidated the template, don't validate it anymore
-        validateParentClasses(parents1, selfType, clazz.isTrait)
-      if (clazz.isCase)
-        validateNoCaseAncestor(clazz)
-      if (clazz.isTrait && hasSuperArgs(parents1.head))
-        ConstrArgsInParentOfTraitError(parents1.head, clazz)
-
-      if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
-        checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])
-
-      val bodyWithPrimaryCtor = {
-        val primaryCtor = treeInfo.firstConstructor(body1)
-        val primaryCtor1 = primaryCtor match {
-          case DefDef(_, _, _, _, _, Block(earlyVals :+ global.pendingSuperCall, unit)) =>
-            val argss = superArgs(parents1.head) getOrElse Nil
-            val pos = wrappingPos(parents1.head.pos, primaryCtor :: argss.flatten).makeTransparent
-            val superCall = atPos(pos)(PrimarySuperCall(argss))
-            deriveDefDef(primaryCtor)(_ => Block(earlyVals :+ superCall, unit) setPos pos) setPos pos
-          case _ => primaryCtor
-        }
-        body1 mapConserve { case `primaryCtor` => primaryCtor1; case stat => stat }
-      }
-
-      val body3 = typedStats(bodyWithPrimaryCtor, templ.symbol)
-
-      if (clazz.info.firstParent.typeSymbol == AnyValClass)
-        validateDerivedValueClass(clazz, body3)
-
-      if (!clazz.isTrait && clazz.isNonBottomSubClass(ConstantAnnotationClass)) {
-        val ctors = body3.iterator.collect { case method: DefDef if method.symbol.isConstructor => method }
-        val primary = ctors.next() // there is always a primary constructor
-        if (primary.symbol.paramss.lengthIs != 1) ConstantAnnotationNeedsSingleArgumentList(primary, clazz)
-        ctors.foreach(AuxConstrInConstantAnnotation(_, clazz))
-      }
-
-
-      if (clazz.isTrait) {
-        for (decl <- clazz.info.decls if decl.isTerm && decl.isEarlyInitialized) {
-          context.warning(decl.pos, "Implementation restriction: early definitions in traits are not initialized before the super class is initialized.", WarningCategory.Other)
-        }
-      }
-
-      treeCopy.Template(templ, parents1, self1, body3) setType clazz.tpe_*
-    }
-
-    /** Remove definition annotations from modifiers (they have been saved
-     *  into the symbol's `annotations` in the type completer / namer)
-     *
-     *  However reification does need annotation definitions to proceed.
-     *  Unfortunately, AnnotationInfo doesn't provide enough info to reify it in general case.
-     *  The biggest problem is with the "atp: Type" field, which cannot be reified in some situations
-     *  that involve locally defined annotations. See more about that in Reifiers.scala.
-     *
-     *  That's why the original tree gets saved into `original` field of AnnotationInfo (happens elsewhere).
-     *  The field doesn't get pickled/unpickled and exists only during a single compilation run.
-     *  This simultaneously allows us to reify annotations and to preserve backward compatibility.
-     */
-    def typedModifiers(mods: Modifiers): Modifiers =
-      mods.copy(annotations = Nil) setPositions mods.positions
-
-    def typedValDef(vdef: ValDef): ValDef = {
-      val sym = vdef.symbol
-      currentRun.profiler.beforeTypedImplDef(sym)
-      try {
-        val valDefTyper = {
-          val maybeConstrCtx =
-            if ((sym.isParameter || sym.isEarlyInitialized) && sym.owner.isConstructor) context.makeConstructorContext
-            else context
-          newTyper(maybeConstrCtx.makeNewScope(vdef, sym))
-        }
-        valDefTyper.typedValDefImpl(vdef)
-      } finally {
-        currentRun.profiler.afterTypedImplDef(sym)
-      }
-    }
-
-    // use typedValDef instead. this version is called after creating a new context for the ValDef
-    private def typedValDefImpl(vdef: ValDef): ValDef = {
-      val sym = vdef.symbol.initialize
-      val typedMods = if (nme.isLocalName(sym.name) && sym.isPrivateThis && !vdef.mods.isPrivateLocal) {
-        // scala/bug#10009 This tree has been given a field symbol by `enterGetterSetter`, patch up the
-        // modifiers accordingly so that we can survive resetAttrs and retypechecking.
-        // Similarly, we use `sym.name` rather than `vdef.name` below to use the local name.
-        typedModifiers(vdef.mods.copy(flags = sym.flags, privateWithin = tpnme.EMPTY))
-      } else typedModifiers(vdef.mods)
-
-      sym.annotations.foreach(_.completeInfo())
-      sym.filterAnnotations(_ != UnmappableAnnotation)
-
-      val tpt1 = checkNoEscaping.privates(this, sym, transformedOr(vdef.tpt, typedType(vdef.tpt)))
-      checkNonCyclic(vdef, tpt1)
-
-      // allow trait accessors: it's the only vehicle we have to hang on to annotations that must be passed down to
-      // the field that's mixed into a subclass
-      if (sym.hasAnnotation(definitions.VolatileAttr) && !((sym hasFlag MUTABLE | LAZY) || (sym hasFlag ACCESSOR) && sym.owner.isTrait))
-        VolatileValueError(vdef)
-
-      val rhs1 =
-        if (vdef.rhs.isEmpty) {
-          if (sym.isVariable && sym.owner.isTerm && !sym.isLazy && !isPastTyper)
-            LocalVarUninitializedError(vdef)
-          vdef.rhs
-        } else {
-          val tpt2 = if (sym.hasDefault) {
-            // When typechecking default parameter, replace all type parameters in the expected type by Wildcard.
-            // This allows defining "def foo[T](a: T = 1)"
-            val tparams = sym.owner.skipConstructor.info.typeParams
-            val subst = new SubstTypeMap(tparams, WildcardType.fillList(tparams.length)) {
-              @tailrec
-              override def matches(sym: Symbol, sym1: Symbol) =
-                if (sym.isSkolem) matches(sym.deSkolemize, sym1)
-                else if (sym1.isSkolem) matches(sym, sym1.deSkolemize)
-                else super.matches(sym, sym1)
-            }
-            // allow defaults on by-name parameters
-            if (sym hasFlag BYNAMEPARAM)
-              if (tpt1.tpe.typeArgs.isEmpty) WildcardType // during erasure tpt1 is Function0
-              else subst(tpt1.tpe.typeArgs.head)
-            else subst(tpt1.tpe)
-          } else tpt1.tpe
-          transformedOrTyped(vdef.rhs, EXPRmode | BYVALmode, tpt2)
-        }
-      val vdef1 = treeCopy.ValDef(vdef, typedMods, sym.name, tpt1, checkDead(context, rhs1)) setType NoType
-      if (sym.isSynthetic && sym.name.startsWith(nme.RIGHT_ASSOC_OP_PREFIX))
-        rightAssocValDefs += ((sym, vdef1.rhs))
-      if (sym.isSynthetic && sym.owner.isClass && (tpt1.tpe eq UnitTpe) && vdef.hasAttachment[PatVarDefAttachment.type] && sym.isPrivateThis && vdef.mods.isPrivateLocal && !sym.enclClassChain.exists(_.isInterpreterWrapper)) {
-        context.warning(vdef.pos, s"Pattern definition introduces Unit-valued member of ${sym.owner.name}; consider wrapping it in `locally { ... }`.", WarningCategory.OtherMatchAnalysis)
-        vdef.removeAttachment[PatVarDefAttachment.type]
-      }
-      vdef1
-    }
-
-    /** Analyze the super constructor call to record information used later to compute parameter aliases */
-    def analyzeSuperConsructor(meth: Symbol, vparamss: List[List[ValDef]], rhs: Tree): Unit = {
-      val clazz = meth.owner
-      debuglog(s"computing param aliases for $clazz:${clazz.primaryConstructor.tpe}:$rhs")
-      val pending = ListBuffer[AbsTypeError]()
-
-      // !!! This method is redundant with other, less buggy ones.
-      def decompose(call: Tree): (Tree, List[Tree]) = call match {
-        case _ if call.isErrorTyped => // e.g. scala/bug#7636
-          (call, Nil)
-        case Apply(fn, args) =>
-          // an object cannot be allowed to pass a reference to itself to a superconstructor
-          // because of initialization issues; scala/bug#473, scala/bug#3913, scala/bug#6928.
-          foreachSubTreeBoundTo(args, clazz) { tree =>
-            if (tree.symbol.isModule)
-              pending += SuperConstrReferenceError(tree)
-            tree match {
-              case This(_) =>
-                pending += SuperConstrArgsThisReferenceError(tree)
-              case _ => ()
-            }
-          }
-          val (superConstr, preArgs) = decompose(fn)
-          val params = fn.tpe.params
-          // appending a dummy tree to represent Nil for an empty varargs (is this really necessary?)
-          val applyArgs = if (args.sizeCompare(params) < 0) args :+ EmptyTree else args take params.length
-
-          assert(sameLength(applyArgs, params) || call.isErrorTyped,
-            s"arity mismatch but call is not error typed: $clazz (params=$params, args=$applyArgs)")
-
-          (superConstr, preArgs ::: applyArgs)
-        case Block(_ :+ superCall, _) =>
-          decompose(superCall)
-        case _ =>
-          (call, Nil)
-      }
-
-      // associate superclass paramaccessors with their aliases
-      val (superConstr, superArgs) = decompose(rhs)
-      if (superConstr.symbol.isPrimaryConstructor) {
-        val superClazz = superConstr.symbol.owner
-        if (!superClazz.isJavaDefined) {
-          val superParamAccessors = superClazz.constrParamAccessors
-          if (sameLength(superParamAccessors, superArgs)) {
-            val accToSuperAcc = mutable.AnyRefMap[Symbol, Symbol]()
-            for ((superAcc, superArg@Ident(name)) <- superParamAccessors zip superArgs) {
-              if (mexists(vparamss)(_.symbol == superArg.symbol)) {
-                val ownAcc = clazz.info decl name suchThat (_.isParamAccessor) match {
-                  case acc if !acc.isDeferred && acc.hasAccessorFlag => acc.accessed
-                  case acc => acc
-                }
-                ownAcc match {
-                  case acc: TermSymbol if !acc.isVariable && !isByNameParamType(acc.info) =>
-                    accToSuperAcc(acc) = superAcc
-                  case _ =>
-                }
-              }
-            }
-            if (!accToSuperAcc.isEmpty) {
-              superConstructorCalls(clazz) = accToSuperAcc
-            }
-          }
-        }
-      }
-
-      pending.foreach(ErrorUtils.issueTypeError)
-    }
-
-    // Check for scala/bug#4842.
-    private def checkSelfConstructorArgs(ddef: DefDef, clazz: Symbol): Unit = {
-      val pending = ListBuffer[AbsTypeError]()
-      ddef.rhs match {
-        case Block(stats, expr) =>
-          val selfConstructorCall = stats.headOption.getOrElse(expr)
-          foreachSubTreeBoundTo(List(selfConstructorCall), clazz) {
-            case tree @ This(_) =>
-              pending += SelfConstrArgsThisReferenceError(tree)
-            case _ => ()
-          }
-        case _ =>
-      }
-      pending.foreach(ErrorUtils.issueTypeError)
-    }
-
-    /**
-     * Run the provided function for each sub tree of `trees` that
-     * are bound to a symbol with `clazz` as a base class.
-     *
-     * @param f This function can assume that `tree.symbol` is non null
-     */
-    private def foreachSubTreeBoundTo[A](trees: List[Tree], clazz: Symbol)(f: Tree => Unit): Unit =
-      for {
-        tree <- trees
-        subTree <- tree
-      } {
-        val sym = subTree.symbol
-        if (sym != null && sym.info.baseClasses.contains(clazz))
-          f(subTree)
-      }
-
-    /** Check if a structurally defined method violates implementation restrictions.
-     *  A method cannot be called if it is a non-private member of a refinement type
-     *  and if its parameter's types are any of:
-     *    - the self-type of the refinement
-     *    - a type member of the refinement
-     *    - an abstract type declared outside of the refinement.
-     *    - an instance of a value class
-     *  Furthermore, the result type may not be a value class either
-     */
-    def checkMethodStructuralCompatible(ddef: DefDef): Unit = {
-      val meth = ddef.symbol
-      def parentString = meth.owner.parentSymbols.filter(_ != ObjectClass) match {
-        case Nil => ""
-        case xs  => xs.map(_.nameString).mkString(" (of ", " with ", ")")
-      }
-      def fail(pos: Position, msg: String): Boolean = {
-        context.error(pos, msg)
-        false
-      }
-      /* Have to examine all parameters in all lists.
-       */
-      def paramssTypes(tp: Type): List[List[Type]] = tp match {
-        case mt @ MethodType(_, restpe) => mt.paramTypes :: paramssTypes(restpe)
-        case PolyType(_, restpe)        => paramssTypes(restpe)
-        case _                          => Nil
-      }
-      def resultType = meth.tpe_*.finalResultType
-      def nthParamPos(n1: Int, n2: Int) =
-        try ddef.vparamss(n1)(n2).pos catch { case _: IndexOutOfBoundsException => meth.pos }
-
-      def failStruct(pos: Position, what: String, where: String = "Parameter type") =
-        fail(pos, s"$where in structural refinement may not refer to $what")
-
-      foreachWithIndex(paramssTypes(meth.tpe)) { (paramList, listIdx) =>
-        foreachWithIndex(paramList) { (paramType, paramIdx) =>
-          val sym = paramType.typeSymbol
-          def paramPos = nthParamPos(listIdx, paramIdx)
-
-          /* Not enough to look for abstract types; have to recursively check the bounds
-           * of each abstract type for more abstract types. Almost certainly there are other
-           * exploitable type soundness bugs which can be seen by bounding a type parameter
-           * by an abstract type which itself is bounded by an abstract type.
-           */
-          def checkAbstract(tp0: Type, what: String): Boolean = {
-            def check(sym: Symbol): Boolean = !sym.isAbstractType || {
-              log(s"""checking $tp0 in refinement$parentString at ${meth.owner.owner.fullLocationString}""")
-              (    (!sym.hasTransOwner(meth.owner) && failStruct(paramPos, "an abstract type defined outside that refinement", what))
-                || (!sym.hasTransOwner(meth) && failStruct(paramPos, "a type member of that refinement", what))
-                || checkAbstract(sym.info.upperBound, "Type bound")
-                )
-            }
-            tp0.dealiasWidenChain forall (t => check(t.typeSymbol))
-          }
-          checkAbstract(paramType, "Parameter type")
-
-          if (sym.isDerivedValueClass)
-            failStruct(paramPos, "a user-defined value class")
-          if (paramType.isInstanceOf[ThisType] && sym == meth.owner)
-            failStruct(paramPos, "the type of that refinement (self type)")
-        }
-      }
-      if (resultType.typeSymbol.isDerivedValueClass)
-        failStruct(ddef.tpt.pos, "a user-defined value class", where = "Result type")
-    }
-
-    def typedDefDef(ddef: DefDef): DefDef = {
-      val meth = ddef.symbol.initialize
-      currentRun.profiler.beforeTypedImplDef(meth)
-      try {
-
-        reenterTypeParams(ddef.tparams)
-        reenterValueParams(ddef.vparamss)
-
-        // for `val` and `var` parameter, look at `target` meta-annotation
-        if (!isPastTyper && meth.isPrimaryConstructor) {
-          for (vparams <- ddef.vparamss; vd <- vparams) {
-            if (vd.mods.isParamAccessor) {
-              val sym = vd.symbol
-              sym.setAnnotations(sym.annotations.filter(AnnotationInfo.mkFilter(ParamTargetClass, defaultRetention = true)))
-            }
-          }
-        }
-
-        val tparams1 = ddef.tparams mapConserve typedTypeDef
-        val vparamss1 = ddef.vparamss.mapConserve(_.mapConserve(typedValDef))
-
-        warnTypeParameterShadow(tparams1, meth)
-
-        meth.annotations.foreach(_.completeInfo())
-        // we only have to move annotations around for accessors -- see annotSig as used by AccessorTypeCompleter and ValTypeCompleter
-        if (meth.isAccessor) meth.filterAnnotations(_ != UnmappableAnnotation)
-
-        for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1)
-          if (isRepeatedParamType(vparam1.symbol.tpe))
-            StarParamNotLastError(vparam1)
-
-        val tpt1 = checkNoEscaping.privates(this, meth, transformedOr(ddef.tpt, typedType(ddef.tpt)))
-        checkNonCyclic(ddef, tpt1)
-        ddef.tpt.setType(tpt1.tpe)
-        val typedMods = typedModifiers(ddef.mods)
-        val rhsAtOwner = // introduced for async, but could be universally handy
-          ddef.getAndRemoveAttachment[ChangeOwnerAttachment] match {
-            case None => ddef.rhs
-            case Some(ChangeOwnerAttachment(originalOwner)) => ddef.rhs.changeOwner(originalOwner, ddef.symbol)
-          }
-        var rhs1 =
-          if (ddef.name == nme.CONSTRUCTOR && !ddef.symbol.hasStaticFlag) { // need this to make it possible to generate static ctors
-            if (!meth.isPrimaryConstructor &&
-              (!meth.owner.isClass ||
-                meth.owner.isModuleClass ||
-                meth.owner.isAnonOrRefinementClass))
-              InvalidConstructorDefError(ddef)
-            typed(rhsAtOwner)
-          } else if (meth.isMacro) {
-            // typechecking macro bodies is sort of unconventional
-            // that's why we employ our custom typing scheme orchestrated outside of the typer
-            transformedOr(rhsAtOwner, typedMacroBody(this, ddef))
-          } else {
-            transformedOrTyped(rhsAtOwner, EXPRmode, tpt1.tpe)
-          }
-
-        if (meth.isClassConstructor && !isPastTyper && !meth.owner.isSubClass(AnyValClass) && !meth.isJava) {
-          // There are no supercalls for AnyVal or constructors from Java sources, which
-          // would blow up in analyzeSuperConsructor; there's nothing to be computed for them anyway.
-          if (meth.isPrimaryConstructor)
-            analyzeSuperConsructor(meth, vparamss1, rhs1)
-          else
-            checkSelfConstructorArgs(ddef, meth.owner)
-        }
-
-        if (tpt1.tpe.typeSymbol != NothingClass && !context.returnsSeen && rhs1.tpe.typeSymbol != NothingClass)
-          rhs1 = checkDead(context, rhs1)
-
-        if (!isPastTyper) {
-          if (meth.owner.isClass && meth.paramss.exists(ps => ps.exists(_.hasDefault) && isRepeatedParamType(ps.last.tpe)))
-            StarWithDefaultError(meth)
-
-          for (pp <- meth.paramss ; p <- pp)
-            for (n <- p.deprecatedParamName)
-              if (mexists(meth.paramss)(p1 => p != p1 && (p1.name == n || p1.deprecatedParamName.contains(n))))
-                DeprecatedParamNameError(p, n)
-
-          if (settings.multiargInfix && !meth.isConstructor && meth.owner.isClass && !meth.isDeprecated && !meth.hasAnnotation(UnusedClass) && !meth.ownerChain.exists(_.isDeprecated) && !meth.isSynthetic)
-            meth.paramss match {
-              case (h :: _ :: _) :: Nil if !h.isImplicit && Chars.isOperatorPart(meth.name.decoded.head) =>
-                warnMultiargInfix(ddef)
-              case _ =>
-            }
-
-          if (meth.isStructuralRefinementMember)
-            checkMethodStructuralCompatible(ddef)
-
-          if (meth.isImplicit && !meth.isSynthetic) meth.paramss match {
-            case List(param) :: _ if !param.isImplicit =>
-              checkFeature(ddef.pos, currentRun.runDefinitions.ImplicitConversionsFeature, meth.toString)
-            case _ =>
-          }
-        }
-
-        treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
-      } finally {
-        currentRun.profiler.afterTypedImplDef(meth)
-      }
-    }
-
-    def typedTypeDef(tdef: TypeDef): TypeDef =
-      typerWithCondLocalContext(context.makeNewScope(tdef, tdef.symbol))(tdef.tparams.nonEmpty) {
-        _.typedTypeDefImpl(tdef)
-      }
-
-    // use typedTypeDef instead. this version is called after creating a new context for the TypeDef
-    private def typedTypeDefImpl(tdef: TypeDef): TypeDef = {
-      tdef.symbol.initialize
-      reenterTypeParams(tdef.tparams)
-      val tparams1 = tdef.tparams mapConserve typedTypeDef
-      val typedMods = typedModifiers(tdef.mods)
-      tdef.symbol.annotations.foreach(_.completeInfo())
-
-      warnTypeParameterShadow(tparams1, tdef.symbol)
-
-      // @specialized should not be pickled when compiling with -no-specialize
-      if (settings.nospecialization.value && currentRun.compiles(tdef.symbol)) {
-        tdef.symbol.removeAnnotation(definitions.SpecializedClass)
-        tdef.symbol.deSkolemize.removeAnnotation(definitions.SpecializedClass)
-      }
-
-      val rhs1 = checkNoEscaping.privates(this, tdef.symbol, typedType(tdef.rhs))
-      checkNonCyclic(tdef.symbol)
-      if (tdef.symbol.owner.isType)
-        rhs1.tpe match {
-          case TypeBounds(lo1, hi1) if !(lo1 <:< hi1) => LowerBoundError(tdef, lo1, hi1)
-          case _                                      => ()
-        }
-
-      treeCopy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs1) setType NoType
-    }
-
-    private def enterLabelDef(stat: Tree): Unit = {
-      stat match {
-        case ldef @ LabelDef(_, _, _) =>
-          if (ldef.symbol == NoSymbol)
-            ldef.symbol = namer.enterInScope(
-              context.owner.newLabel(ldef.name, ldef.pos) setInfo MethodType(Nil, UnitTpe))
-        case _ =>
-      }
-    }
-
-    def typedLabelDef(ldef: LabelDef): LabelDef = {
-      if (!nme.isLoopHeaderLabel(ldef.symbol.name) || isPastTyper) {
-        val restpe = ldef.symbol.tpe.resultType
-        val rhs1 = typed(ldef.rhs, restpe)
-        ldef.params foreach (param => param setType param.symbol.tpe)
-        deriveLabelDef(ldef)(_ => rhs1) setType restpe
-      }
-      else {
-        val initpe = ldef.symbol.tpe.resultType
-        val rhs1 = typed(ldef.rhs)
-        val restpe = rhs1.tpe
-        if (restpe == initpe) { // stable result, no need to check again
-          ldef.params foreach (param => param setType param.symbol.tpe)
-          treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
-        } else {
-          context.scope.unlink(ldef.symbol)
-          val sym2 = namer.enterInScope(
-            context.owner.newLabel(ldef.name, ldef.pos) setInfo MethodType(Nil, restpe))
-          val LabelDef(_, _, rhs1) = resetAttrs(ldef): @unchecked
-          val rhs2 = typed(brutallyResetAttrs(rhs1), restpe)
-          ldef.params foreach (param => param setType param.symbol.tpe)
-          deriveLabelDef(ldef)(_ => rhs2) setSymbol sym2 setType restpe
-        }
-      }
-    }
-
-    def typedBlock(block0: Block, mode: Mode, pt: Type): Block = {
-      val syntheticPrivates = new ListBuffer[Symbol]
-      try {
-        namer.enterSyms(block0.stats)
-        val block = treeCopy.Block(block0, pluginsEnterStats(this, namer.expandMacroAnnotations(block0.stats)), block0.expr)
-        for (stat <- block.stats) enterLabelDef(stat)
-
-        if (phaseId(currentPeriod) <= currentRun.typerPhase.id) {
-          // This is very tricky stuff, because we are navigating the Scylla and Charybdis of
-          // anonymous classes and what to return from them here. On the one hand, we cannot admit
-          // every non-private member of an anonymous class as a part of the structural type of the
-          // enclosing block. This runs afoul of the restriction that a structural type may not
-          // refer to an enclosing type parameter or abstract types (which in turn is necessitated
-          // by what can be done in Java reflection). On the other hand, making every term member
-          // private conflicts with private escape checking - see ticket #3174 for an example.
-          //
-          // The cleanest way forward is if we would find a way to suppress structural type checking
-          // for these members and maybe defer type errors to the places where members are called.
-          // But that would be a big refactoring and also a big departure from existing code. The
-          // probably safest fix for 2.8 is to keep members of an anonymous class that are not
-          // mentioned in a parent type private (as before) but to disable escape checking for code
-          // that's in the same anonymous class. That's what's done here.
-          //
-          // We really should go back and think hard whether we find a better way to address the
-          // problem of escaping idents on the one hand and well-formed structural types on the
-          // other.
-          block match {
-            case Block(List(classDef @ ClassDef(_, _, _, _)), Apply(Select(New(_), _), _)) =>
-              val classDecls = classDef.symbol.info.decls
-              lazy val visibleMembers =
-                pt.members match {
-                  case _: ErrorScope => classDecls.toList
-                  case ms => ms
-                }
-
-              def matchesVisibleMember(member: Symbol) = visibleMembers exists { vis =>
-                (member.name == vis.name) &&
-                  (member.tpe <:< vis.tpe.substThis(vis.owner, classDef.symbol))
-              }
-              // The block is an anonymous class definitions/instantiation pair
-              //   -> members that are hidden by the type of the block are made private
-              classDecls foreach { toHide =>
-                if (toHide.isTerm
-                  && toHide.isPossibleInRefinement
-                  && toHide.isPublic
-                  && !matchesVisibleMember(toHide)) {
-                  (toHide
-                    resetFlag (PROTECTED | LOCAL)
-                    setFlag (PRIVATE | SYNTHETIC_PRIVATE)
-                    setPrivateWithin NoSymbol)
-
-                  syntheticPrivates += toHide
-                }
-              }
-
-            case _ =>
-          }
-        }
-        val statsTyped = typedStats(block.stats, context.owner)
-        val expr1 = typed(block.expr, mode &~ (FUNmode | QUALmode | APPSELmode), pt)
-
-        // Remove ValDef for right-associative by-value operator desugaring which has been inlined into expr1
-        val statsTyped2 = statsTyped match {
-          case (vd: ValDef) :: Nil if inlinedRightAssocValDefs.remove(vd.symbol) => Nil
-          case _ => statsTyped
-        }
-
-        treeCopy.Block(block, statsTyped2, expr1)
-          .setType(if (treeInfo.isExprSafeToInline(block)) expr1.tpe else expr1.tpe.deconst)
-      } finally {
-        // enable escaping privates checking from the outside and recycle
-        // transient flag
-        syntheticPrivates foreach (_ resetFlag SYNTHETIC_PRIVATE)
-      }
-    }
-
-    def typedCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = {
-      // verify no _* except in last position
-      for (Apply(_, xs) <- cdef.pat ; x <- xs dropRight 1 ; if treeInfo isStar x)
-        StarPositionInPatternError(x)
-
-      // withoutAnnotations - see continuations-run/z1673.scala
-      // This adjustment is awfully specific to continuations, but AFAICS the
-      // whole AnnotationChecker framework is.
-      val pat1 = typedPattern(cdef.pat, pattpe.withoutAnnotations)
-
-      for (bind @ Bind(name, _) <- cdef.pat) {
-        val sym = bind.symbol
-        if (name.toTermName != nme.WILDCARD && sym != null) {
-          if (sym == NoSymbol) {
-            if (context.scope.lookup(name) == NoSymbol)
-              namer.enterInScope(context.owner.newErrorSymbol(name))
-          } else
-            namer.enterIfNotThere(sym)
-        }
-      }
-
-      val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree
-      else typed(cdef.guard, BooleanTpe)
-      var body1: Tree = typed(cdef.body, pt)
-
-      if (context.enclosingCaseDef.savedTypeBounds.nonEmpty) {
-        body1 modifyType context.enclosingCaseDef.restoreTypeBounds
-        // insert a cast if something typechecked under the GADT constraints,
-        // but not in real life (i.e., now that's we've reset the method's type skolems'
-        //   infos back to their pre-GADT-constraint state)
-        if (isFullyDefined(pt) && !(body1.tpe <:< pt)) {
-          log(s"Adding cast to pattern because ${body1.tpe} does not conform to expected type $pt")
-          body1 = typedPos(body1.pos)(gen.mkCast(body1, pt.dealiasWiden))
-        }
-      }
-
-      //    body1 = checkNoEscaping.locals(context.scope, pt, body1)
-      treeCopy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe
-    }
-
-    def typedCases(cases: List[CaseDef], pattp: Type, pt: Type): List[CaseDef] =
-      cases mapConserve { cdef =>
-        newTyper(context.makeNewScope(cdef, context.owner)).typedCase(cdef, pattp, pt)
-      }
-
-    def adaptCase(cdef: CaseDef, mode: Mode, tpe: Type): CaseDef = deriveCaseDef(cdef)(adapt(_, mode, tpe))
-
-    def packedTypes(trees: List[Tree]): List[Type] = trees map (c => packedType(c, context.owner).deconst)
-
-    // takes untyped sub-trees of a match and type checks them
-    def typedMatch(selector: Tree, cases: List[CaseDef], mode: Mode, pt: Type, tree: Tree = EmptyTree): Match = {
-      val selector1  = checkDead(context, typedByValueExpr(selector))
-      val selectorTp = packCaptured(selector1.tpe.widen).skolemizeExistential(context.owner, selector)
-      val casesTyped = typedCases(cases, selectorTp, pt)
-
-      def finish(cases: List[CaseDef], matchType: Type) =
-        treeCopy.Match(tree, selector1, cases) setType matchType
-
-      if (isFullyDefined(pt))
-        finish(casesTyped, pt)
-      else packedTypes(casesTyped) match {
-        case packed if sameWeakLubAsLub(packed) => finish(casesTyped, lub(packed))
-        case packed                             =>
-          val lub = weakLub(packed)
-          finish(casesTyped map (adaptCase(_, mode, lub)), lub)
-      }
-    }
-
-    /** synthesize and type check a PartialFunction implementation based on the match in `tree`
-     *
-     *  `param => sel match { cases }` becomes:
-     *
-     *  new AbstractPartialFunction[\$argTp, \$matchResTp] {
-     *    def applyOrElse[A1 <: \$argTp, B1 >: \$matchResTp](\$param: A1, default: A1 => B1): B1 =
-     *       \$selector match { \$cases }
-     *    def isDefinedAt(x: \$argTp): Boolean =
-     *       \$selector match { \$casesTrue }
-     *  }
-     *
-     * TODO: it would be nicer to generate the tree specified above at once and type it as a whole,
-     * there are two gotchas:
-     *    - matchResTp may not be known until we've typed the match (can only use resTp when it's fully defined),
-     *       - if we typed the match in isolation first, you'd know its result type, but would have to re-jig the owner structure
-     *       - could we use a type variable for matchResTp and backpatch it?
-     *    - occurrences of `this` in `cases` or `sel` must resolve to the this of the class originally enclosing the match,
-     *      not of the anonymous partial function subclass
-     *
-     * an alternative TODO: add partial function AST node or equivalent and get rid of this synthesis --> do everything in uncurry (or later)
-     * however, note that pattern matching codegen is designed to run *before* uncurry
-     */
-    def synthesizePartialFunction(paramName: TermName, paramPos: Position, paramSynthetic: Boolean,
-                                  tree: Tree, mode: Mode, pt: Type): Tree = {
-      assert(pt.typeSymbol == PartialFunctionClass, s"PartialFunction synthesis for match in $tree requires PartialFunction expected type, but got $pt.")
-      val (argTp, resTp) = partialFunctionArgResTypeFromProto(pt)
-
-      // if argTp isn't fully defined, we can't translate --> error
-      // NOTE: resTp still might not be fully defined
-      if (!isFullyDefined(argTp)) {
-        MissingParameterTypeAnonMatchError(tree, pt)
-        return setError(tree)
-      }
-
-      // targs must conform to Any for us to synthesize an applyOrElse (fallback to apply otherwise -- typically for @cps annotated targs)
-      val targsValidParams = (argTp <:< AnyTpe) && (resTp <:< AnyTpe)
-
-      val anonClass = context.owner newAnonymousFunctionClass tree.pos addAnnotation SerialVersionUIDAnnotation
-
-      import CODE._
-
-      val Match(sel, cases) = tree: @unchecked
-
-      // need to duplicate the cases before typing them to generate the apply method, or the symbols will be all messed up
-      val casesTrue = cases.map(deriveCaseDef(_)(x => atPos(x.pos.focus)(TRUE)).duplicate)
-
-      // must generate a new tree every time
-      def selector(paramSym: Symbol): Tree = gen.mkUnchecked(
-        if (sel != EmptyTree) sel.duplicate
-        else atPos(tree.pos.focusStart)(
-          // scala/bug#6925: subsume type of the selector to `argTp`
-          // we don't want/need the match to see the `A1` type that we must use for variance reasons in the method signature
-          //
-          // this failed: replace `selector` by `Typed(selector, TypeTree(argTp))` -- as it's an upcast, this should never fail,
-          //   `(x: A1): A` doesn't always type check, even though `A1 <: A`, due to singleton types (test/files/pos/t4269.scala)
-          // hence the cast, which will be erased in posterasure
-          // (the cast originally caused  extremely weird types to show up
-          //  in test/scaladoc/run/scala/bug#5933.scala because `variantToSkolem` was missing `tpSym.initialize`)
-          gen.mkCastPreservingAnnotations(Ident(paramSym), argTp)
-        ))
-
-      def mkParam(methodSym: Symbol, tp: Type = argTp) =
-        methodSym.newValueParameter(paramName, paramPos.focus, SYNTHETIC) setInfo tp
-
-      def mkDefaultCase(body: Tree) =
-        atPos(tree.pos.makeTransparent) {
-          CaseDef(Bind(nme.DEFAULT_CASE, Ident(nme.WILDCARD)), body)
-        }
-
-      def synthMethodTyper(methodSym: MethodSymbol) = {
-        val ctx = context.makeNewScope(context.tree, methodSym)
-        // scala/bug#10291 make sure `Return`s are linked to the original enclosing method, not the one we're synthesizing
-        ctx.enclMethod = context.enclMethod
-        newTyper(ctx)
-      }
-
-      // `def applyOrElse[A1 <: $argTp, B1 >: $matchResTp](x: A1, default: A1 => B1): B1 =
-      //  ${`$selector match { $cases; case default$ => default(x) }`
-      def applyOrElseMethodDef = {
-        val methodSym = anonClass.newMethod(nme.applyOrElse, tree.pos, FINAL | OVERRIDE)
-
-        // create the parameter that corresponds to the function's parameter
-        val A1 = methodSym.newTypeParameter(newTypeName("A1")).setInfo(TypeBounds.upper(argTp))
-        val x = mkParam(methodSym, A1.tpe)
-
-        // applyOrElse's default parameter:
-        val B1 = methodSym.newTypeParameter(newTypeName("B1")).setInfo(TypeBounds.empty)
-        val default = methodSym.newValueParameter(newTermName("default"), tree.pos.focus, SYNTHETIC) setInfo functionType(List(A1.tpe), B1.tpe)
-
-        val paramSyms = List(x, default)
-        methodSym setInfo genPolyType(List(A1, B1), MethodType(paramSyms, B1.tpe))
-
-        val methodBodyTyper = synthMethodTyper(methodSym)
-        if (!paramSynthetic) methodBodyTyper.context.scope enter x
-
-        // First, type without the default case; only the cases provided
-        // by the user are typed. The LUB of these becomes `B`, the lower
-        // bound of `B1`, which in turn is the result type of the default
-        // case
-        val match0 = methodBodyTyper.typedMatch(selector(x), cases, mode, resTp)
-        val matchResTp = match0.tpe
-
-        B1 setInfo TypeBounds.lower(matchResTp) // patch info
-
-        // the default uses applyOrElse's first parameter since the scrut's type has been widened
-        val match_ = {
-          val cdef = mkDefaultCase(methodBodyTyper.typed1(REF(default).APPLY(REF(x)), mode, B1.tpe).setType(B1.tpe))
-          val List(defaultCase) = methodBodyTyper.typedCases(List(cdef), argTp, B1.tpe): @unchecked
-          treeCopy.Match(match0, match0.selector, match0.cases :+ defaultCase)
-        }
-        match_ setType B1.tpe
-
-        // scala/bug#6187 Do you really want to know? Okay, here's what's going on here.
-        //
-        //         Well behaved trees satisfy the property:
-        //
-        //         typed(tree) == typed(resetAttrs(typed(tree))
-        //
-        //         Trees constructed without low-level symbol manipulation get this for free;
-        //         references to local symbols are cleared by `ResetAttrs`, but bind to the
-        //         corresponding symbol in the re-typechecked tree. But PartialFunction synthesis
-        //         doesn't play by these rules.
-        //
-        //         During typechecking of method bodies, references to method type parameter from
-        //         the declared types of the value parameters should bind to a fresh set of skolems,
-        //         which have been entered into scope by `Namer#methodSig`. A comment therein:
-        //
-        //         "since the skolemized tparams are in scope, the TypeRefs in vparamSymss refer to skolemized tparams"
-        //
-        //         But, if we retypecheck the reset `applyOrElse`, the TypeTree of the `default`
-        //         parameter contains no type. Somehow (where?!) it recovers a type that is _almost_ okay:
-        //         `A1 => B1`. But it should really be `A1&0 => B1&0`. In the test, run/t6187.scala, this
-        //         difference results in a type error, as `default.apply(x)` types as `B1`, which doesn't
-        //         conform to the required `B1&0`
-        //
-        //         I see three courses of action.
-        //
-        //         1) synthesize a `asInstanceOf[B1]` below (I tried this first. But... ewwww.)
-        //         2) install an 'original' TypeTree that will used after ResetAttrs (the solution below)
-        //         3) Figure out how the almost-correct type is recovered on re-typechecking, and
-        //            substitute in the skolems.
-        //
-        //         For 2.11, we'll probably shift this transformation back a phase or two, so macros
-        //         won't be affected. But in any case, we should satisfy retypecheckability.
-        //
-        val originals: Map[Symbol, Tree] = {
-          def typedIdent(sym: Symbol) = methodBodyTyper.typedType(Ident(sym), mode)
-          val A1Tpt = typedIdent(A1)
-          val B1Tpt = typedIdent(B1)
-          Map(
-            x -> A1Tpt,
-            default -> gen.scalaFunctionConstr(List(A1Tpt), B1Tpt)
-          )
-        }
-        def newParam(param: Symbol): ValDef = {
-          val vd              = ValDef(param, EmptyTree)
-          val tt @ TypeTree() = vd.tpt: @unchecked
-          tt setOriginal (originals(param) setPos param.pos.focus)
-          vd
-        }
-
-        val defdef = newDefDef(methodSym, match_)(vparamss = mapParamss(methodSym)(newParam), tpt = TypeTree(B1.tpe))
-
-        (defdef, matchResTp)
-      }
-
-      // `def isDefinedAt(x: $argTp): Boolean = ${`$selector match { $casesTrue; case default$ => false } }`
-      def isDefinedAtMethod = {
-        val methodSym = anonClass.newMethod(nme.isDefinedAt, tree.pos.makeTransparent, FINAL)
-        val paramSym = mkParam(methodSym)
-
-        val methodBodyTyper = synthMethodTyper(methodSym) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)
-        if (!paramSynthetic) methodBodyTyper.context.scope enter paramSym
-        methodSym setInfo MethodType(List(paramSym), BooleanTpe)
-
-        val defaultCase = mkDefaultCase(FALSE)
-        val match_ = methodBodyTyper.typedMatch(selector(paramSym), casesTrue :+ defaultCase, mode, BooleanTpe)
-
-        DefDef(methodSym, match_)
-      }
-
-      // only used for @cps annotated partial functions
-      // `def apply(x: $argTp): $matchResTp = $selector match { $cases }`
-      def applyMethod = {
-        val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL | OVERRIDE)
-        val paramSym = mkParam(methodSym)
-
-        methodSym setInfo MethodType(List(paramSym), AnyTpe)
-
-        val methodBodyTyper = synthMethodTyper(methodSym)
-        if (!paramSynthetic) methodBodyTyper.context.scope enter paramSym
-
-        val match_ = methodBodyTyper.typedMatch(selector(paramSym), cases, mode, resTp)
-
-        val matchResTp = match_.tpe
-        methodSym setInfo MethodType(List(paramSym), matchResTp) // patch info
-
-        (DefDef(methodSym, match_), matchResTp)
-      }
-
-      def parents(resTp: Type) = addSerializable(appliedType(AbstractPartialFunctionClass.typeConstructor, List(argTp, resTp)))
-
-      val members = {
-        val (applyMeth, matchResTp) = {
-          // rig the show so we can get started typing the method body -- later we'll correct the infos...
-          // targs were type arguments for PartialFunction, so we know they will work for AbstractPartialFunction as well
-          anonClass setInfo ClassInfoType(parents(resTp), newScope, anonClass)
-
-          // somehow @cps annotations upset the typer when looking at applyOrElse's signature, but not apply's
-          // TODO: figure out the details (T @cps[U] is not a subtype of Any, but then why does it work for the apply method?)
-          if (targsValidParams) applyOrElseMethodDef
-          else applyMethod
-        }
-
-        // patch info to the class's definitive info
-        anonClass setInfo ClassInfoType(parents(matchResTp), newScope, anonClass)
-        List(applyMeth, isDefinedAtMethod)
-      }
-
-      members foreach (m => anonClass.info.decls enter m.symbol)
-
-      val typedBlock = typedPos(tree.pos, mode, pt) {
-        Block(ClassDef(anonClass, NoMods, ListOfNil, members, tree.pos.focus), atPos(tree.pos.focus)(
-          Apply(Select(New(Ident(anonClass.name).setSymbol(anonClass)), nme.CONSTRUCTOR), Nil)
-        ))
-      }
-
-      if (typedBlock.isErrorTyped) typedBlock
-      else // Don't leak implementation details into the type, see scala/bug#6575
-        typedPos(tree.pos, mode, pt) {
-          Typed(typedBlock, TypeTree(typedBlock.tpe baseType PartialFunctionClass))
-        }
-    }
-
-    /** Synthesize and type check the implementation of a type with a Single Abstract Method.
-     *
-     * Based on a type checked Function node `{ (p1: T1, ..., pN: TN) => body } : S`
-     * where `S` is the expected type that defines a single abstract method (call it `apply` for the example),
-     * that has signature `(p1: T1', ..., pN: TN'): T'`, synthesize the instantiation of the following anonymous class
-     *
-     * {{{
-     *   new S {
-     *    def apply\$body(p1: T1, ..., pN: TN): T = body
-     *    def apply(p1: T1', ..., pN: TN'): T' = apply\$body(p1,..., pN)
-     *   }
-     * }}}
-     *
-     * The `apply` method is identified by the argument `sam`; `S` corresponds to the argument `pt`,
-     * If `pt` is not fully defined, we derive `samClassTpFullyDefined` by inferring any unknown type parameters.
-     *
-     * The types T1' ... TN' and T' are derived from the method signature of the sam method,
-     * as seen from the fully defined `samClassTpFullyDefined`.
-     *
-     * The function's body is put in a (static) method in the class definition to enforce scoping.
-     * S's members should not be in scope in `body`. (Putting it in the block outside the class runs into implementation problems described below)
-     *
-     * The restriction on implicit arguments (neither S's constructor, nor sam may take an implicit argument list),
-     * is to keep the implementation of type inference (the computation of `samClassTpFullyDefined`) simple.
-     *
-     * Impl notes:
-     *   - `fun` has a FunctionType, but the expected type `pt` is some SAM type -- let's remedy that
-     *   - `fun` is fully attributed, so we'll have to wrangle some symbols into shape (owner change, vparam syms)
-     *   - after experimentation, it works best to type check function literals fully first and then adapt to a sam type,
-     *     as opposed to a sam-specific code paths earlier on in type checking (in typedFunction).
-     *     For one, we want to emit the same bytecode regardless of whether the expected
-     *     function type is a built-in FunctionN or some SAM type
-     *
-     */
-    def inferSamType(fun: Tree, pt: Type, mode: Mode): Boolean = fun match {
-      case fun@Function(vparams, _) if !isFunctionType(pt) =>
-        // TODO: can we ensure there's always a SAMFunction attachment, instead of looking up the sam again???
-        // seems like overloading complicates things?
-        val sam = samOfProto(pt)
-
-        if (!samMatchesFunctionBasedOnArity(sam, vparams)) false
-        else {
-          def fullyDefinedMeetsExpectedFunTp(pt: Type): Boolean = isFullyDefined(pt) && {
-            val samMethType = pt memberInfo sam
-            fun.tpe <:< functionType(samMethType.paramTypes, samMethType.resultType)
-          }
-
-          val samTp =
-            if (!sam.exists) NoType
-            else if (fullyDefinedMeetsExpectedFunTp(pt)) pt
-            else try {
-              val ptFullyDefined = instantiateSamFromFunction(fun.tpe, pt, sam)
-              if (ptFullyDefined <:< pt && fullyDefinedMeetsExpectedFunTp(ptFullyDefined)) {
-                debuglog(s"sam fully defined expected type: $ptFullyDefined from $pt for ${fun.tpe}")
-                ptFullyDefined
-              } else {
-                debuglog(s"Could not define type $pt using ${fun.tpe} <:< ${pt memberInfo sam} (for $sam)")
-                NoType
-              }
-            } catch {
-              case e@(_: NoInstance | _: TypeError) =>
-                debuglog(s"Error during SAM synthesis: could not define type $pt using ${fun.tpe} <:< ${pt memberInfo sam} (for $sam)\n$e")
-                NoType
-            }
-
-          if (samTp eq NoType) false
-          else {
-            /* Make a synthetic class symbol to represent the synthetic class that
-             * will be spun up by LMF for this function. This is necessary because
-             * it's possible that the SAM method might need bridges, and they have
-             * to go somewhere. Erasure knows to compute bridges for these classes
-             * just as if they were real templates extending the SAM type. */
-            val synthCls = fun.symbol.owner.newClassWithInfo(
-              name = tpnme.ANON_CLASS_NAME,
-              parents = ObjectTpe :: samTp :: Nil,
-              scope = newScope,
-              pos = sam.pos,
-              newFlags = SYNTHETIC | ARTIFACT
-            )
-
-            synthCls.info.decls.enter {
-              val newFlags = (sam.flags & ~DEFERRED) | SYNTHETIC
-              sam.cloneSymbol(synthCls, newFlags).setInfo(samTp memberInfo sam)
-            }
-
-            fun.setType(samTp)
-
-            /* Arguably I should do `fun.setSymbol(samCls)` rather than leaning
-             * on an attachment, but doing that confounds lambdalift's free var
-             * analysis in a way which does not seem to be trivially reparable. */
-            fun.updateAttachment(SAMFunction(samTp, sam, synthCls))
-
-            true
-          }
-        }
-      case _ => false
-    }
-
-    /**
-     * Deconstruct an expected function-ish type `pt` into `numVparams` argument prototypes and a result prototype.
-     *
-     * If the expected type `pt` does not denote a function-ish type with arity `numVparams`,
-     * still return the expected number of ErrorType/NoType argument protos, and WildcardType for the result.
-     *
-     * @return (argProtos, resProto) where argProtos.lengthCompare(numVparams) == 0
-     */
-    private def argsResProtosFromFun(pt: Type, numVparams: Int): (List[Type], Type) =
-      pt match {
-        case pt: OverloadedArgProto if pt.hofParamTypes.lengthCompare(numVparams) == 0 => (pt.hofParamTypes, WildcardType)
-        case _                                                                         =>
-          val FunctionSymbol = FunctionClass(numVparams)
-
-          // In case of any non-trivial type slack between `pt` and the built-in function types, we go the SAM route,
-          // as a subclass could have (crazily) implemented the apply method and introduced another abstract method
-          // to serve as the vehicle.
-          val ptNorm = pt.typeSymbol match {
-            case NoSymbol                              => NoType
-            case FunctionSymbol | PartialFunctionClass => pt
-            case _                                     =>
-              val sam = samOf(pt)
-              if (sam.exists && sam.info.params.lengthCompare(numVparams) == 0)
-                wildcardExtrapolation(methodToExpressionTp(pt memberInfo sam))
-              else pt // allow type slack (pos/6221)
-          }
-
-          unwrapWrapperTypes(ptNorm baseType FunctionSymbol) match {
-            case TypeRef(_, _, args :+ res) => (args, res) // if it's a TypeRef, we know its symbol will be FunctionSymbol
-            case _ =>
-              val dummyPt = if (pt == ErrorType) ErrorType else NoType
-              (List.fill(numVparams)(dummyPt), WildcardType) // dummyPt is in CBN position
-          }
-      }
-
-
-    /** Type check a function literal.
-     *
-     * Based on the expected type pt, potentially synthesize an instance of
-     *   - PartialFunction,
-     *   - a type with a Single Abstract Method.
-     */
-    private def typedFunction(fun: Function, mode: Mode, pt: Type): Tree = {
-      val vparams = fun.vparams
-      val numVparams = vparams.length
-      if (numVparams > definitions.MaxFunctionArity) MaxFunctionArityError(fun, s", but $numVparams given")
-      else {
-        val (argProtos, resProto) = argsResProtosFromFun(pt, numVparams)
-
-        // After typer, no need for further checks, parameter type inference or PartialFunction synthesis.
-        if (isPastTyper) doTypedFunction(fun, resProto)
-        else {
-          val paramsMissingType = mutable.ArrayBuffer.empty[ValDef] //.sizeHint(numVparams) probably useless, since initial size is 16 and max fun arity is 22
-
-          // first, try to define param types from expected function's arg types if needed
-          foreach2(vparams, argProtos) { (vparam, argpt) =>
-            // TODO: do we need to exclude vparam.symbol.isError? (I don't think so,
-            // because I don't see how we could recurse after the `setError(vparam)` call below
-            if (vparam.tpt.isEmpty) {
-              if (isFullyDefined(argpt)) vparam.tpt setType argpt
-              else paramsMissingType += vparam
-
-              if (!vparam.tpt.pos.isDefined) vparam.tpt setPos vparam.pos.focus
-            }
-          }
-
-          if (paramsMissingType.nonEmpty && pt != ErrorType) {
-            // If we can resolve the missing parameter type by undoing eta-expansion and recursing, do that -- otherwise, report error and bail
-            typedFunctionUndoingEtaExpansion(fun, mode, resProto) orElse {
-              // we ran out of things to try, missing parameter types are an irrevocable error
-              var issuedMissingParameterTypeError = false
-              paramsMissingType.foreach { vparam =>
-                setError(vparam) //  see neg/t8675b.scala (we used to set vparam.tpt to ErrorType, but that isn't as effective)
-                MissingParameterTypeError(fun, vparam, pt, withTupleAddendum = !issuedMissingParameterTypeError)
-                issuedMissingParameterTypeError = true
-              }
-
-              setError(fun)
-            }
-          } else if (numVparams == 1 && pt.typeSymbol == PartialFunctionClass) { // dodge auto-tupling with the == 1
-            // translate `x => x match { <cases> }` : PartialFunction to
-            // `new PartialFunction { def applyOrElse(x, default) = x match { <cases> } def isDefinedAt(x) = ... }`
-            val funBody = fun.body match {
-              case Match(sel, _) if sel ne EmptyTree => fun.body
-              case funBody                           =>
-                atPos(funBody.pos.makeTransparent) {
-                  Match(EmptyTree, List(CaseDef(Bind(nme.DEFAULT_CASE, Ident(nme.WILDCARD)), funBody)))
-                }
-            }
-            // go to outer context -- must discard the context that was created for the Function since we're discarding the function
-            // thus, its symbol, which serves as the current context.owner, is not the right owner
-            // you won't know you're using the wrong owner until lambda lift crashes (unless you know better than to use the wrong owner)
-            val outerTyper = newTyper(context.outer)
-            val p = vparams.head
-            if (p.tpt.tpe == null) p.tpt setType outerTyper.typedType(p.tpt).tpe
-
-            outerTyper.synthesizePartialFunction(p.name, p.pos, paramSynthetic = false, funBody, mode, pt)
-          } else doTypedFunction(fun, resProto)
-        }
-      }
-    }
-
-    /** Retry typedFunction when parameter types are missing, and they might be recovered from
-     * the method selection that was eta-expanded into `fun`.
-     *
-     * When typing `(a1: T1, ..., aN: TN) => m(a1,..., aN)`, where some Ti are not fully defined,
-     * type `m` directly (undoing eta-expansion of method m) to determine the argument types.
-     * We have to be careful to use the result of typing the method selection, as its tree
-     * may be rewritten.
-     *
-     * This tree is the result from one of:
-     *   - manual eta-expansion with named arguments (x => f(x));
-     *   - wildcard-style eta expansion (`m(_, _,)`);
-     *   - (I don't think it can result from etaExpand, because we know the argument types there.)
-     *
-     * Note that method values are a separate thing (`m _`): they have the idiosyncratic shape
-     * of `Typed(expr, Function(Nil, EmptyTree))`
-     *
-     * @return EmptyTree on failure, or a typed version of `fun` if we are successful
-     */
-    private def typedFunctionUndoingEtaExpansion(fun: Function, mode: Mode, resProto: Type) = {
-      val vparams = fun.vparams
-
-      fun.body match {
-        // we can compare arguments and parameters by name because there cannot be a binder between
-        // the function's valdefs and the Apply's arguments
-        // If all vparams are constrained by the method application, see if we can derive expected types for them.
-        // Note that not all method arguments need be references to a function param.
-        case Apply(meth, args) =>
-          // Map param with missing param type to the argument it's passed as in the eta-expanded method application
-          // This list specifies a way to compute the expected parameter type for each of our function's arguments in order.
-          // Either we already know it, and then we have a Type, or we don't, and then it's an index `idx` into
-          // the arguments passed to `meth`, so we can derive it from its MethodType
-          // (based on where the function's parameter is applied to `meth`)
-          val formalsFromApply =
-            vparams.map { vd =>
-              if (!vd.tpt.isEmpty) {
-                if (!vd.tpt.isTyped) {
-                  val vd1 = typedValDef(vd)
-                  if (vd1.isErroneous) Left(-1)
-                  else Right(vd1.tpt.tpe)
-                }
-                else Right(vd.tpt.tpe)
-              }
-              else Left(args.indexWhere {
-                case Ident(name) => name == vd.name
-                case _           => false // TODO: this does not catch eta-expansion of an overloaded method that involves numeric widening scala/bug#9738 (and maybe similar patterns?)
-              })
-            }
-
-          // If some of the vparams without type annotation was not applied to `meth`,
-          // we're not going to learn enough from typing `meth` to determine them.
-          if (formalsFromApply.contains(Left(-1))) EmptyTree
-          else {
-            // We're looking for a method (as indicated by FUNmode in the silent typed below),
-            // so let's make sure our expected type is a MethodType (of the right arity, but we can't easily say more about the argument types)
-            val methArgs = NoSymbol.newSyntheticValueParams(WildcardType.fillList(args.length))
-
-            silent(_.typed(meth, mode.forFunMode, MethodType(methArgs, resProto))).fold(EmptyTree: Tree) { methTyped =>
-              // if context.undetparams is not empty, the method was polymorphic,
-              // so we need the missing arguments to infer its type. See #871
-              if (context.undetparams.isEmpty) {
-                // If we are sure this function type provides all the necessary info, so that we won't have
-                // any undetermined argument types, recurse below (`typedFunction(fun, mode, ptUnrollingEtaExpansion)`)
-                // and rest assured we won't end up right back here (and keep recursing).
-                //
-                // Be careful to reuse methTyped -- it may have changed from meth (scala/bug#9745)!
-                //
-                // TODO: CBN / varargs / implicits? should we use formalTypes?
-                methodToExpressionTp(methTyped.tpe) match { // we don't know how many of the vparams of our function were actually applied to the method
-                  case TypeRef(_, _, argProtos :+ _) =>
-                    val argProtosRecovered =
-                      formalsFromApply.map {
-                        case Left(idx) =>
-                          val argPt = if (argProtos.isDefinedAt(idx)) argProtos(idx) else NoType // bounds check should not be needed due to expected type `MethodType(methArgs, resProto)` above
-                          if (isFullyDefined(argPt)) argPt else NoType
-                        case Right(tp) => tp
-                      }
-
-                    if (argProtosRecovered contains NoType) EmptyTree // cannot safely recurse
-                    else {
-                      val funPt = functionType(argProtosRecovered, resProto)
-                      // recursion is safe because now all parameter types can be derived from `argProtosRecovered` in the prototype `funPt` passed to typedFunction
-                      typedFunction(treeCopy.Function(fun, vparams, treeCopy.Apply(fun.body, methTyped, args)), mode, funPt)
-                    }
-                  case _ => EmptyTree
-                }
-              } else EmptyTree
-            }
-          }
-        case _ => EmptyTree
-      }
-    }
-
-    // Assuming the expected number of parameters, which all have type annotations, do the happy path.
-    private def doTypedFunction(fun: Function, bodyPt: Type) = {
-      val vparams = fun.vparams
-      val vparamSyms = vparams map { vparam =>
-        enterSym(context, vparam)
-        if (context.retyping) context.scope enter vparam.symbol
-        vparam.symbol
-      }
-      val vparamsTyped = vparams mapConserve typedValDef
-      val bodyTyped = typed(fun.body, bodyPt)
-
-      val funSym = FunctionClass(vparams.length)
-      val funTp =
-        if (phase.erasedTypes) funSym.tpe
-        else {
-          val resTp =
-            packedType(bodyTyped, fun.symbol).resultType.deconst match {
-              case ct: ConstantType if (bodyPt eq WildcardType) || (ct.widen <:< bodyPt) => ct.widen
-              case tp                                                                    => tp
-            }
-
-          appliedType(funSym, vparamSyms.map(_.tpe) :+ resTp)
-        }
-
-      treeCopy.Function(fun, vparamsTyped, bodyTyped) setType funTp
-    }
-
-    // #2624: need to infer type arguments for eta expansion of a polymorphic method
-    // context.undetparams contains clones of meth.typeParams (fresh ones were generated in etaExpand)
-    // need to run typer on tree0, since etaExpansion sets the tpe's of its subtrees to null
-    // can't type with the expected type, as we can't recreate the setup in (3) without calling typed
-    // (note that (3) does not call typed to do the polymorphic type instantiation --
-    //  it is called after the tree has been typed with a polymorphic expected result type)
-    def typedEtaExpansion(tree: Tree, mode: Mode, pt: Type): Tree = {
-      debuglog(s"eta-expanding $tree: ${tree.tpe} to $pt")
-
-      if (tree.tpe.isDependentMethodType) DependentMethodTpeConversionToFunctionError(tree, tree.tpe) // TODO: support this
-      else {
-        val expansion = etaExpand(tree, context.owner)
-        if (context.undetparams.isEmpty) typed(expansion, mode, pt)
-        else instantiate(typed(expansion, mode), mode, pt)
-      }
-    }
-
-    def typedRefinement(templ: Template): Unit = {
-      val stats = templ.body
-      namer.enterSyms(stats)
-
-      // need to delay rest of typedRefinement to avoid cyclic reference errors
-      unit.toCheck += { () =>
-        val stats1 = typedStats(stats, NoSymbol)
-        // this code kicks in only after typer, so `stats` will never be filled in time
-        // as a result, most of compound type trees with non-empty stats will fail to reify
-        // todo. investigate whether something can be done about this
-        val att = templ.attachments.get[CompoundTypeTreeOriginalAttachment].getOrElse(CompoundTypeTreeOriginalAttachment(Nil, Nil))
-        templ.removeAttachment[CompoundTypeTreeOriginalAttachment]
-        templ updateAttachment att.copy(stats = stats1)
-        for (stat <- stats1 if stat.isDef && stat.symbol.isOverridingSymbol)
-          stat.symbol setFlag OVERRIDE
-      }
-    }
-
-    def typedImport(imp : Import): Import = transformed.remove(imp) match {
-      case Some(imp1: Import) => imp1
-      case _                  => log(s"unhandled import: $imp in $unit"); imp
-    }
-
-    def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
-      val inBlock = exprOwner == context.owner
-      def includesTargetPos(tree: Tree) =
-        tree.pos.isRange && context.unit.exists && (tree.pos includes context.unit.targetPos)
-      val localTarget = stats exists includesTargetPos
-      def typedStat(stat: Tree): Tree = stat match {
-        case s if context.owner.isRefinementClass && !treeInfo.isDeclarationOrTypeDef(s) => OnlyDeclarationsError(s)
-        case imp @ Import(_, _) =>
-          imp.symbol.initialize
-          if (!imp.symbol.isError) {
-            context = context.make(imp)
-            typedImport(imp)
-          } else EmptyTree
-        // skip typechecking of statements in a sequence where some other statement includes the targetposition
-        case s if localTarget && !includesTargetPos(s) => s
-        case _ =>
-          val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
-          else newTyper(context.make(stat, exprOwner))
-          // XXX this creates a spurious dead code warning if an exception is thrown
-          // in a constructor, even if it is the only thing in the constructor.
-          val result = checkDead(context, localTyper.typedByValueExpr(stat))
-
-          if (treeInfo.isSelfOrSuperConstrCall(result)) {
-            context.inConstructorSuffix = true
-            if (treeInfo.isSelfConstrCall(result)) {
-              val called = result.symbol
-              val defined = exprOwner.enclMethod
-              if (called == defined) ConstructorRecursesError(stat)
-              else {
-                val calledPos = called.pos.pointOrElse(0)
-                val definedPos = defined.pos.pointOrElse(0)
-                if (calledPos > definedPos) ConstructorsOrderError(stat)
-                else if (calledPos == definedPos) {
-                  // Trees generated by a macro have the same position
-                  // Trees typechecked by a ToolBox have no position
-                  val constructors = defined.owner.info.decl(nme.CONSTRUCTOR).alternatives
-                  if (constructors.indexOf(called) > constructors.indexOf(defined)) ConstructorsOrderError(stat)
-                }
-              }
-            }
-          }
-          result
-      }
-
-      // TODO: adapt to new trait field encoding, figure out why this exemption is made
-      // 'accessor' and 'accessed' are so similar it becomes very difficult to
-      //follow the logic, so I renamed one to something distinct.
-      def accesses(looker: Symbol, accessed: Symbol) = (
-        accessed.isLocalToThis
-          && (accessed.isParamAccessor || looker.hasAccessorFlag && !accessed.hasAccessorFlag && accessed.isPrivate)
-        )
-
-      def checkNoDoubleDefs(scope: Scope): Unit = {
-        var e = scope.elems
-        while ((e ne null) && e.owner == scope) {
-          var e1 = scope.lookupNextEntry(e)
-          while ((e1 ne null) && e1.owner == scope) {
-            val sym = e.sym
-            val sym1 = e1.sym
-
-            /* From the spec (refchecks checks other conditions regarding erasing to the same type and default arguments):
-             *
-             * A block expression [... its] statement sequence may not contain two definitions or
-             * declarations that bind the same name --> `inBlock`
-             *
-             * It is an error if a template directly defines two matching members.
-             *
-             * A member definition $M$ _matches_ a member definition $M'$, if $M$ and $M'$ bind the same name,
-             * and one of following holds:
-             *   1. Neither $M$ nor $M'$ is a method definition.
-             *   2. $M$ and $M'$ define both monomorphic methods with equivalent argument types.
-             *   3. $M$ defines a parameterless method and $M'$ defines a method with an empty parameter list `()` or _vice versa_.
-             *   4. $M$ and $M'$ define both polymorphic methods with equal number of argument types $\overline T$, $\overline T'$
-             *      and equal numbers of type parameters $\overline t$, $\overline t'$, say,
-             *      and  $\overline T' = [\overline t'/\overline t]\overline T$.
-             */
-            if (!(accesses(sym, sym1) || accesses(sym1, sym))  // TODO: does this purely defer errors until later?
-              && (inBlock || !(sym.isMethod || sym1.isMethod) || (sym.tpe matches sym1.tpe))
-              // default getters are defined twice when multiple overloads have defaults.
-              // The error for this is deferred until RefChecks.checkDefaultsInOverloaded
-              && !sym.isErroneous && !sym1.isErroneous && !sym.hasDefault) {
-              log("Double definition detected:\n  " +
-                ((sym.getClass, sym.info, sym.ownerChain)) + "\n  " +
-                ((sym1.getClass, sym1.info, sym1.ownerChain)))
-
-              DefDefinedTwiceError(sym, sym1)
-              scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
-            }
-            e1 = scope.lookupNextEntry(e1)
-          }
-          e = e.next
-        }
-      }
-
-      def addSynthetics(stats: List[Tree], scope: Scope): List[Tree] = {
-        var newStats = new ListBuffer[Tree]
-        var moreToAdd = true
-        while (moreToAdd) {
-          val initElems = scope.elems
-          // scala/bug#5877 The decls of a package include decls of the package object. But we don't want to add
-          //         the corresponding synthetics to the package class, only to the package object class.
-          // scala/bug#6734 Locality test below is meaningless if we're not even in the correct tree.
-          //         For modules that are synthetic case companions, check that case class is defined here.
-          // scala/bug#10783 ditto for synthetic companions of derived value classes.
-          def shouldAdd(sym: Symbol): Boolean = {
-            def classDefinedHere(s: Symbol): Boolean = stats exists {
-              case t: ClassDef => t.symbol eq s
-              case _           => false
-            }
-            def shouldAddAsModule: Boolean =
-              classDefinedHere(companionSymbolOf(sym, context))
-
-            (!sym.isModule || shouldAddAsModule) && (inBlock || !context.isInPackageObject(sym, context.owner))
-          }
-          for (sym <- scope)  context.unit.synthetics.get(sym) match {
-            // OPT: shouldAdd is usually true. Call it here, rather than in the outer loop
-            case Some(tree) if shouldAdd(sym) =>
-              // if the completer set the IS_ERROR flag, retract the stat (currently only used by applyUnapplyMethodCompleter)
-              if (!sym.initialize.hasFlag(IS_ERROR))
-                newStats += typedStat(tree) // might add even more synthetics to the scope
-              context.unit.synthetics -= sym
-            case _ => ()
-          }
-          // the type completer of a synthetic might add more synthetics. example: if the
-          // factory method of a case class (i.e. the constructor) has a default.
-          moreToAdd = scope.elems ne initElems
-        }
-        if (newStats.isEmpty) stats
-        else {
-          // put default getters next to the method they belong to,
-          // same for companion objects. fixes #2489 and #4036.
-          // [Martin] This is pretty ugly. I think we could avoid
-          // this code by associating defaults and companion objects
-          // with the original tree instead of the new symbol.
-          def matches(stat: Tree, synt: Tree) = (stat, synt) match {
-            // synt is default arg for stat
-            case (DefDef(_, statName, _, _, _, _), DefDef(mods, syntName, _, _, _, _)) =>
-              mods.hasDefault && syntName.decodedName.startsWith(statName)
-
-            // synt is companion module
-            case (ClassDef(_, className, _, _), ModuleDef(_, moduleName, _)) =>
-              className.toTermName == moduleName
-
-            // synt is implicit def for implicit class (#6278)
-            case (ClassDef(cmods, cname, _, _), DefDef(dmods, dname, _, _, _, _)) =>
-              cmods.isImplicit && dmods.isImplicit && cname.toTermName == dname
-
-            // ValDef and Accessor
-            case (ValDef(_, cname, _, _), DefDef(_, dname, _, _, _, _)) =>
-              cname.getterName == dname.getterName
-
-            case _ => false
-          }
-
-          def matching(stat: Tree): List[Tree] = {
-            val (pos, neg) = newStats.partition(synt => matches(stat, synt))
-            newStats = neg
-            pos.toList
-          }
-
-          // sorting residual stats for stability (scala/bug#10343, synthetics generated by other synthetics)
-          (stats foldRight List[Tree]())((stat, res) => {
-            stat :: matching(stat) ::: res
-          }) ::: newStats.sortBy(_.symbol.name).toList
-        }
-      }
-
-      val stats1 = stats mapConserve typedStat
-      if (phase.erasedTypes) stats1
-      else {
-        val scope = if (inBlock) context.scope else context.owner.info.decls
-
-        // As packages are open, it doesn't make sense to check double definitions here. Furthermore,
-        // it is expensive if the package is large. Instead, such double definitions are checked in `Namers.enterInScope`
-        if (!context.owner.isPackageClass)
-          checkNoDoubleDefs(scope)
-
-        // Note that Java units don't have synthetics, but there's no point in making a special case (for performance or correctness),
-        // as we only type check Java units when running Scaladoc on Java sources.
-        addSynthetics(stats1, scope)
-      }
-    }
-
-    def typedArg(arg: Tree, mode: Mode, newmode: Mode, pt: Type): Tree = {
-      val typedMode = mode.onlySticky | newmode
-      val t = withCondConstrTyper(mode.inSccMode)(_.typed(arg, typedMode, pt))
-      checkDead.inMode(context, typedMode, t)
-    }
-
-    def typedArgs(args: List[Tree], mode: Mode) =
-      args mapConserve (arg => typedArg(arg, mode, NOmode, WildcardType))
-
-    /** Does function need to be instantiated, because a missing parameter
-     *  in an argument closure overlaps with an uninstantiated formal?
-     */
-    def needsInstantiation(tparams: List[Symbol], formals: List[Type], args: List[Tree]) = {
-      def isLowerBounded(tparam: Symbol) = !tparam.info.lowerBound.typeSymbol.isBottomClass
-
-      tparams.forall(isLowerBounded) && exists2(formals, args) {
-        case (formal, Function(vparams, _)) if vparams.exists(_.tpt.isEmpty) =>
-          val arity = vparams.length
-          arity <= MaxFunctionArity && (formal.baseType(FunctionClass(arity)) match {
-            case TypeRef(_, _, formalargs) =>
-              exists2(formalargs, vparams) { (formal, vparam) =>
-                vparam.tpt.isEmpty && tparams.exists(formal.contains)
-              }
-            case _ =>
-              false
-          })
-        case _ =>
-          false
-      }
-    }
-
-    def callToCompanionConstr(context: Context, calledFun: Symbol) = {
-      calledFun.isConstructor && {
-        val methCtx = context.enclMethod
-        (methCtx != NoContext) && {
-          val contextFun = methCtx.tree.symbol
-          contextFun.isPrimaryConstructor && contextFun.owner.isModuleClass &&
-            companionSymbolOf(calledFun.owner, context).moduleClass == contextFun.owner
-        }
-      }
-    }
-
-    def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: Mode, pt: Type): Tree = {
-      // TODO_NMT: check the assumption that args nonEmpty
-      def duplErrTree = setError(treeCopy.Apply(tree, fun0, args))
-      def duplErrorTree(err: AbsTypeError) = { context.issue(err); duplErrTree }
-
-      def preSelectOverloaded(fun: Tree): Tree = {
-        if (fun.hasSymbolField && fun.symbol.isOverloaded) {
-          // remove alternatives with wrong number of parameters without looking at types.
-          // less expensive than including them in inferMethodAlternative (see below).
-          def shapeType(arg: Tree): Type = arg match {
-            case Function(vparams, body) =>
-              // No need for phasedAppliedType, as we don't get here during erasure --
-              // overloading resolution happens during type checking.
-              // During erasure, the condition above (fun.symbol.isOverloaded) is false.
-              functionType(vparams map (_ => AnyTpe), shapeType(body))
-            case Match(EmptyTree, _) => // A partial function literal
-              appliedType(PartialFunctionClass, AnyTpe :: NothingTpe :: Nil)
-            case NamedArg(Ident(name), rhs) =>
-              NamedType(name, shapeType(rhs))
-            case _ =>
-              NothingTpe
-          }
-          val argtypes = args map shapeType
-          val pre = fun.symbol.tpe.prefix
-          var sym = fun.symbol filter { alt =>
-            // must use pt as expected type, not WildcardType (a tempting quick fix to #2665)
-            // now fixed by using isWeaklyCompatible in exprTypeArgs
-            // TODO: understand why exactly -- some types were not inferred anymore (`ant clean quick.bin` failed)
-            // (I had expected inferMethodAlternative to pick up the slack introduced by using WildcardType here)
-            //
-            // @PP responds: I changed it to pass WildcardType instead of pt and only one line in
-            // trunk (excluding scalacheck, which had another) failed to compile. It was this line in
-            // Types: "refs = Array(Map(), Map())".  I determined that inference fails if there are at
-            // least two invariant type parameters. See the test case I checked in to help backstop:
-            // pos/isApplicableSafe.scala.
-            isApplicableSafe(context.undetparams, followApply(pre memberType alt), argtypes, pt)
-          }
-          if (sym.isOverloaded) {
-            // retracted synthetic apply in favor of user-defined apply
-            def isRetracted(alt: Symbol) = alt.isError && alt.isSynthetic
-            // loose arity check: based on args, prefer no tupling, assume no args: _*,
-            // but keep alt with repeated params or default args, this is a loose fitting
-            def isLooseFit(alt: Symbol)  =
-              isApplicableBasedOnArity(pre memberType alt, argtypes.length, varargsStar = false, tuplingAllowed = false) || alt.tpe.params.exists(_.hasDefault)
-            sym.filter(alt => !isRetracted(alt) && isLooseFit(alt)) match {
-              case _: NoSymbol =>
-              case sym1        => sym = sym1
-            }
-          }
-          if (sym == NoSymbol) fun
-          else adaptAfterOverloadResolution(fun setSymbol sym setType pre.memberType(sym), mode.forFunMode)
-        } else fun
-      }
-
-      val fun = preSelectOverloaded(fun0)
-      val argslen = args.length
-
-      fun.tpe match {
-        case OverloadedType(pre, alts) =>
-          def handleOverloaded = {
-            val undetparams = context.undetparams
-
-            val argTpes: ListBuffer[Type] = ListBuffer.empty[Type]
-            val args1: List[Tree] = context.savingUndeterminedTypeParams() {
-              val amode = forArgMode(fun, mode)
-
-              mapWithIndex(args) { (arg, argIdx) =>
-                def typedArg0(tree: Tree, argIdxOrName: Either[Int, Name] = Left(argIdx)) = {
-                  typedArg(tree, amode, BYVALmode, OverloadedArgProto(argIdxOrName, pre, alts)(undetparams))
-                }
-
-                arg match {
-                  // scala/bug#8197/scala/bug#4592 call for checking whether this named argument could be interpreted as an assign
-                  // infer.checkNames must not use UnitType: it may not be a valid assignment, or the setter may return another type from Unit
-                  // TODO: just make it an error to refer to a non-existent named arg, as it's far more likely to be
-                  //       a typo than an assignment passed as an argument
-                  case NamedArg(lhs@Ident(name), rhs) =>
-                    // named args: only type the righthand sides ("unknown identifier" errors otherwise)
-                    // the assign is untyped; that's ok because we call doTypedApply
-                    val rhsTyped = typedArg0(rhs, Right(name))
-                    argTpes += NamedType(name, rhsTyped.tpe.deconst)
-                    treeCopy.NamedArg(arg, lhs, rhsTyped)
-                  case treeInfo.WildcardStarArg(_) =>
-                    val argTyped = typedArg0(arg)
-                    argTpes += RepeatedType(argTyped.tpe.deconst)
-                    argTyped
-                  case _ =>
-                    val argTyped = typedArg0(arg)
-                    argTpes += argTyped.tpe.deconst
-                    argTyped
-                }
-              }
-            }
-            if (context.reporter.hasErrors)
-              setError(tree)
-            else {
-              // warn about conversions applied to blocks (#9386) in lieu of fixing
-              def checkConversionsToBlockArgs(appl: Tree): Unit =
-                if (settings.warnByNameImplicit) {
-                  val treeInfo.Applied(_, _, argss) = appl
-                  val needsAdjust =
-                    argss.find {
-                      case (aiv: ApplyImplicitView) :: Nil =>
-                        aiv.args match {
-                          case Block(_, _) :: Nil => true
-                          case _ => false
-                        }
-                      case _ => false
-                    }
-                  needsAdjust.foreach(ts => context.warning(ts.head.pos, "Implicits applied to block expressions after overload resolution may have unexpected semantics", WarningCategory.LintBynameImplicit))
-                }
-              inferMethodAlternative(fun, undetparams, argTpes.toList, pt)
-              doTypedApply(tree, adaptAfterOverloadResolution(fun, mode.forFunMode, WildcardType), args1, mode, pt).tap(checkConversionsToBlockArgs)
-            }
-          }
-          handleOverloaded
-
-        case _ if currentRun.runDefinitions.isPolymorphicSignature(fun.symbol) =>
-          // Mimic's Java's treatment of polymorphic signatures as described in
-          // https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.12.3
-          //
-          // One can think of these methods as being infinitely overloaded. We create
-          // a fictitious new cloned method symbol for each call site that takes on a signature
-          // governed by a) the argument types and b) the expected type
-          val args1 = typedArgs(args, forArgMode(fun, mode))
-          val clone = fun.symbol.cloneSymbol.withoutAnnotations
-          val cloneParams = args1.map(arg => clone.newValueParameter(freshTermName()).setInfo(arg.tpe.deconst))
-          val resultType =
-            if (fun.symbol.tpe.resultType.typeSymbol != ObjectClass) fun.symbol.tpe.resultType
-            else if (isFullyDefined(pt)) pt
-            else ObjectTpe
-          clone.modifyInfo(mt => copyMethodType(mt, cloneParams, resultType))
-          val fun1 = fun.setSymbol(clone).setType(clone.info)
-          doTypedApply(tree, fun1, args1, mode, resultType).setType(resultType)
-
-        case mt @ MethodType(params, _) =>
-          val paramTypes = mt.paramTypes
-          // repeat vararg as often as needed, remove by-name
-          val formals = formalTypes(paramTypes, argslen)
-
-          /* Try packing all arguments into a Tuple and apply `fun` to that.
-           * This is the last thing which is tried (after default arguments).
-           */
-          def tryTupleApply: Tree =
-            if (phase.erasedTypes || !eligibleForTupleConversion(paramTypes, argslen)) EmptyTree
-            else {
-              val tupleArgs = List(atPos(tree.pos.makeTransparent)(gen.mkTuple(args)))
-              // expected one argument, but got 0 or >1 ==>  try applying to tuple
-              // the inner "doTypedApply" does "extractUndetparams" => restore when it fails
-              val savedUndetparams = context.undetparams
-              // May warn or error if a Unit or tuple was inserted.
-              def validate(t: Tree): Tree = {
-                // regardless of typer's mode
-                val invalidAdaptation = t.symbol != null && !checkValidAdaptation(t, args)
-                // only bail if we're typing an expression (and not inside another application)
-                if (invalidAdaptation && mode.typingExprNotFun) EmptyTree
-                else t.removeAttachment[MultiargInfixAttachment.type]       // don't warn if we tupled
-              }
-              def reset(): Tree = {
-                context.undetparams = savedUndetparams
-                EmptyTree
-              }
-              silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)).fold(reset())(validate)
-            }
-
-          /* Treats an application which uses named or default arguments.
-           * Also works if names + a vararg used: when names are used, the vararg
-           * parameter has to be specified exactly once. Note that combining varargs
-           * and defaults is ruled out by typedDefDef.
-           */
-          def tryNamesDefaults: Tree = {
-            val lencmp = compareLengths(args, formals)
-
-            def checkNotMacro() = {
-              if (treeInfo.isMacroApplication(fun))
-                tryTupleApply orElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun))
-            }
-
-            if (mt.isErroneous) duplErrTree
-            else if (mode.inPatternMode) {
-              // #2064
-              duplErrorTree(WrongNumberOfArgsError(tree, fun))
-            } else if (lencmp > 0) {
-              tryTupleApply orElse duplErrorTree {
-                val (_, argPos) = removeNames(Typer.this)(args, params)
-                TooManyArgsNamesDefaultsError(tree, fun, formals, args, argPos)
-              }
-            } else if (lencmp == 0) {
-              // we don't need defaults. names were used, so this application is transformed
-              // into a block (@see transformNamedApplication in NamesDefaults)
-              val (namelessArgs, argPos) = removeNames(Typer.this)(args, params)
-              if (namelessArgs exists (_.isErroneous)) {
-                duplErrTree
-              } else if (!allArgsArePositional(argPos) && !sameLength(formals, params))
-              // !allArgsArePositional indicates that named arguments are used to re-order arguments
-                duplErrorTree(MultipleVarargError(tree))
-              else if (allArgsArePositional(argPos) && NamedApplyBlock.unapply(fun).isEmpty) {
-                // if there's no re-ordering, and fun is not transformed, no need to transform
-                // more than an optimization, e.g. important in "synchronized { x = update-x }"
-                checkNotMacro()
-                doTypedApply(tree, fun, namelessArgs, mode, pt)
-              } else {
-                checkNotMacro()
-                transformNamedApplication(Typer.this, mode, pt)(
-                  treeCopy.Apply(tree, fun, namelessArgs), argPos)
-              }
-            } else {
-              // defaults are needed. they are added to the argument list in named style as
-              // calls to the default getters. Example:
-              //  foo[Int](a)()  ==>  foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
-
-              // scala/bug#8111 transformNamedApplication eagerly shuffles around the application to preserve
-              //         evaluation order. During this process, it calls `changeOwner` on symbols that
-              //         are transplanted underneath synthetic temporary vals.
-              //
-              //         Here, we keep track of the symbols owned by `context.owner` to enable us to
-              //         rollback, so that we don't end up with "orphaned" symbols.
-              //
-              //         TODO: Find a better way!
-              //
-              //         Note that duplicating trees would not be enough to fix this problem, we would also need to
-              //         clone local symbols in the duplicated tree to truly isolate things (in the spirit of BodyDuplicator),
-              //         or, better yet, disentangle the logic in `transformNamedApplication` so that we could
-              //         determine whether names/defaults is viable *before* transforming trees.
-              def ownerOf(sym: Symbol) = if (sym == null || sym == NoSymbol) NoSymbol else sym.owner
-              val symsOwnedByContextOwner = tree.collect {
-                case t @ (_: DefTree | _: Function) if ownerOf(t.symbol) == context.owner => t.symbol
-              }
-              def rollbackNamesDefaultsOwnerChanges(): Unit = {
-                symsOwnedByContextOwner foreach (_.owner = context.owner)
-              }
-
-              val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
-              if (fun1.isErroneous) duplErrTree
-              else {
-                val NamedApplyBlock(NamedApplyInfo(qual, targs, previousArgss, _)) = fun1: @unchecked
-                val blockIsEmpty = fun1 match {
-                  case Block(Nil, _) =>
-                    // if the block does not have any ValDef we can remove it. Note that the call to
-                    // "transformNamedApplication" is always needed in order to obtain targs/previousArgss
-                    fun1.attachments.remove[NamedApplyInfo]
-                    true
-                  case _ => false
-                }
-                val (allArgs, missing) = addDefaults(args, qual, targs, previousArgss, params, fun.pos.focus, context)
-                val funSym = fun1 match { case Block(_, expr) => expr.symbol case x => throw new MatchError(x) }
-                val lencmp2 = compareLengths(allArgs, formals)
-
-                if (!sameLength(allArgs, args) && callToCompanionConstr(context, funSym)) {
-                  duplErrorTree(ModuleUsingCompanionClassDefaultArgsError(tree))
-                } else if (lencmp2 > 0) {
-                  removeNames(Typer.this)(allArgs, params) // #3818
-                  duplErrTree
-                } else if (lencmp2 == 0) {
-                  // useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
-                  checkNotMacro()
-                  context.set(ContextMode.DiagUsedDefaults)
-                  def checkRecursive(res: Tree): Unit =
-                    if (settings.warnRecurseWithDefault && !res.isErroneous && context.owner.hasTransOwner(funSym))
-                      context.warning(res.pos, "Recursive call used default arguments instead of passing current argument values.", WarningCategory.LintRecurseWithDefault)
-
-                  doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt).tap(checkRecursive)
-                } else {
-                  rollbackNamesDefaultsOwnerChanges()
-                  tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing))
-                }
-              }
-            }
-          }
-
-          if (!sameLength(formals, args) ||   // wrong nb of arguments
-            (args exists isNamedArg) ||     // uses a named argument
-            NamedApplyBlock.unapply(fun).isDefined) {       // fun was transformed to a named apply block =>
-            // integrate this application into the block
-            if (isApplyDynamicNamed(fun) && isDynamicRewrite(fun)) typedNamedApply(tree, fun, args, mode, pt)
-            else tryNamesDefaults
-          } else {
-            val tparams = context.extractUndetparams()
-            if (tparams.isEmpty) { // all type params are defined
-              def handleMonomorphicCall: Tree = {
-                // no expected type when jumping to a match label -- anything goes (this is ok since we're typing the translation of well-typed code)
-                // ... except during erasure: we must take the expected type into account as it drives the insertion of casts!
-                // I've exhausted all other semi-clean approaches I could think of in balancing GADT magic, scala/bug#6145, CPS type-driven transforms and other existential trickiness
-                // (the right thing to do -- packing existential types -- runs into limitations in subtyping existential types,
-                //  casting breaks scala/bug#6145,
-                //  not casting breaks GADT typing as it requires sneaking ill-typed trees past typer)
-                def noExpectedType = !phase.erasedTypes && fun.symbol.isLabel && treeInfo.isSynthCaseSymbol(fun.symbol)
-
-                val args1 =
-                  if (noExpectedType)
-                    typedArgs(args, forArgMode(fun, mode))
-                  else
-                    typedArgsForFormals(args, paramTypes, forArgMode(fun, mode))
-
-                // instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case:
-                // val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo)
-                // precise(foo) : foo.type => foo.type
-                val restpe = mt.resultType(mapList(args1)(arg => gen stableTypeFor arg orElse arg.tpe))
-                def ifPatternSkipFormals(tp: Type) = tp match {
-                  case MethodType(_, rtp) if mode.inPatternMode => rtp
-                  case _ => tp
-                }
-
-                // Inline RHS of ValDef for right-associative by-value operator desugaring.
-                // Remove the ValDef also if the argument is a constant-folded reference to it.
-                var (args2, pos2) = (args1, tree.pos)
-                args1 match {
-                  case List(lit: Literal) =>
-                    lit.attachments.get[OriginalTreeAttachment] match {
-                      case Some(OriginalTreeAttachment(id: Ident)) if rightAssocValDefs.contains(id.symbol) =>
-                        inlinedRightAssocValDefs += id.symbol
-                        rightAssocValDefs.remove(id.symbol)
-                      case _ =>
-                    }
-
-                  case List(id: Ident) if rightAssocValDefs.contains(id.symbol) =>
-                    mt.params match {
-                      case List(p) if p.isByNameParam =>
-                        inlinedRightAssocValDefs += id.symbol
-                        val rhs = rightAssocValDefs.remove(id.symbol).get
-                        args2 = rhs.changeOwner(id.symbol -> context.owner) :: Nil
-                        pos2 = wrappingPos(tree :: rhs :: Nil)
-                      case _ =>
-                    }
-                  case _ =>
-                }
-
-                if (!isPastTyper && args.isEmpty && canTranslateEmptyListToNil && currentRun.runDefinitions.isListApply(fun))
-                  atPos(tree.pos)(gen.mkNil.setType(restpe))
-                else {
-                  // annoying issue with classOf that shouldn't be deconsted after typers (during fields phase)
-                  val resTp = ifPatternSkipFormals(if (isPastTyper) restpe else restpe.deconst)
-                  constfold(treeCopy.Apply(tree, fun, args2) setType resTp setPos pos2, context.owner)
-                }
-              }
-              if (settings.warnDeadCode.value) {
-                val sym = fun.symbol
-                if (sym != null && sym.isMethod && !sym.isConstructor) {
-                  val suppress = sym == Object_synchronized || (sym.isLabel && treeInfo.isSynthCaseSymbol(sym))
-                  context.withSuppressDeadArgWarning(suppress) {
-                    handleMonomorphicCall
-                  }
-                } else handleMonomorphicCall
-              } else handleMonomorphicCall
-            } else if (needsInstantiation(tparams, formals, args)) {
-              //println("needs inst "+fun+" "+tparams+"/"+(tparams map (_.info)))
-              inferExprInstance(fun, tparams)
-              doTypedApply(tree, fun, args, mode, pt)
-            } else {
-              def handlePolymorphicCall = {
-                assert(!mode.inPatternMode, mode) // this case cannot arise for patterns
-                val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
-                val strictTargs = map2(lenientTargs, tparams)((targ, tparam) =>
-                  if (targ == WildcardType) tparam.tpeHK else targ)
-                var remainingParams = paramTypes
-                def typedArgToPoly(arg: Tree, formal: Type): Tree = { //TR TODO: cleanup
-                  val lenientPt = formal.instantiateTypeParams(tparams, lenientTargs)
-                  val newmode =
-                    if (isByNameParamType(remainingParams.head)) POLYmode
-                    else POLYmode | BYVALmode
-                  if (remainingParams.tail.nonEmpty) remainingParams = remainingParams.tail
-                  val arg1 = typedArg(arg, forArgMode(fun, mode), newmode, lenientPt)
-                  val argtparams = context.extractUndetparams()
-                  if (!argtparams.isEmpty) {
-                    val strictPt = formal.instantiateTypeParams(tparams, strictTargs)
-                    inferArgumentInstance(arg1, argtparams, strictPt, lenientPt)
-                    arg1
-                  } else arg1
-                }
-                val args1 = map2(args, formals)(typedArgToPoly)
-                if (args1 exists { _.isErrorTyped }) duplErrTree
-                else {
-                  debuglog("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(_.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(_.tpe.lowerBound) + ", parambounds = " + tparams.map(_.info)) //debug
-                  // define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun"
-                  // returns those undetparams which have not been instantiated.
-                  val undetparams = inferMethodInstance(fun, tparams, args1, pt)
-                  try doTypedApply(tree, fun, args1, mode, pt)
-                  finally context.undetparams = undetparams
-                }
-              }
-              handlePolymorphicCall
-            }
-          }
-
-        case SingleType(_, _) =>
-          doTypedApply(tree, fun setType fun.tpe.widen, args, mode, pt)
-
-        case ErrorType =>
-          if (!tree.isErrorTyped) setError(tree) else tree
-        // @H change to setError(treeCopy.Apply(tree, fun, args))
-
-        // scala/bug#7877 `isTerm` needed to exclude `class T[A] { def unapply(..) }; ... case T[X] =>`
-        case HasUnapply(_) if mode.inPatternMode && fun.isTerm =>
-          doTypedUnapply(tree, fun0, fun, args, mode, pt)
-
-        case _ =>
-          if (treeInfo.isMacroApplication(tree)) duplErrorTree(MacroTooManyArgumentListsError(tree, fun.symbol))
-          else duplErrorTree(ApplyWithoutArgsError(tree, fun))
-      }
-    }
-
-    /**
-     * Convert an annotation constructor call into an AnnotationInfo.
-     */
-    def typedAnnotation(ann: Tree, annotee: Option[Tree], mode: Mode = EXPRmode): AnnotationInfo = {
-      var hasError: Boolean = false
-      var unmappable: Boolean = false
-      val pending = ListBuffer[AbsTypeError]()
-      def ErroneousAnnotation = new ErroneousAnnotation().setOriginal(ann)
-
-      def rangeFinder(): (Int, Int) =
-        if (settings.Yrangepos.value && annotee.get.pos.isDefined) {
-          val p = annotee.get.pos
-          (p.start, p.end)
-        } else {
-          // compute approximate range
-          var s = unit.source.length
-          var e = 0
-          object setRange extends ForeachTreeTraverser({ child =>
-            val pos = child.pos
-            if (pos.isDefined) {
-              s = s min pos.start
-              e = e max pos.end
-            }
-          }) {
-            // in `@nowarn @ann(deprecatedMethod) def foo`, the deprecation warning should show
-            override def traverseModifiers(mods: Modifiers): Unit = ()
-          }
-          setRange(annotee.get)
-          (s, e max s)
-        }
-      def registerNowarn(info: AnnotationInfo): Unit = {
-        if (annotee.isDefined && NowarnClass.exists && info.matches(NowarnClass) && !runReporting.suppressionExists(info.pos)) {
-          val filters = (info.assocs: @unchecked) match {
-            case Nil => List(MessageFilter.Any)
-            case (_, LiteralAnnotArg(s)) :: Nil =>
-              if (s.stringValue.isEmpty) Nil
-              else {
-                val (ms, fs) = s.stringValue.split('&').map(WConf.parseFilter(_, runReporting.rootDirPrefix)).toList.partitionMap(identity)
-                if (ms.nonEmpty)
-                  reporter.error(info.pos, s"Invalid message filter:\n${ms.mkString("\n")}")
-                fs
-              }
-          }
-          val (start, end) = rangeFinder()
-          runReporting.addSuppression(Suppression(info.pos, filters, start, end))
-        }
-      }
-      def registerDeprecationSuppression(info: AnnotationInfo): Unit =
-        if (annotee.isDefined && info.matches(DeprecatedAttr) && !runReporting.suppressionExists(info.pos)) {
-          val (start, end) = rangeFinder()
-          runReporting.addSuppression(Suppression(info.pos, List(MessageFilter.Category(WarningCategory.Deprecation)), start, end, synthetic = true))
-        }
-
-      def finish(res: AnnotationInfo): AnnotationInfo = {
-        if (hasError) {
-          pending.foreach(ErrorUtils.issueTypeError)
-          ErroneousAnnotation
-        } else {
-          registerNowarn(res)
-          registerDeprecationSuppression(res)
-          res
-        }
-      }
-
-      def reportAnnotationError(err: AbsTypeError) = {
-        pending += err
-        hasError = true
-        ErroneousAnnotation
-      }
-
-      // begin typedAnnotation
-      val treeInfo.Applied(fun0, _, argss) = ann
-      if (fun0.isErroneous) return finish(ErroneousAnnotation)
-      val typedFun = context.withinAnnotation(typed(fun0, mode.forFunMode))
-      if (typedFun.isErroneous) return finish(ErroneousAnnotation)
-
-      val Select(New(annTpt), _) = typedFun: @unchecked
-      val annType = annTpt.tpe // for a polymorphic annotation class, this type will have unbound type params (see context.undetparams)
-      val annTypeSym = annType.typeSymbol
-      val isJava = annTypeSym.isJavaDefined
-
-      val isAnnotation = annTypeSym.isJavaAnnotation || annType <:< AnnotationClass.tpe
-      if (!isAnnotation) {
-        reportAnnotationError(DoesNotExtendAnnotation(typedFun, annTypeSym))
-        return finish(ErroneousAnnotation)
-      }
-
-      /* Calling constfold right here is necessary because some trees (negated
-       * floats and literals in particular) are not yet folded.
-       */
-      def tryConst(tr: Tree, pt: Type): Option[LiteralAnnotArg] = {
-        // The typed tree may be relevantly different than the tree `tr`,
-        // e.g. it may have encountered an implicit conversion.
-        val ttree = if (isJava) typed(constfold(tr, context.owner), pt) else tr
-        val const: Constant = ttree match {
-          case l @ Literal(c) if !l.isErroneous => c
-          case tree => tree.tpe match {
-            case ConstantType(c) => c
-            case _               => null
-          }
-        }
-
-        def isDefaultArg(tree: Tree) = tree match {
-          case treeInfo.Applied(fun, _, _) => fun.symbol != null && fun.symbol.isDefaultGetter
-          case _ => false
-        }
-
-        if (const == null) {
-          if (unit.isJava) unmappable = true
-          else if (!isDefaultArg(ttree)) reportAnnotationError(AnnotationNotAConstantError(ttree))
-          None
-        } else if (const.value == null) {
-          reportAnnotationError(AnnotationArgNullError(tr)); None
-        } else
-          Some(LiteralAnnotArg(const))
-      }
-
-      /* Converts an untyped tree to a ClassfileAnnotArg. If the conversion fails,
-       * an error message is reported and None is returned.
-       */
-      @tailrec
-      def tree2ConstArg(tree: Tree, pt: Type): Option[ClassfileAnnotArg] = tree match {
-        case Apply(Select(New(_), nme.CONSTRUCTOR), _) if pt.typeSymbol == ArrayClass && unit.isJava =>
-          // In Java, a single value may be passed for array annotation parameters
-          tree2ConstArg(Apply(Select(gen.mkAttributedRef(ArrayModule), nme.apply), List(tree)), pt)
-
-        case Apply(Select(New(_), nme.CONSTRUCTOR), _) if pt.typeSymbol == ArrayClass =>
-          reportAnnotationError(ArrayConstantsError(tree)); None
-
-        case ann @ Apply(Select(New(tpt), nme.CONSTRUCTOR), _) if isJava =>
-          val annInfo = typedAnnotation(ann, None, mode)
-          val annType = annInfo.atp
-
-          if (!annType.typeSymbol.isSubClass(pt.typeSymbol))
-            reportAnnotationError(AnnotationTypeMismatchError(tpt, pt, annType))
-          else if (!annType.typeSymbol.isJavaDefined)
-            reportAnnotationError(NestedAnnotationError(ann, annType))
-
-          if (annInfo.atp.isErroneous) { hasError = true; None }
-          else Some(NestedAnnotArg(annInfo))
-
-        // use of Array.apply[T: ClassTag](xs: T*): Array[T]
-        // and    Array.apply(x: Int, xs: Int*): Array[Int]       (and similar)
-        case treeInfo.Applied(fun, targs, args :: _) =>
-          val typedFun = if (isJava) typed(fun, mode.forFunMode) else fun
-          if (typedFun.symbol.owner == ArrayModule.moduleClass && typedFun.symbol.name == nme.apply)
-            pt match {
-              case _ if !isJava =>
-                trees2ConstArg(args, targs.headOption.map(_.tpe).getOrElse(WildcardType))
-              case TypeRef(_, ArrayClass, targ :: _) =>
-                trees2ConstArg(args, targ)
-              case _ =>
-                // For classfile annotations, pt can only be T:
-                //   BT = Int, .., String, Class[_], JavaAnnotClass
-                //   T = BT | Array[BT]
-                // So an array literal as argument can only be valid if pt is Array[_]
-                reportAnnotationError(ArrayConstantsTypeMismatchError(tree, pt))
-                None
-            }
-          else tryConst(tree, pt)
-
-        case Typed(t, _) =>
-          tree2ConstArg(t, pt)
-
-        case tree if unit.isJava && pt.typeSymbol == ArrayClass =>
-          /* If we get here, we have a Java array annotation argument which was passed
-           * as a single value, and needs to be wrapped. */
-          trees2ConstArg(tree :: Nil, pt.typeArgs.head)
-
-        case tree =>
-          tryConst(tree, pt)
-      }
-      def trees2ConstArg(trees: List[Tree], pt: Type): Option[ArrayAnnotArg] = {
-        traverseOpt(trees)(tree2ConstArg(_, pt))
-          .map(args => ArrayAnnotArg(args.toArray))
-      }
-
-      @inline def constantly = {
-        // Arguments of Java annotations and ConstantAnnotations are checked to be constants and
-        // stored in the `assocs` field of the resulting AnnotationInfo
-        if (argss.lengthIs > 1) {
-          reportAnnotationError(MultipleArgumentListForAnnotationError(ann))
-        } else {
-          val annScopeJava = annType.decls.filter(sym => sym.isMethod && !sym.isConstructor && sym.isJavaDefined)
-
-          val names = mutable.Set[Symbol]()
-          names ++= annScopeJava.iterator
-
-          def hasValue = names exists (_.name == nme.value)
-          val namedArgs = argss match {
-            case List(List(arg)) if !isNamedArg(arg) && hasValue => gen.mkNamedArg(nme.value, arg) :: Nil
-            case List(args)                                      => args
-            case x                                               => throw new MatchError(x)
-          }
-
-          val nvPairs = namedArgs map {
-            case arg @ NamedArg(Ident(name), rhs) =>
-              val sym = annScopeJava.lookup(name)
-              if (sym == NoSymbol) {
-                reportAnnotationError(UnknownAnnotationNameError(arg, name))
-                (nme.ERROR, None)
-              } else if (!names.contains(sym)) {
-                reportAnnotationError(DuplicateValueAnnotationError(arg, name))
-                (nme.ERROR, None)
-              } else {
-                names -= sym
-                sym.cookJavaRawInfo() // #3429
-                val annArg = tree2ConstArg(rhs, sym.tpe.resultType)
-                (sym.name, annArg)
-              }
-            case arg =>
-              reportAnnotationError(ClassfileAnnotationsAsNamedArgsError(arg))
-              (nme.ERROR, None)
-          }
-          for (sym <- names) {
-            // make sure the flags are up to date before erroring (jvm/t3415 fails otherwise)
-            sym.initialize
-            if (!sym.hasAnnotation(AnnotationDefaultAttr) && !sym.hasDefault)
-              reportAnnotationError(AnnotationMissingArgError(ann, annType, sym))
-          }
-
-          if (hasError) ErroneousAnnotation
-          else if (unmappable) UnmappableAnnotation
-          else AnnotationInfo(annType, Nil, nvPairs.map(p => (p._1, p._2.get))).setOriginal(Apply(typedFun, namedArgs).setPos(ann.pos))
-        }
-      }
-      @inline def statically = {
-        val typedAnn: Tree = {
-          // local dummy fixes scala/bug#5544
-          val localTyper = newTyper(context.make(ann, context.owner.newLocalDummy(ann.pos)))
-          localTyper.typed(ann, mode)
-        }
-        @tailrec
-        def annInfo(t: Tree): AnnotationInfo = t match {
-          case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
-            // `tpt.tpe` is more precise than `annType`, since it incorporates the types of `args`
-            AnnotationInfo(tpt.tpe, args, Nil).setOriginal(typedAnn).setPos(t.pos)
-
-          case Block(_, expr) =>
-            if (!annTypeSym.isNonBottomSubClass(ConstantAnnotationClass))
-              context.warning(t.pos, "Usage of named or default arguments transformed this annotation\n"+
-                "constructor call into a block. The corresponding AnnotationInfo\n"+
-                "will contain references to local values and default getters instead\n"+
-                "of the actual argument trees", WarningCategory.Other)
-            annInfo(expr)
-
-          case Apply(fun, args) =>
-            context.warning(t.pos, "Implementation limitation: multiple argument lists on annotations are\n"+
-              "currently not supported; ignoring arguments "+ args, WarningCategory.Other)
-            annInfo(fun)
-
-          case _ =>
-            reportAnnotationError(UnexpectedTreeAnnotationError(t, typedAnn))
-        }
-
-        if ((typedAnn.tpe == null) || typedAnn.tpe.isErroneous) ErroneousAnnotation
-        else {
-          val info = annInfo(typedAnn)
-          // check message and since args to deprecated
-          // when deprecated gets more params, those other args may also be defaults.
-          def usesDefault = typedAnn match {
-            case Block(vals, _) => info.args.exists {
-              case Ident(n) => vals.exists {
-                case ValDef(_, `n`, _, rhs) => treeInfo.isDefaultGetter(rhs)
-                case _                      => false
-              }
-              case _ =>
-                false
-            }
-            case _ =>
-              info.args.exists(treeInfo.isDefaultGetter)
-          }
-          if (annTypeSym == DeprecatedAttr && settings.lintDeprecation && argss.head.lengthIs < 2 && usesDefault)
-            context.warning(ann.pos, """Specify both message and version: @deprecated("message", since = "1.0")""", WarningCategory.LintDeprecation)
-          info
-        }
-      }
-
-      finish {
-        if (isJava)
-          constantly
-        else {
-          val info = statically
-          if (!info.isErroneous && annTypeSym.isNonBottomSubClass(ConstantAnnotationClass)) {
-            var namedArgs: Map[Name, Tree] = Map.empty
-            val treeInfo.Applied(constr, _, _) = info.original match {
-              case Block(stats, call) =>
-                // when named / default args are used
-                namedArgs = Map.from(stats collect {
-                  case ValDef(_, name, _, rhs) => (name, rhs)
-                })
-                call
-              case call => call
-            }
-            val params = constr.symbol.paramss.headOption.getOrElse(Nil)
-            val assocs = info.args.zip(params) map {
-              case (arg, param) =>
-                val origArg = arg match {
-                  case Ident(n) => namedArgs.getOrElse(n, arg)
-                  case _ => arg
-                }
-                (param.name, tree2ConstArg(origArg, param.tpe.resultType))
-            }
-            if (hasError) ErroneousAnnotation
-            else if (unmappable) UnmappableAnnotation
-            else AnnotationInfo(info.atp, Nil, assocs.collect { case (n, Some(arg)) => (n, arg) }).setOriginal(info.original).setPos(info.pos)
-          } else
-            info
-        }
-      }
-    }
-
-    def typedMacroAnnotation(cdef: ClassDef) = {
-      val clazz = cdef.symbol
-      if (!isPastTyper) {
-        if (clazz != null && (clazz isNonBottomSubClass AnnotationClass)) {
-          val macroTransform = clazz.info.member(nme.macroTransform)
-          if (macroTransform != NoSymbol) {
-            clazz.setFlag(MACRO)
-            if (clazz.getAnnotation(CompileTimeOnlyAttr).isEmpty) clazz.addAnnotation(AnnotationInfo(CompileTimeOnlyAttr.tpe, List(Literal(Constant(MacroAnnotationNotExpandedMessage)) setType StringClass.tpe), Nil))
-            def flavorOk = macroTransform.isMacro
-            def paramssOk = mmap(macroTransform.paramss)(p => (p.name, p.info)) == List(List((nme.annottees, scalaRepeatedType(AnyTpe))))
-            def tparamsOk = macroTransform.typeParams.isEmpty
-            def everythingOk = flavorOk && paramssOk && tparamsOk
-            if (!everythingOk) MacroAnnotationShapeError(clazz)
-            if (!(clazz isNonBottomSubClass StaticAnnotationClass)) MacroAnnotationMustBeStaticError(clazz)
-            // TODO: revisit the decision about @Inherited
-            if (clazz.hasAnnotation(InheritedAttr)) MacroAnnotationCannotBeInheritedError(clazz)
-            if (!clazz.isStatic) MacroAnnotationCannotBeMemberError(clazz)
-          }
-        }
-      }
-      cdef
-    }
-
-    /** Compute an existential type from raw hidden symbols `syms` and type `tp`
-     */
-    def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, context.owner)
-
-    def isReferencedFrom(ctx: Context, sym: Symbol): Boolean =
-      ctx.owner.isTerm && ctx.scope.exists(dcl => dcl.isInitialized && dcl.info.contains(sym)) || {
-        var ctx1 = ctx.outer
-        while ((ctx1 != NoContext) && (ctx1.scope eq ctx.scope))
-          ctx1 = ctx1.outer
-
-        (ctx1 != NoContext) && isReferencedFrom(ctx1, sym)
-      }
-
-    def isCapturedExistential(sym: Symbol) =
-      (sym hasAllFlags EXISTENTIAL | CAPTURED) && {
-        val start = if (settings.areStatisticsEnabled) statistics.startTimer(isReferencedNanos) else null
-        try !isReferencedFrom(context, sym)
-        finally if (settings.areStatisticsEnabled) statistics.stopTimer(isReferencedNanos, start)
-      }
-
-    def packCaptured(tpe: Type): Type = {
-      val captured = mutable.Set[Symbol]()
-      for (tp <- tpe)
-        if (isCapturedExistential(tp.typeSymbol))
-          captured += tp.typeSymbol
-      existentialAbstraction(captured.toList, tpe)
-    }
-
-    /** convert local symbols and skolems to existentials */
-    def packedType(tree: Tree, owner: Symbol): Type = {
-      def defines(tree: Tree, sym: Symbol) = (
-        sym.isExistentialSkolem && sym.unpackLocation == tree
-          || tree.isDef && tree.symbol == sym
-        )
-      def isVisibleParameter(sym: Symbol) = (
-        sym.isParameter
-          && (sym.owner == owner)
-          && (sym.isType || !owner.isAnonymousFunction)
-        )
-      def containsDef(owner: Symbol, sym: Symbol): Boolean =
-        (!sym.hasPackageFlag) && {
-          var o = sym.owner
-          while (o != owner && o != NoSymbol && !o.hasPackageFlag) o = o.owner
-          o == owner && !isVisibleParameter(sym)
-        }
-      val localSyms = mutable.LinkedHashSet[Symbol]()
-      val boundSyms = mutable.LinkedHashSet[Symbol]()
-      def isLocal(sym: Symbol): Boolean =
-        if (sym == NoSymbol || sym.isRefinementClass || sym.isLocalDummy) false
-        else if (owner == NoSymbol) tree exists (defines(_, sym))
-        else containsDef(owner, sym) || isRawParameter(sym) || isCapturedExistential(sym)
-      def containsLocal(tp: Type): Boolean =
-        tp exists (t => isLocal(t.typeSymbol) || isLocal(t.termSymbol))
-
-      val dealiasLocals = new TypeMap {
-        @tailrec
-        def apply(tp: Type): Type = tp match {
-          case TypeRef(pre, sym, _) =>
-            if (sym.isAliasType && containsLocal(tp) && (tp.dealias ne tp)) apply(tp.dealias)
-            else {
-              if (pre.isVolatile) pre match {
-                case SingleType(_, sym) if sym.isSynthetic && isPastTyper =>
-                  debuglog(s"ignoring volatility of prefix in pattern matcher generated inferred type: $tp") // See pos/t7459c.scala
-                case _ =>
-                  InferTypeWithVolatileTypeSelectionError(tree, pre)
-              }
-              mapOver(tp)
-            }
-          case _ =>
-            mapOver(tp)
-        }
-      }
-      // add all local symbols of `tp` to `localSyms`
-      // TODO: expand higher-kinded types into individual copies for each instance.
-      def addLocals(tp: Type): Unit = {
-        val remainingSyms = new ListBuffer[Symbol]
-        def addIfLocal(sym: Symbol, tp: Type): Unit = {
-          if (isLocal(sym) && !localSyms(sym) && !boundSyms(sym)) {
-            if (sym.typeParams.isEmpty) {
-              localSyms += sym
-              remainingSyms += sym
-            } else {
-              AbstractExistentiallyOverParamerizedTpeError(tree, tp)
-            }
-          }
-        }
-
-        for (t <- tp) {
-          t match {
-            case ExistentialType(tparams, _) =>
-              boundSyms ++= tparams
-            case AnnotatedType(annots, _) =>
-              for (annot <- annots; arg <- annot.args) {
-                arg match {
-                  case Ident(_) =>
-                    // Check the symbol of an Ident, unless the
-                    // Ident's type is already over an existential.
-                    // (If the type is already over an existential,
-                    // then remap the type, not the core symbol.)
-                    if (!arg.tpe.typeSymbol.hasFlag(EXISTENTIAL))
-                      addIfLocal(arg.symbol, arg.tpe)
-                  case _ => ()
-                }
-              }
-            case _ =>
-          }
-          addIfLocal(t.termSymbol, t)
-          addIfLocal(t.typeSymbol, t)
-        }
-        for (sym <- remainingSyms) addLocals(sym.existentialBound)
-      }
-
-      val dealiasedType = dealiasLocals(tree.tpe)
-      addLocals(dealiasedType)
-      packSymbols(localSyms.toList, dealiasedType)
-    }
-
-    def typedClassOf(tree: Tree, tpt: Tree, noGen: Boolean = false) =
-      if (!checkClassOrModuleType(tpt) && noGen) tpt
-      else atPos(tree.pos)(gen.mkClassOf(tpt.tpe))
-
-    protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Mode): Tree = {
-      for (wc <- tree.whereClauses)
-        if (wc.symbol == NoSymbol) { namer enterSym wc; wc.symbol setFlag EXISTENTIAL }
-        else context.scope enter wc.symbol
-      val whereClauses1 = typedStats(tree.whereClauses, context.owner)
-      for (vd @ ValDef(_, _, _, _) <- whereClauses1)
-        if (vd.symbol.tpe.isVolatile)
-          AbstractionFromVolatileTypeError(vd)
-      val tpt1 = typedType(tree.tpt, mode)
-      existentialTransform(whereClauses1 map (_.symbol), tpt1.tpe)((tparams, tp) => {
-        val original = tpt1 match {
-          case tpt : TypeTree => atPos(tree.pos)(ExistentialTypeTree(tpt.original, tree.whereClauses))
-          case _ =>
-            debuglog(s"cannot reconstruct the original for $tree, because $tpt1 is not a TypeTree")
-            tree
-        }
-        TypeTree(newExistentialType(tparams, tp)) setOriginal original
-      }
-      )
-    }
-
-    // lifted out of typed1 because it's needed in typedImplicit0
-    protected def typedTypeApply(tree: Tree, mode: Mode, fun: Tree, args: List[Tree]): Tree = fun.tpe match {
-      case OverloadedType(_, _) =>
-        inferPolyAlternatives(fun, mapList(args)(_.tpe))
-
-        // scala/bug#8267 `memberType` can introduce existentials *around* a PolyType/MethodType, see AsSeenFromMap#captureThis.
-        //         If we had selected a non-overloaded symbol, `memberType` would have been called in `makeAccessible`
-        //         and the resulting existential type would have been skolemized in `adapt` *before* we typechecked
-        //         the enclosing type-/ value- application.
-        //
-        //         However, if the selection is overloaded, we defer calling `memberType` until we can select a single
-        //         alternative here. It is therefore necessary to skolemize the existential here.
-        //
-        val fun1 = adaptAfterOverloadResolution(fun, mode.forFunMode | TAPPmode)
-
-        val tparams = fun1.symbol.typeParams //@M TODO: fun.symbol.info.typeParams ? (as in typedAppliedTypeTree)
-        val args1 = if (sameLength(args, tparams)) {
-          //@M: in case TypeApply we can't check the kind-arities of the type arguments,
-          // as we don't know which alternative to choose... here we do
-          map2Conserve(args, tparams) {
-            //@M! the polytype denotes the expected kind
-            (arg, tparam) => typedHigherKindedType(arg, mode, Kind.FromParams(tparam.typeParams))
-          }
-        } else // @M: there's probably something wrong when args.length != tparams.length... (triggered by bug #320)
-        // Martin, I'm using fake trees, because, if you use args or arg.map(typedType),
-        // inferPolyAlternatives loops...  -- I have no idea why :-(
-        // ...actually this was looping anyway, see bug #278.
-          return TypedApplyWrongNumberOfTpeParametersError(fun, fun)
-
-        typedTypeApply(tree, mode, fun1, args1)
-      case SingleType(_, _) =>
-        typedTypeApply(tree, mode, fun setType fun.tpe.widen, args)
-      case PolyType(tparams, restpe) if tparams.nonEmpty =>
-        if (sameLength(tparams, args)) {
-          val isJava = context.unit.isJava
-          val isClassOf = fun.symbol.rawname == nme.classOf && currentRun.runDefinitions.isPredefClassOf(fun.symbol)
-          if (isJava && fun.symbol.isTerm) args.foreach(_.modifyType(rawToExistential)) // e.g. List.class, parsed as classOf[List]
-          val targs = mapList(args)(_.tpe)
-          checkBounds(tree, NoPrefix, NoSymbol, tparams, targs, "")
-          if (isClassOf)
-            typedClassOf(tree, args.head, noGen = true)
-          else {
-            if (!isPastTyper && fun.symbol == Any_isInstanceOf && targs.nonEmpty) {
-              val scrutineeType = fun match {
-                case Select(qual, _) => qual.tpe
-                case _               => AnyTpe
-              }
-              checkCheckable(tree, targs.head, scrutineeType, inPattern = false)
-            }
-            val resultpe = restpe.instantiateTypeParams(tparams, targs)
-            //@M substitution in instantiateParams needs to be careful!
-            //@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int]
-            //@M    --> first, m[a] gets changed to m[Int], then m gets substituted for List,
-            //          this must preserve m's type argument, so that we end up with List[Int], and not List[a]
-            //@M related bug: #1438
-            //println("instantiating type params "+restpe+" "+tparams+" "+targs+" = "+resultpe)
-            treeCopy.TypeApply(tree, fun, args) setType resultpe
-          }
-        }
-        else {
-          TypedApplyWrongNumberOfTpeParametersError(tree, fun)
-        }
-      case ErrorType =>
-        setError(treeCopy.TypeApply(tree, fun, args))
-      case _ =>
-        fun match {
-          // drop the application for an applyDynamic or selectDynamic call since it has been pushed down
-          case treeInfo.DynamicApplication(_, _) => fun
-          case _ => TypedApplyDoesNotTakeTpeParametersError(tree, fun)
-        }
-    }
-
-    //
-    // START: applyDynamic support
-    //
-    import treeInfo.{isApplyDynamicName, DynamicUpdate, DynamicApplicationNamed}
-
-    private def acceptsApplyDynamic(tp: Type) = tp.typeSymbol isNonBottomSubClass DynamicClass
-
-    /** Returns `true` if `name` can be selected dynamically on `qual`, `false` if not. */
-    private def acceptsApplyDynamicWithType(qual: Tree, name: Name): Boolean =
-    // don't selectDynamic selectDynamic, do select dynamic at unknown type
-      !isApplyDynamicName(name) && acceptsApplyDynamic(qual.tpe.widen)
-
-    // if the qualifier is a Dynamic, that's all we need to know
-    private def isDynamicallyUpdatable(tree: Tree) = tree match {
-      case DynamicUpdate(qual, _) => acceptsApplyDynamic(qual.tpe)
-      case _                      => false
-    }
-
-    private def isApplyDynamicNamed(fun: Tree): Boolean = fun match {
-      case DynamicApplicationNamed(qual, _) => acceptsApplyDynamic(qual.tpe.widen)
-      case _ => false
-      // look deeper?
-      // val treeInfo.Applied(methPart, _, _) = fun
-      // println("methPart of "+ fun +" is "+ methPart)
-      // if (methPart ne fun) isApplyDynamicNamed(methPart)
-      // else false
-    }
-
-    private def typedNamedApply(orig: Tree, fun: Tree, args: List[Tree], mode: Mode, pt: Type): Tree = {
-      def argToBinding(arg: Tree): Tree = arg match {
-        case NamedArg(i @ Ident(name), rhs) =>
-          atPos(i.pos.withEnd(rhs.pos.end)) {
-            gen.mkTuple(List(atPos(i.pos)(CODE.LIT(name.toString)), rhs))
-          }
-        case _ =>
-          gen.mkTuple(List(CODE.LIT(""), arg))
-      }
-
-      val t = treeCopy.Apply(orig, unmarkDynamicRewrite(fun), args map argToBinding)
-      wrapErrors(t, _.typed(t, mode, pt))
-    }
-
-    /** Translate selection that does not typecheck according to the normal rules into a selectDynamic/applyDynamic.
-     *
-     * foo.method("blah")  ~~> foo.applyDynamic("method")("blah")
-     * foo.method(x = "blah")  ~~> foo.applyDynamicNamed("method")(("x", "blah"))
-     * foo.varia = 10      ~~> foo.updateDynamic("varia")(10)
-     * foo.field           ~~> foo.selectDynamic("field")
-     * foo.arr(10) = 13    ~~> foo.selectDynamic("arr").update(10, 13)
-     *
-     * what if we want foo.field == foo.selectDynamic("field") == 1, but `foo.field = 10` == `foo.selectDynamic("field").update(10)` == ()
-     * what would the signature for selectDynamic be? (hint: it needs to depend on whether an update call is coming or not)
-     *
-     * need to distinguish selectDynamic and applyDynamic somehow: the former must return the selected value, the latter must accept an apply or an update
-     *  - could have only selectDynamic and pass it a boolean whether more is to come,
-     *    so that it can either return the bare value or something that can handle the apply/update
-     *      HOWEVER that makes it hard to return unrelated values for the two cases
-     *      --> selectDynamic's return type is now dependent on the boolean flag whether more is to come
-     *  - simplest solution: have two method calls
-     *
-     */
-    private def mkInvoke(context: Context, tree: Tree, qual: Tree, name: Name): Option[Tree] = {
-      val cxTree = context.enclosingNonImportContext.tree // scala/bug#8364
-      debuglog(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)")
-      val treeInfo.Applied(treeSelection, _, _) = tree
-      def isDesugaredApply = {
-        val protoQual = macroExpandee(qual) orElse qual
-        treeSelection match {
-          case Select(`protoQual`, nme.apply) => true
-          case _                              => false
-        }
-      }
-
-      Option.when(acceptsApplyDynamicWithType(qual, name)) {
-        def matches(t: Tree) = isDesugaredApply || treeInfo.dissectCore(t) == treeSelection
-
-        /* Note that the trees which arrive here are potentially some distance from
-         * the trees of direct interest. `cxTree` is some enclosing expression which
-         * may apparently be arbitrarily larger than `tree`; and `tree` itself is
-         * too small, having at least in some cases lost its explicit type parameters.
-         * This logic is designed to use `tree` to pinpoint the immediately surrounding
-         * Apply/TypeApply/Select node, and only then creates the dynamic call.
-         * See scala/bug#6731 among others.
-         */
-        def findSelection(t: Tree): Option[(TermName, Tree)] = t match {
-          case Apply(fn, args) if matches(fn) =>
-            val op = if(args.exists(_.isInstanceOf[NamedArg])) nme.applyDynamicNamed else nme.applyDynamic
-            // not supported: foo.bar(a1,..., an: _*)
-            val fn1 = if(treeInfo.isWildcardStarArgList(args)) DynamicVarArgUnsupported(fn, op) else fn
-            Some((op, fn1))
-          case Assign(lhs, _) if matches(lhs) => Some((nme.updateDynamic, lhs))
-          case _ if matches(t)                => Some((nme.selectDynamic, t))
-          case _                              => t.children.flatMap(findSelection).headOption
-        }
-        findSelection(cxTree) map { case (opName, treeInfo.Applied(_, targs, _)) =>
-          val fun = atPos(wrappingPos(qual :: targs)) {
-            gen.mkTypeApply(Select(qual, opName) setPos qual.pos, targs)
-          }
-          if (opName == nme.updateDynamic) suppressMacroExpansion(fun) // scala/bug#7617
-          val nameStringLit = atPos(treeSelection.pos.withStart(treeSelection.pos.point).makeTransparent) {
-            Literal(Constant(name.decode))
-          }
-          markDynamicRewrite {
-            atPos(wrappingPos(qual :: fun :: nameStringLit :: Nil)) {
-              Apply(fun, List(nameStringLit))
-            }
-          }
-        } getOrElse {
-          // While there may be an error in the found tree itself, it should not be possible to *not find* it at all.
-          devWarning(s"Tree $tree not found in the context $cxTree while trying to do a dynamic application")
-          setError(tree)
-        }
-      }
-    }
-    private def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = silent(typeTree) orElse (err => DynamicRewriteError(tree, err.head))
-    //
-    // END: applyDynamic support
-    //
-
-    def typed1(tree: Tree, mode: Mode, pt: Type): Tree = {
-      // Lookup in the given class using the root mirror.
-      def lookupInOwner(owner: Symbol, name: Name): Symbol =
-        if (mode.inQualMode) rootMirror.missingHook(owner, name) else NoSymbol
-
-      // Lookup in the given qualifier.  Used in last-ditch efforts by typedIdent and typedSelect.
-      def lookupInRoot(name: Name): Symbol  = lookupInOwner(rootMirror.RootClass, name)
-      def lookupInEmpty(name: Name): Symbol = rootMirror.EmptyPackageClass.info member name
-
-      def lookupInQualifier(qual: Tree, name: Name): Symbol =
-        if (name == nme.ERROR || qual.tpe.widen.isErroneous)
-          NoSymbol
-        else lookupInOwner(qual.tpe.typeSymbol, name) orElse {
-          NotAMemberError(tree, qual, name, startingIdentContext)
-          NoSymbol
-        }
-
-      def startingIdentContext =
-      // ignore current variable scope in patterns to enforce linearity
-        if (mode.inNone(PATTERNmode | TYPEPATmode)) context
-        else context.outer
-
-      def typedAnnotated(atd: Annotated): Tree = {
-        val ann = atd.annot
-        val arg1 = typed(atd.arg, mode, pt)
-        /* mode for typing the annotation itself */
-        val annotMode = (mode &~ TYPEmode) | EXPRmode
-
-        def resultingTypeTree(tpe: Type) = {
-          // we need symbol-ful originals for reification
-          // hence we go the extra mile to hand-craft this guy
-          val original = arg1 match {
-            case tt @ TypeTree() if tt.original != null => Annotated(ann, tt.original)
-            // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)"
-            case _ => Annotated(ann, arg1)
-          }
-          original setType ann.tpe
-          TypeTree(tpe) setOriginal original setPos tree.pos.focus
-        }
-
-        if (arg1.isType) {
-          // make sure the annotation is only typechecked once
-          if (ann.tpe == null) {
-            val ainfo = typedAnnotation(ann, Some(atd), annotMode)
-            val atype = arg1.tpe.withAnnotation(ainfo)
-
-            if (ainfo.isErroneous)
-            // Erroneous annotations were already reported in typedAnnotation
-              arg1  // simply drop erroneous annotations
-            else {
-              ann setType atype
-              resultingTypeTree(atype)
-            }
-          } else {
-            // the annotation was typechecked before
-            resultingTypeTree(ann.tpe)
-          }
-        }
-        else {
-          if (ann.tpe == null) {
-            val annotInfo = typedAnnotation(ann, Some(atd), annotMode)
-            ann setType arg1.tpe.withAnnotation(annotInfo)
-          }
-          val atype = ann.tpe
-          // For `f(): @inline/noinline` callsites, add the InlineAnnotatedAttachment. TypeApplys
-          // are eliminated by erasure, so add it to the underlying function in this case.
-          @tailrec
-          def setInlineAttachment(t: Tree, att: InlineAnnotatedAttachment): Unit = t match {
-            case TypeApply(fun, _) => setInlineAttachment(fun, att)
-            case _ => t.updateAttachment(att)
-          }
-          if (atype.hasAnnotation(definitions.ScalaNoInlineClass)) setInlineAttachment(arg1, NoInlineCallsiteAttachment)
-          else if (atype.hasAnnotation(definitions.ScalaInlineClass)) setInlineAttachment(arg1, InlineCallsiteAttachment)
-          Typed(arg1, resultingTypeTree(atype)) setPos tree.pos setType atype
-        }
-      }
-
-      def typedBind(tree: Bind) =
-        tree match {
-          case Bind(name: TypeName, body)  =>
-            assert(body.isEmpty, s"${context.unit} typedBind: ${name.debugString} ${body} ${body.getClass}")
-            val sym =
-              if (tree.symbol != NoSymbol) tree.symbol
-              else {
-                if (isFullyDefined(pt))
-                  context.owner.newAliasType(name, tree.pos) setInfo pt
-                else
-                  context.owner.newAbstractType(name, tree.pos) setInfo TypeBounds.empty
-              }
-
-            if (name != tpnme.WILDCARD) namer.enterInScope(sym)
-            else context.scope.enter(sym)
-
-            tree setSymbol sym setType sym.tpeHK
-
-          case Bind(name: TermName, body)  =>
-            val sym =
-              if (tree.symbol != NoSymbol) tree.symbol
-              else context.owner.newValue(name, tree.pos)
-
-            if (name != nme.WILDCARD) {
-              if (context.inPatAlternative)
-                VariableInPatternAlternativeError(tree)
-
-              namer.enterInScope(sym)
-            }
-
-            val body1 = typed(body, mode, pt)
-            val impliedType = patmat.binderTypeImpliedByPattern(body1, pt) // scala/bug#1503, scala/bug#5204
-            val symTp =
-              if (treeInfo.isSequenceValued(body)) seqType(impliedType)
-              else impliedType
-            sym setInfo symTp
-
-            // have to imperatively set the symbol for this bind to keep it in sync with the symbols used in the body of a case
-            // when type checking a case we imperatively update the symbols in the body of the case
-            // those symbols are bound by the symbols in the Binds in the pattern of the case,
-            // so, if we set the symbols in the case body, but not in the patterns,
-            // then re-type check the casedef (for a second try in typedApply for example -- scala/bug#1832),
-            // we are no longer in sync: the body has symbols set that do not appear in the patterns
-            // since body1 is not necessarily equal to body, we must return a copied tree,
-            // but we must still mutate the original bind
-            tree setSymbol sym
-            treeCopy.Bind(tree, name, body1) setSymbol sym setType impliedType
-        }
-
-      def typedArrayValue(tree: ArrayValue) = {
-        val elemtpt1 = typedType(tree.elemtpt, mode)
-        val elems1   = tree.elems mapConserve (elem => typed(elem, mode, elemtpt1.tpe))
-        // see run/t6126 for an example where `pt` does not suffice (tagged types)
-        val tpe1     = if (isFullyDefined(pt) && !phase.erasedTypes) pt else arrayType(elemtpt1.tpe)
-
-        treeCopy.ArrayValue(tree, elemtpt1, elems1) setType tpe1
-      }
-
-      def typedAssign(lhs: Tree, rhs: Tree): Tree = {
-        // see scala/bug#7617 for an explanation of why macro expansion is suppressed
-        def typedLhs(lhs: Tree) = typed(lhs, EXPRmode | LHSmode | POLYmode)
-        val lhs1    = unsuppressMacroExpansion(typedLhs(suppressMacroExpansion(lhs)))
-        val varsym  = lhs1.symbol
-
-        // see #2494 for double error message example
-        def fail() =
-          if (lhs1.isErrorTyped) lhs1
-          else AssignmentError(tree, varsym)
-
-        if (varsym == null)
-          return fail()
-
-        def shadowsSetter =
-          lhs1 match {
-            case treeInfo.Applied(Select(qual, _), _, _) if qual.isTyped =>
-              qual.tpe.member(varsym.name.setterName).exists
-            case _ => false
-          }
-
-        def setterRewrite =
-          lhs1 match {
-            case treeInfo.Applied(Select(qual, _), _, _) =>
-              val sel = Select(qual, varsym.name.setterName) setPos lhs.pos
-              val app = Apply(sel, List(rhs)) setPos tree.pos
-              typed(app, mode, pt)
-            case _ => EmptyTree
-          }
-
-        if (treeInfo.mayBeVarGetter(varsym)) {
-          val res = setterRewrite
-          if (!res.isEmpty) return res
-        }
-
-        //      if (varsym.isVariable ||
-        //        // setter-rewrite has been done above, so rule out methods here, but, wait a minute, why are we assigning to non-variables after erasure?!
-        //        (phase.erasedTypes && varsym.isValue && !varsym.isMethod)) {
-        if (varsym.isVariable || varsym.isValue && phase.assignsFields) {
-          val rhs1 = typedByValueExpr(rhs, lhs1.tpe)
-          treeCopy.Assign(tree, lhs1, checkDead(context, rhs1)) setType UnitTpe
-        }
-        else if (isDynamicallyUpdatable(lhs1)) {
-          val t = atPos(lhs1.pos.withEnd(rhs.pos.end)) {
-            Apply(lhs1, List(rhs))
-          }
-          wrapErrors(t, _.typed1(t, mode, pt))
-        }
-        else if (shadowsSetter) setterRewrite orElse fail()
-        else fail()
-      }
-
-      def typedIf(tree: If): If = {
-        val cond1 = checkDead(context, typedByValueExpr(tree.cond, BooleanTpe))
-        // One-legged ifs don't need a lot of analysis
-        if (tree.elsep.isEmpty)
-          return treeCopy.If(tree, cond1, typed(tree.thenp, UnitTpe), tree.elsep) setType UnitTpe
-
-        val thenp1 = typed(tree.thenp, pt)
-        val elsep1 = typed(tree.elsep, pt)
-
-        // in principle we should pack the types of each branch before lubbing, but lub doesn't really work for existentials anyway
-        // in the special (though common) case where the types are equal, it pays to pack before comparing
-        // especially virtpatmat needed more aggressive unification of skolemized types
-        // this breaks src/library/scala/collection/immutable/TrieIterator.scala (which as of 2.13 doesn't actually exist anymore)
-        // annotated types need to be lubbed regardless (at least, continuations break if you bypass them like this)
-        def samePackedTypes = (
-          !isPastTyper
-            && thenp1.tpe.annotations.isEmpty
-            && elsep1.tpe.annotations.isEmpty
-            && packedType(thenp1, context.owner) =:= packedType(elsep1, context.owner)
-          )
-        def finish(ownType: Type) = treeCopy.If(tree, cond1, thenp1, elsep1) setType ownType
-        // TODO: skolemize (lub of packed types) when that no longer crashes on files/pos/t4070b.scala
-        // @PP: This was doing the samePackedTypes check BEFORE the isFullyDefined check,
-        // which based on everything I see everywhere else was a bug. I reordered it.
-        if (isFullyDefined(pt))
-          finish(pt)
-        // Important to deconst, otherwise `if (???) 0 else 0` evaluates to 0 (scala/bug#6331)
-        else thenp1.tpe.deconst :: elsep1.tpe.deconst :: Nil match {
-          case tp :: _ if samePackedTypes     => finish(tp)
-          case tpes if sameWeakLubAsLub(tpes) => finish(lub(tpes))
-          case tpes                           =>
-            val lub = weakLub(tpes)
-            treeCopy.If(tree, cond1, adapt(thenp1, mode, lub), adapt(elsep1, mode, lub)) setType lub
-        }
-      }
-
-      // Type the Match and leave it until phase `patmat`
-      // empty-selector matches are transformed into synthetic PartialFunction implementations when the expected type demands it
-      def typedVirtualizedMatch(tree: Match): Tree = {
-        val selector = tree.selector
-        val cases = tree.cases
-        if (selector == EmptyTree) {
-          if (pt.typeSymbol == PartialFunctionClass)
-            synthesizePartialFunction(newTermName(fresh.newName("x")), tree.pos, paramSynthetic = true, tree, mode, pt)
-          else {
-            val arity = functionArityFromType(pt) match { case -1 => 1 case arity => arity } // scala/bug#8429: consider sam and function type equally in determining function arity
-
-            val params = for (i <- List.range(0, arity)) yield
-              atPos(tree.pos.focusStart) {
-                ValDef(Modifiers(PARAM | SYNTHETIC),
-                  freshTermName("x" + i + "$"), TypeTree(), EmptyTree)
-              }
-            val ids = for (p <- params) yield Ident(p.name)
-            val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
-            // scala/bug#8120 If we don't duplicate the cases, the original Match node will share trees with ones that
-            //         receive symbols owned by this function. However if, after a silent mode session, we discard
-            //         this Function and try a different approach (e.g. applying a view to the receiver) we end up
-            //         with orphaned symbols which blows up far down the pipeline (or can be detected with -Ycheck:typer).
-            val body = treeCopy.Match(tree, selector1, (cases map duplicateAndKeepPositions).asInstanceOf[List[CaseDef]])
-            typed1(atPos(tree.pos) { Function(params, body) }, mode, pt)
-          }
-        } else
-          typedMatch(selector, cases, mode, pt, tree)
-      }
-
-      def typedReturn(tree: Return) = {
-        val expr = tree.expr
-        val enclMethod = context.enclMethod
-        if (enclMethod == NoContext ||
-          enclMethod.owner.isConstructor ||
-          context.enclClass.enclMethod == enclMethod // i.e., we are in a constructor of a local class
-        ) {
-          ReturnOutsideOfDefError(tree)
-        } else {
-          val DefDef(_, name, _, _, restpt, _) = enclMethod.tree: @unchecked
-          if (restpt.tpe eq null) {
-            ReturnWithoutTypeError(tree, enclMethod.owner)
-          }
-          else {
-            val expr1 = context withinReturnExpr typedByValueExpr(expr, restpt.tpe)
-            // Warn about returning a value if no value can be returned.
-            if (restpt.tpe.typeSymbol == UnitClass) {
-              // The typing in expr1 says expr is Unit (it has already been coerced if
-              // it is non-Unit) so we have to retype it.  Fortunately it won't come up much
-              // unless the warning is legitimate.
-              val typedExpr = typed(expr)
-              if (!isPastTyper && typedExpr.tpe.typeSymbol != UnitClass)
-                context.warning(tree.pos, "enclosing method " + name + s" has result type Unit: return value of type ${typedExpr.tpe} discarded", WarningCategory.Other)
-            }
-            val res = treeCopy.Return(tree, checkDead(context, expr1)).setSymbol(enclMethod.owner)
-            val tp = pluginsTypedReturn(NothingTpe, this, res, restpt.tpe)
-            res.setType(tp)
-          }
-        }
-      }
-
-      def typedNew(tree: New) = {
-        val tpt = tree.tpt
-        val tpt1 = {
-          // This way typedNew always returns a dealiased type. This used to happen by accident
-          // for instantiations without type arguments due to ad hoc code in typedTypeConstructor,
-          // and annotations depended on it (to the extent that they worked, which they did
-          // not when given a parameterized type alias which dealiased to an annotation.)
-          // typedTypeConstructor dealiases nothing now, but it makes sense for a "new" to always be
-          // given a dealiased type.
-          val tpt0 = typedTypeConstructor(tpt) modifyType (_.dealias)
-
-          if (checkStablePrefixClassType(tpt0)) {
-            tpt0.tpe.normalize match { // eta-expand
-              case PolyType(undet, appliedToUndet) =>
-                context.undetparams = undet // can reuse these type params, they're fresh
-                notifyUndetparamsAdded(undet)
-                TypeTree().setOriginal(tpt0).setType(appliedToUndet)
-              case _                               => tpt0
-            }
-          }
-          else tpt0
-        }
-
-        /* If current tree <tree> appears in <val x(: T)? = <tree>>
-         * return `tp with x.type' else return `tp`.
-         */
-        def narrowRhs(tp: Type) = { val sym = context.tree.symbol
-          context.tree match {
-            case ValDef(mods, _, _, Apply(Select(`tree`, _), _)) if !mods.isMutable && sym != null && sym != NoSymbol =>
-              val sym1 =
-                if (sym.owner.isClass && sym.getterIn(sym.owner) != NoSymbol) sym.getterIn(sym.owner)
-                else sym
-              val pre = if (sym1.owner.isClass) sym1.owner.thisType else NoPrefix
-              intersectionType(List(tp, singleType(pre, sym1)))
-            case _ => tp
-          }}
-
-        val tp = tpt1.tpe
-        val sym = tp.typeSymbol.initialize
-
-        if ((sym.isAbstractType || sym.hasAbstractFlag)
-          && !(sym.isJavaAnnotation && context.inAnnotation))
-          IsAbstractError(tree, sym)
-        else if (isPrimitiveValueClass(sym)) {
-          NotAMemberError(tpt, TypeTree(tp), nme.CONSTRUCTOR, startingIdentContext)
-          setError(tpt)
-        }
-        else if (!(  tp == sym.typeOfThis // when there's no explicit self type -- with (#3612) or without self variable
-          // sym.thisSym.tpe == tp.typeOfThis (except for objects)
-          || narrowRhs(tp) <:< tp.typeOfThis
-          || phase.erasedTypes
-          )) {
-          DoesNotConformToSelfTypeError(tree, sym, tp.typeOfThis)
-        } else
-          treeCopy.New(tree, tpt1).setType(tp)
-      }
-
-
-      /* Eta expand an expression like `m _`, where `m` denotes a method or a by-name argument
-       *
-       * The spec says:
-       * The expression `$e$ _` is well-formed if $e$ is of method type or if $e$ is a call-by-name parameter.
-       *   (1) If $e$ is a method with parameters, `$e$ _` represents $e$ converted to a function type
-       *       by [eta expansion](#eta-expansion).
-       *   (2) If $e$ is a parameterless method or call-by-name parameter of type `=> $T$`, `$e$ _` represents
-       *       the function of type `() => $T$`, which evaluates $e$ when it is applied to the empty parameter list `()`.
-       */
-      def typedEta(methodValue: Tree): Tree = methodValue.tpe match {
-        case tp@(MethodType(_, _) | PolyType(_, MethodType(_, _))) => // (1)
-          if (tp.params.lengthCompare(definitions.MaxFunctionArity) > 0) MaxFunctionArityError(methodValue, s"; method ${methodValue.symbol.name} cannot be eta-expanded because it takes ${tp.params.length} arguments")
-          else {
-            val etaPt =
-              pt match {
-                case pt: ProtoType =>
-                  pt.asFunctionType orElse functionType(WildcardType.fillList(tp.params.length), WildcardType) orElse WildcardType // arity overflow --> NoType
-                case _             => pt
-              }
-
-            // We know syntactically methodValue can't refer to a constructor because you can't write `this _` for that (right???)
-            typedEtaExpansion(methodValue, mode, etaPt)
-          }
-
-        case TypeRef(_, ByNameParamClass, _) |  NullaryMethodType(_) => // (2)
-          val pos = methodValue.pos
-          // must create it here to change owner (normally done by typed's typedFunction)
-          val funSym = context.owner.newAnonymousFunctionValue(pos)
-          new ChangeOwnerTraverser(context.owner, funSym) traverse methodValue
-
-          val result = typed(Function(Nil, methodValue) setSymbol funSym setPos pos, mode, pt)
-
-          if (currentRun.isScala3) {
-            UnderscoreNullaryEtaError(methodValue)
-          } else {
-            context.deprecationWarning(pos, NoSymbol, UnderscoreNullaryEtaWarnMsg, "2.13.2")
-            result
-          }
-
-        case ErrorType =>
-          methodValue
-
-        case _ =>
-          UnderscoreEtaError(methodValue)
-      }
-
-      def tryTypedArgs(args: List[Tree], mode: Mode): Option[List[Tree]] = {
-        val c = context.makeSilent(reportAmbiguousErrors = false)
-        c.retyping = true
-        try {
-          val res = newTyper(c).typedArgs(args, mode)
-          if (c.reporter.hasErrors) None else Some(res)
-        } catch {
-          case ex: CyclicReference =>
-            throw ex
-          case _: TypeError =>
-            // @H some of typer errors can still leak,
-            // for instance in continuations
-            None
-        }
-      }
-
-      /* Try to apply function to arguments; if it does not work, try to convert Java raw to existentials, or try to
-       * insert an implicit conversion.
-       */
-      def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
-        val start = if (settings.areStatisticsEnabled) statistics.startTimer(failedApplyNanos) else null
-
-        def onError(typeErrors: Seq[AbsTypeError], warnings: Seq[(Position, String, WarningCategory, Symbol)]): Tree = {
-          if (settings.areStatisticsEnabled) statistics.stopTimer(failedApplyNanos, start)
-
-          // If the problem is with raw types, convert to existentials and try again.
-          // See #4712 for a case where this situation arises,
-          if ((fun.symbol ne null) && fun.symbol.isJavaDefined) {
-            val newtpe = rawToExistential(fun.tpe)
-            if (fun.tpe ne newtpe) {
-              // println("late cooking: "+fun+":"+fun.tpe) // DEBUG
-              return tryTypedApply(fun setType newtpe, args)
-            }
-          }
-          // TODO: case to recurse into Function?
-          /* Only retry if the error hails from a result expression of `tree`
-           * (for instance, it makes no sense to retry on an error from a block statement)
-           * compare with `samePointAs` since many synthetic trees are made with
-           * offset positions even under -Yrangepos.
-           */
-          def errorInResult(tree: Tree): Boolean = {
-            def pred(tree: Tree) = typeErrors.exists(_.errPos samePointAs tree.pos)
-            def loop(tree: Tree): Boolean = pred(tree) || (tree match {
-              case Block(_, r)          => loop(r)
-              case Match(_, cases)      => cases.exists(pred)
-              case CaseDef(_, _, r)     => loop(r)
-              case Annotated(_, r)      => loop(r)
-              case If(_, t, e)          => loop(t) || loop(e)
-              case Try(b, catches, _)   => loop(b) || catches.exists(pred)
-              case MethodValue(r)       => loop(r)
-              case Select(qual, _)      => loop(qual)
-              case Apply(fun, args)     => loop(fun) || args.exists(loop)
-              case TypeApply(fun, args) => loop(fun) || args.exists(loop)
-              case _                    => false
-            })
-            loop(tree)
-          }
-          val retry = typeErrors.forall(_.errPos != null) && (errorInResult(fun) || errorInResult(tree) || args.exists(errorInResult))
-          typingStack.printTyping {
-            val funStr = s"${ptTree(fun)} and ${args.map(ptTree).mkString(", ")}"
-            if (retry) s"second try: $funStr"
-            else s"no second try: $funStr because error not in result: ${typeErrors.head.errPos}!=${tree.pos}"
-          }
-          if (retry) {
-            val Select(qual, name) = fun: @unchecked
-            tryTypedArgs(args, forArgMode(fun, mode)) match {
-              case Some(args1) if !args1.exists(arg => arg.exists(_.isErroneous)) =>
-                val qual1 =
-                  if (!pt.isError) adaptToArguments(qual, name, args1, pt)
-                  else qual
-                if (qual1 ne qual) {
-                  val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos
-                  return context withinSecondTry typed1(tree1, mode, pt)
-                }
-              case _ => ()
-            }
-          }
-          def adjust(err: AbsTypeError) =
-            if (tree.hasAttachment[InterpolatedString.type])
-              tree match {
-                case Apply(sc @ Ident(nme.StringContextName), _) =>
-                  if (sc.isErroneous) err
-                  else NormalTypeError(tree, s"${err.errMsg}; signature for interpolation must be `StringContext.apply(String*)`")
-                case Apply(Select(_, nm), badargs) =>
-                  if (badargs.exists(arg => arg.isErroneous || arg.pos.includes(err.errPos) && arg.pos != err.errPos)) err
-                  else NormalTypeError(tree, s"${err.errMsg}; incompatible interpolation method $nm")
-                case x => throw new MatchError(x)
-              }
-            else err
-          typeErrors.foreach(err => context.issue(adjust(err)))
-          warnings.foreach { case (p, m, c, s) => context.warning(p, m, c, s) }
-          setError(treeCopy.Apply(tree, fun, args))
-        }
-
-        silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
-          case SilentResultValue(value) => value
-          case e: SilentTypeError => onError(e.errors, e.warnings)
-        }
-      }
-
-      def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = {
-        // TODO: replace `fun.symbol.isStable` by `treeInfo.isStableIdentifierPattern(fun)`
-        val stableApplication = (fun.symbol ne null) && fun.symbol.isMethod && fun.symbol.isStable
-        val funpt = if (mode.inPatternMode) pt else WildcardType
-        val appStart = if (settings.areStatisticsEnabled) statistics.startTimer(failedApplyNanos) else null
-        val opeqStart = if (settings.areStatisticsEnabled) statistics.startTimer(failedOpEqNanos) else null
-
-        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, c, s) => context.warning(p, m, c, s) }
-          args.foreach(typed(_, mode, ErrorType))
-          setError(tree)
-        }
-        def advice1(convo: Tree, errors: List[AbsTypeError], err: SilentTypeError): List[AbsTypeError] =
-          errors.map { e =>
-            if (e.errPos samePointAs 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.linesIterator.toList).mkString(header, f"%n    ", expansion))
-            } else e
-          }
-        def advice2(errors: List[AbsTypeError]): List[AbsTypeError] =
-          errors.map { e =>
-            if (e.errPos samePointAs 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 (settings.areStatisticsEnabled) statistics.stopTimer(failedOpEqNanos, opeqStart)
-              val erred = qual1.exists(_.isErroneous) || args.exists(_.isErroneous)
-              if (erred) reportError(error) else {
-                val convo = convertToAssignment(fun, qual1, name, args)
-                if (settings.multiargInfix && tree.hasAttachment[MultiargInfixAttachment.type] && args.lengthCompare(1) > 0)
-                  warnMultiargInfix(tree)
-                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 (settings.areStatisticsEnabled) statistics.stopTimer(failedApplyNanos, appStart)
-              val Apply(Select(qual2, _), args2) = tree: @unchecked
-              val erred = qual2.exists(_.isErroneous) || args2.exists(_.isErroneous)
-              reportError {
-                if (erred) error else SilentTypeError(advice2(error.errors), error.warnings)
-              }
-            }
-          case _ =>
-            if (settings.areStatisticsEnabled) statistics.stopTimer(failedApplyNanos, appStart)
-            reportError(error)
-        }
-        val silentResult = silent(
-          op                    = _.typed(fun, mode.forFunMode, funpt),
-          reportAmbiguousErrors = !mode.inExprMode && context.ambiguousErrors,
-          newtree               = if (mode.inExprMode) tree else context.tree
-        )
-        silentResult match {
-          case SilentResultValue(fun1) =>
-            val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1
-            if (settings.areStatisticsEnabled) statistics.incCounter(typedApplyCount)
-            val isFirstTry = fun2 match {
-              case Select(_, _) => mode.inExprMode && {
-                val noSecondTry = (
-                  isPastTyper
-                    || context.inSecondTry
-                    || (fun2.symbol ne null) && fun2.symbol.isConstructor
-                    || isImplicitMethodType(fun2.tpe)
-                  )
-                !noSecondTry
-              }
-              case _ => false
-            }
-            if (isFirstTry)
-              tryTypedApply(fun2, args)
-            else
-              doTypedApply(tree, fun2, args, mode, pt)
-          case err: SilentTypeError => onError(err)
-        }
-      }
-
-      def typedApply(tree: Apply) = tree match {
-        case Apply(Block(stats, expr), args) =>
-          typed1(atPos(tree.pos)(Block(stats, Apply(expr, args) setPos tree.pos.makeTransparent)), mode, pt)
-        case Apply(fun, args) =>
-          normalTypedApply(tree, fun, args) match {
-            case treeInfo.ArrayInstantiation(level, componentType, arg) =>
-              // convert new Array[T](len) to evidence[ClassTag[T]].newArray(len)
-              // convert new Array^N[T](len) for N > 1 to evidence[ClassTag[Array[...Array[T]...]]].newArray(len)
-              // where Array HK gets applied (N-1) times
-              val tagType = (1 until level).foldLeft(componentType)((res, _) => arrayType(res))
-
-              val tree1: Tree = resolveClassTag(tree.pos, tagType) match {
-                case EmptyTree => MissingClassTagError(tree, tagType)
-                case tag       => atPos(tree.pos)(new ApplyToImplicitArgs(Select(tag, nme.newArray), arg :: Nil))
-              }
-              if (tree1.isErrorTyped) tree1 else typed(tree1, mode, pt)
-            case Apply(Select(fun, nme.apply), _) if treeInfo.isSuperConstrCall(fun) => TooManyArgumentListsForConstructor(tree) //scala/bug#5696
-            case tree1 if mode.inPatternMode && tree1.tpe.paramSectionCount > 0 =>
-              // For a case class C with more than two parameter lists,
-              // C(_) is typed as C(_)() which is a method type like ()C.
-              // In a pattern, just use the final result type, C in this case.
-              // The enclosing context may be case c @ C(_) => or val c @ C(_) = v.
-              tree1 modifyType (_.finalResultType)
-              tree1
-            case tree1 @ Apply(_, args1) if settings.multiargInfix && tree.hasAttachment[MultiargInfixAttachment.type] && args1.lengthCompare(1) > 0 =>
-              warnMultiargInfix(tree1)
-              tree1
-            case tree1                                                               => tree1
-          }
-      }
-
-      def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree]): Tree = {
-        val prefix = name.toTermName stripSuffix nme.EQL
-        def mkAssign(vble: Tree): Tree =
-          Assign(
-            vble,
-            Apply(
-              Select(vble.duplicate, prefix) setPos fun.pos.focus, args) setPos tree.pos.makeTransparent
-          ) setPos tree.pos
-
-        def mkUpdate(table: Tree, indices: List[Tree], args_? : Option[List[Tree]]) =
-          gen.evalOnceAll(table :: indices, context.owner, fresh) {
-            case tab :: is =>
-              def mkCall(name: Name, extraArgs: Tree*) =
-                Apply(
-                  Select(tab(), name) setPos table.pos,
-                  is.map(i => i()) ++ extraArgs
-                ) setPos tree.pos
-
-              def mkApplies(core: Tree) = args_?.fold(core) { args =>
-                Apply(core, args) setPos wrappingPos(core :: args)
-              }
-              mkCall(
-                nme.update,
-                Apply(Select(mkApplies(mkCall(nme.apply)), prefix) setPos fun.pos, args) setPos tree.pos
-              )
-            case _ => EmptyTree
-          }
-
-        val assignment = qual match {
-          case Ident(_) =>
-            mkAssign(qual)
-
-          case Select(qualqual, _) =>
-            gen.evalOnce(qualqual, context.owner, fresh) { qq =>
-              val qq1 = qq()
-              mkAssign(Select(qq1, qual.symbol) setPos qual.pos)
-            }
-
-          case Apply(fn, extra) if qual.isInstanceOf[ApplyToImplicitArgs] =>
-            fn match {
-              case treeInfo.Applied(Select(table, nme.apply), _, indices :: Nil) =>
-                // table(indices)(implicits)
-                mkUpdate(table, indices, Some(extra))
-              case _  => UnexpectedTreeAssignmentConversionError(qual)
-            }
-
-          case Apply(fn, indices) =>
-            fn match {
-              case treeInfo.Applied(Select(table, nme.apply), _, Nil) =>
-                mkUpdate(table, indices, None)
-              case _  => UnexpectedTreeAssignmentConversionError(qual)
-            }
-
-          case x => throw new MatchError(x)
-        }
-        assignment
-      }
-
-      def typedSuper(tree: Super) = {
-        val mix = tree.mix
-        val qual1 = typed(tree.qual)
-
-        val clazz = qual1 match {
-          case This(_) => qual1.symbol
-          case _ => qual1.tpe.typeSymbol
-        }
-        def findMixinSuper(site: Type): Type = {
-          var ps = site.parents filter (_.typeSymbol.name == mix)
-          if (ps.isEmpty)
-            ps = site.parents filter (_.typeSymbol.name == mix)
-          if (ps.isEmpty) {
-            debuglog("Fatal: couldn't find site " + site + " in " + site.parents.map(_.typeSymbol.name))
-            if (phase.erasedTypes && context.enclClass.owner.isTrait) {
-              // the reference to super class got lost during erasure
-              restrictionError(tree.pos, unit, "traits may not select fields or methods from super[C] where C is a class")
-              ErrorType
-            } else {
-              MixinMissingParentClassNameError(tree, mix, clazz)
-              ErrorType
-            }
-          } else if (!ps.tail.isEmpty) {
-            AmbiguousParentClassError(tree)
-            ErrorType
-          } else {
-            ps.head
-          }
-        }
-
-        val owntype =
-          if (!mix.isEmpty) findMixinSuper(clazz.tpe)
-          else if (context.inSuperInit) clazz.info.firstParent
-          else intersectionType(clazz.info.parents)
-
-        treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype)
-      }
-
-      def typedThis(tree: This) =
-        tree.symbol orElse qualifyingClass(tree, tree.qual, packageOK = false, immediate = true) match {
-          case NoSymbol => tree
-          case clazz    =>
-            tree setSymbol clazz setType clazz.thisType.underlying
-            if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree
-        }
-
-
-      // For Java, instance and static members are in the same scope, but we put the static ones in the companion object
-      // so, when we can't find a member in the class scope, check the companion
-      def inCompanionForJavaStatic(cls: Symbol, name: Name): Symbol =
-        if (!(context.unit.isJava && cls.isClass)) NoSymbol else {
-          context.javaFindMember(cls.typeOfThis, name, _.isStaticMember)._2
-        }
-
-      /* Attribute a selection where `tree` is `qual.name`.
-       * `qual` is already attributed.
-       */
-      def typedSelect(tree: Tree, qual: Tree, name: Name): Tree = {
-        // note: on error, we discard the work we did in type checking tree.qualifier into qual
-        // (tree is either Select or SelectFromTypeTree, and qual may be different from tree.qualifier because it has been type checked)
-        val qualTp = qual.tpe
-        if ((qualTp eq null) || qualTp.isError) setError(tree)
-        else if (name.isTypeName && qualTp.isVolatile)  // TODO: use same error message for volatileType#T and volatilePath.T?
-          if (tree.isInstanceOf[SelectFromTypeTree]) TypeSelectionFromVolatileTypeError(tree, qual)
-          else UnstableTreeError(qual)
-        else {
-          def asDynamicCall = mkInvoke(context, tree, qual, name) map { t =>
-            wrapErrors(t, _.typed1(t, mode, pt))
-          }
-
-          val sym = tree.symbol orElse member(qual.tpe, name) orElse inCompanionForJavaStatic(qual.tpe.typeSymbol, name)
-          if ((sym eq NoSymbol) && name != nme.CONSTRUCTOR && mode.inAny(EXPRmode | PATTERNmode)) {
-            // symbol not found? --> try to convert implicitly to a type that does have the required
-            // member.  Added `| PATTERNmode` to allow enrichment in patterns (so we can add e.g., an
-            // xml member to StringContext, which in turn has an unapply[Seq] method)
-
-            val qual1 = adaptToMemberWithArgs(tree, qual, name, mode)
-            if ((qual1 ne qual) && !qual1.isErrorTyped)
-              return typed(treeCopy.Select(tree, qual1, name), mode, pt)
-          }
-
-          // This special-case complements the logic in `adaptMember` in erasure, it handles selections
-          // from `Super`. In `adaptMember`, if the erased type of a qualifier doesn't conform to the
-          // owner of the selected member, a cast is inserted, e.g., (foo: Option[String]).get.trim).
-          // Similarly, for `super.m`, typing `super` during erasure assigns the superclass. If `m`
-          // is defined in a trait, this is incorrect, we need to assign a type to `super` that conforms
-          // to the owner of `m`. Adding a cast (as in `adaptMember`) would not work, `super.asInstanceOf`
-          // is not a valid tree.
-          if (phase.erasedTypes && qual.isInstanceOf[Super]) {
-            //  See the comment in `preErase` why we use the attachment (scala/bug#7936)
-            val qualSym = tree.getAndRemoveAttachment[QualTypeSymAttachment] match {
-              case Some(a) => a.sym
-              case None => sym.owner
-            }
-            qual.setType(qualSym.tpe)
-          }
-
-          if (!reallyExists(sym)) {
-            def handleMissing: Tree = {
-              def errorTree = missingSelectErrorTree(tree, qual, name)
-              def asTypeSelection =
-                if (context.unit.isJava && name.isTypeName) {
-                  // scala/bug#3120 Java uses the same syntax, A.B, to express selection from the
-                  // value A and from the type A. We have to try both.
-                  atPos(tree.pos)(gen.convertToSelectFromType(qual, name)) match {
-                    case EmptyTree => None
-                    case tree1     => Some(typed1(tree1, mode, pt))
-                  }
-                } else None
-
-              debuglog(s"""
-                          |qual=$qual:${qual.tpe}
-                          |symbol=${qual.tpe.termSymbol.defString}
-                          |scope-id=${qual.tpe.termSymbol.info.decls.hashCode}
-                          |members=${qual.tpe.members mkString ", "}
-                          |name=$name
-                          |found=$sym
-                          |owner=${context.enclClass.owner}
-                """.stripMargin)
-
-              // 1) Try converting a term selection on a java class into a type selection.
-              // 2) Try expanding according to Dynamic rules.
-              // 3) Try looking up the name in the qualifier.
-              asTypeSelection orElse asDynamicCall getOrElse (lookupInQualifier(qual, name) match {
-                case NoSymbol => setError(errorTree)
-                case found    => typed1(tree setSymbol found, mode, pt)
-              })
-            }
-            handleMissing
-          }
-          else {
-            if ((sym ne NoSymbol) && !qual.tpe.isStable && argsDependOnPrefix(sym)) {
-              // Rewrites "qual.name ..." to "{ val lhs = qual ; lhs.name ... }" in cases where
-              // qual is not stable and name has a method type which depends on its prefix. If
-              // this is the case then hoisting qual out as a stable val means that members of
-              // implicit scopes which are accessible via lhs can be candidates for satisfying
-              // implicit (conversions to) arguments of name.
-
-              val vsym = context.owner.newValue(freshTermName(nme.STABILIZER_PREFIX), qual.pos.focus, SYNTHETIC | ARTIFACT | STABLE)
-              vsym.setInfo(uncheckedBounds(qual.tpe))
-              val vdef = atPos(vsym.pos)(ValDef(vsym, focusInPlace(qual)) setType NoType)
-              context.pendingStabilizers ::= vdef
-              qual.changeOwner(context.owner -> vsym)
-              val newQual = Ident(vsym) setType singleType(NoPrefix, vsym) setPos qual.pos.focus
-              return typedSelect(tree, newQual, name)
-            }
-
-            val tree1 = tree match {
-              case Select(_, _)             => treeCopy.Select(tree, qual, name)
-              case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
-              case x                        => throw new MatchError(x)
-            }
-            val pre = qual.tpe
-            var accessibleError: AccessTypeError = null
-            val result = silent(_.makeAccessible(tree1, sym, pre, qual)) match {
-              case SilentTypeError(err) => err match {
-                case err: AccessTypeError =>
-                  accessibleError = err
-                  tree1
-                case _ =>
-                  SelectWithUnderlyingError(tree, err)
-                  return tree
-              }
-              case SilentResultValue(value) => value match {
-                case qual: Tree               => stabilize(qual, pre, mode, pt)
-                case (qual: Tree, pre1: Type) => stabilize(qual, pre1, mode, pt)
-                case x                        => throw new MatchError(x)
-              }
-              case x => throw new MatchError(x)
-            }
-
-            result match {
-              case _ if accessibleError != null =>
-                // don't adapt constructor, scala/bug#6074
-                val qual1 = if (name == nme.CONSTRUCTOR) qual
-                else adaptToMemberWithArgs(tree, qual, name, mode, reportAmbiguous = false, saveErrors = false)
-                if (!qual1.isErrorTyped && (qual1 ne qual))
-                  typed(Select(qual1, name) setPos tree.pos, mode, pt)
-                else
-                // before failing due to access, try a dynamic call.
-                  asDynamicCall getOrElse {
-                    context.issue(accessibleError)
-                    setError(tree)
-                  }
-              // could checkAccessible (called by makeAccessible) potentially have skipped checking a type application in qual?
-              case SelectFromTypeTree(qual@TypeTree(), name) if qual.tpe.typeArgs.nonEmpty => // TODO: somehow the new qual is not checked in refchecks
-                treeCopy.SelectFromTypeTree(
-                  result,
-                  TypeTreeWithDeferredRefCheck() { () => val tp = qual.tpe; val sym = tp.typeSymbolDirect
-                    // will execute during refchecks -- TODO: make private checkTypeRef in refchecks public and call that one?
-                    checkBounds(qual, tp.prefix, sym.owner, sym.typeParams, tp.typeArgs, "")
-                    qual // you only get to see the wrapped tree after running this check :-p
-                  }.setType(qual.tpe).setPos(qual.pos),
-                  name
-                )
-              case _ =>
-                result
-            }
-          }
-        }
-      }
-
-      def typedTypeSelectionQualifier(tree: Tree, pt: Type) =
-        context.withImplicitsDisabled {
-          val mode1 = MonoQualifierModes | mode.onlyTypePat
-          typed(checkRootOfQualifier(tree, mode1), mode1, pt)
-        }
-
-      def typedSelectOrSuperCall(tree: Select) = tree match {
-        case Select(qual @ Super(_, _), nme.CONSTRUCTOR) =>
-          // the qualifier type of a supercall constructor is its first parent class
-          typedSelect(tree, typedSelectOrSuperQualifier(qual), nme.CONSTRUCTOR)
-        case Select(qual, name) =>
-          if (name.isTypeName) {
-            val qualTyped = typedTypeSelectionQualifier(tree.qualifier, WildcardType)
-            val qualStableOrError =
-              if (qualTyped.isErrorTyped || unit.isJava || treeInfo.admitsTypeSelection(qualTyped)) qualTyped
-              else UnstableTreeError(qualTyped)
-            typedSelect(tree, qualStableOrError, name)
-          } else {
-            if (settings.areStatisticsEnabled) statistics.incCounter(typedSelectCount)
-            val qualTyped = checkDead(context, typedQualifier(qual, mode))
-            val tree1 = typedSelect(tree, qualTyped, name)
-
-            if (tree.hasAttachment[PostfixAttachment.type])
-              checkFeature(tree.pos, currentRun.runDefinitions.PostfixOpsFeature, name.decode)
-            val sym = tree1.symbol
-            if (sym != null && sym.isOnlyRefinementMember && !sym.isMacro)
-              checkFeature(tree1.pos, currentRun.runDefinitions.ReflectiveCallsFeature, sym.toString)
-
-            qualTyped.symbol match {
-              case s: Symbol if s.isRootPackage => treeCopy.Ident(tree1, name)
-              case _ => tree1
-            }
-          }
-      }
-
-      /* A symbol qualifies if:
-       *  - it exists
-       *  - it is not stale (stale symbols are made to disappear here)
-       *  - if we are in a constructor pattern, method definitions do not qualify
-       *    unless they are stable.  Otherwise, 'case x :: xs' would find the :: method.
-       */
-      def qualifies(sym: Symbol) = (
-        sym.hasRawInfo
-          && reallyExists(sym)
-          && !(mode.typingConstructorPattern && sym.isMethod && !sym.isStable)
-        )
-
-      /* Attribute an identifier consisting of a simple name or an outer reference.
-       *
-       * @param tree      The tree representing the identifier.
-       * @param name      The name of the identifier.
-       * Transformations: (1) Prefix class members with this.
-       *                  (2) Change imported symbols to selections
-       */
-      def typedIdent(tree: Tree, name: Name): Tree = {
-        // setting to enable unqualified idents in empty package (used by the repl)
-        def inEmptyPackage = if (settings.exposeEmptyPackage.value) lookupInEmpty(name) else NoSymbol
-
-        def issue(err: AbsTypeError) = {
-          // Avoiding some spurious error messages: see scala/bug#2388.
-          val suppress = reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME)
-          if (!suppress)
-            ErrorUtils.issueTypeError(err)
-
-          setError(tree)
-        }
-        // ignore current variable scope in patterns to enforce linearity
-        val startContext = if (mode.typingPatternOrTypePat) context.outer else context
-
-        def asTypeName = if (mode.inAll(MonoQualifierModes) && unit.isJava && name.isTermName) {
-          startContext.lookupSymbol(name.toTypeName, qualifies).symbol
-        } else NoSymbol
-
-        // in Java, only pick a package if it is rooted
-        def termQualifies(sym: Symbol) = qualifies(sym) && (
-          !startContext.unit.isJava  || !sym.hasPackageFlag
-            || sym.owner.isEffectiveRoot || sym.owner.isRootPackage || sym.isRootPackage
-          )
-        val nameLookup  = tree.symbol match {
-          case NoSymbol => startContext.lookupSymbol(name, termQualifies)
-          case sym      => LookupSucceeded(EmptyTree, sym)
-        }
-        import InferErrorGen._
-        nameLookup match {
-          case LookupAmbiguous(msg)         => issue(AmbiguousIdentError(tree, name, msg))
-          case LookupInaccessible(sym, msg) => issue(AccessError(tree, sym, context, msg))
-          case LookupNotFound               =>
-            asTypeName orElse inEmptyPackage orElse lookupInRoot(name) match {
-              case NoSymbol => issue(SymbolNotFoundError(tree, name, context.owner, startContext, mode.in(all = PATTERNmode, none = APPSELmode | TYPEPATmode)))
-              case sym      => typed1(tree setSymbol sym, mode, pt)
-            }
-          case LookupSucceeded(qual, sym)   =>
-            (// this -> Foo.this
-              if (sym.isThisSym)
-                typed1(This(sym.owner) setPos tree.pos, mode, pt)
-              else if (sym.rawname == nme.classOf && currentRun.runDefinitions.isPredefClassOf(sym) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) {
-                // Inferring classOf type parameter from expected type.  Otherwise an
-                // actual call to the stubbed classOf method is generated, returning null.
-                typedClassOf(tree, TypeTree(pt.typeArgs.head).setPos(tree.pos.focus))
-              }
-              else {
-                val pre1  = if (sym.isTopLevel) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe
-                val tree1 = if (qual == EmptyTree) tree else {
-                  val pos = tree.pos
-                  Select(atPos(pos.focusStart)(qual), name).setPos(pos)
-                }
-                var tree2: Tree = null
-                var pre2: Type = pre1
-                makeAccessible(tree1, sym, pre1, qual) match {
-                  case (t: Tree, tp: Type) =>
-                    tree2 = t
-                    pre2 = tp
-                  case t: Tree =>
-                    tree2 = t
-                  case x => throw new MatchError(x)
-                }
-                // scala/bug#5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid
-                //         inference errors in pattern matching.
-                stabilize(tree2, pre2, mode, pt) modifyType dropIllegalStarTypes
-              }) setAttachments tree.attachments
-        }
-      }
-
-      def typedIdentOrWildcard(tree: Ident) = {
-        val name = tree.name
-        if (settings.areStatisticsEnabled) statistics.incCounter(typedIdentCount)
-        if (!tree.isBackquoted &&
-          ((name == nme.WILDCARD && mode.typingPatternNotConstructor) ||
-            (name == tpnme.WILDCARD && mode.inTypeMode)))
-          tree setType makeFullyDefined(pt)
-        else
-          typedIdent(tree, name)
-      }
-
-      def typedCompoundTypeTree(tree: CompoundTypeTree) = {
-        val templ = tree.templ
-        val parents1 = templ.parents mapConserve (typedType(_, mode))
-
-        // This is also checked later in typedStats, but that is too late for scala/bug#5361, so
-        // we eagerly check this here.
-        for (stat <- templ.body if !treeInfo.isDeclarationOrTypeDef(stat))
-          OnlyDeclarationsError(stat)
-
-        if ((parents1 ++ templ.body) exists (_.isErrorTyped)) tree setType ErrorType
-        else {
-          val decls = newScope
-          //Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id)
-          val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos)
-          newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ)
-          templ updateAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere
-          tree setType (if (templ.exists(_.isErroneous)) ErrorType else self) // Being conservative to avoid scala/bug#5361
-        }
-      }
-
-      def typedAppliedTypeTree(tree: AppliedTypeTree) = {
-        val tpt = tree.tpt
-        val args = tree.args
-        val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType)
-
-        if (tpt1.isErrorTyped) {
-          tpt1
-        } else if (!tpt1.hasSymbolField) {
-          AppliedTypeNoParametersError(tree, tpt1.tpe)
-        } else {
-          val tparams = tpt1.symbol.typeParams
-          val isComplete = tpt1.symbol.rawInfo.isComplete
-
-          if (sameLength(tparams, args)) {
-            // @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer)
-            val args1 = map2Conserve(args, tparams) { (arg, tparam) =>
-              def ptParams = Kind.FromParams(tparam.typeParams)
-
-              // if symbol hasn't been fully loaded, can't check kind-arity except when we're in a pattern,
-              // where we can (we can't take part in F-Bounds) and must (scala/bug#8023)
-              val pt = if (mode.typingPatternOrTypePat) {
-                tparam.initialize; ptParams
-              }
-              else if (isComplete) ptParams
-              else Kind.Wildcard
-
-              typedHigherKindedType(arg, mode, pt)
-            }
-            val argtypes = mapList(args1)(_.tpe)
-
-            foreach2(args, tparams) { (arg, tparam) =>
-              // note: can't use args1 in selector, because Binds got replaced
-              val asym = arg.symbol
-              def abounds = asym.info.bounds
-              def tbounds = tparam.info.bounds
-              // TODO investigate whether this should be merged with the near duplicate in Inferencer
-              // and whether or not we should avoid using setInfo here as well to avoid potentially
-              // trampling on type history.
-              def enhanceBounds(): Unit = {
-                val TypeBounds(lo0, hi0) = abounds: @unchecked
-                val TypeBounds(lo1, hi1) = tbounds.subst(tparams, argtypes): @unchecked
-                val lo = lub(List(lo0, lo1))
-                val hi = glb(List(hi0, hi1))
-                if (!(lo =:= lo0 && hi =:= hi0))
-                  asym setInfo logResult(s"Updating bounds of ${asym.fullLocationString} in $tree from '$abounds' to")(TypeBounds(lo, hi))
-              }
-              if (asym != null && asym.isAbstractType) {
-                arg match {
-                  // I removed the Ident() case that partially fixed scala/bug#1786,
-                  // because the stricter bounds being inferred broke e.g., slick
-                  // worse, the fix was compilation order-dependent
-                  // sharpenQuantifierBounds (used in skolemizeExistential) has an alternative fix (scala/bug#6169) that's less invasive
-                  case Bind(_, _) => enhanceBounds()
-                  case _          =>
-                }
-              }
-            }
-            val original = treeCopy.AppliedTypeTree(tree, tpt1, args1)
-            val result = TypeTree(appliedType(tpt1.tpe, argtypes)) setOriginal original
-            val isPoly = tpt1.tpe.isInstanceOf[PolyType]
-            if (isPoly) // did the type application (performed by appliedType) involve an unchecked beta-reduction?
-              TypeTreeWithDeferredRefCheck() { () =>
-                // wrap the tree and include the bounds check -- refchecks will perform this check (that the beta reduction was indeed allowed) and unwrap
-                // we can't simply use original in refchecks because it does not contains types
-                // (and the only typed trees we have been mangled so they're not quite the original tree anymore)
-                checkBounds(result, tpt1.tpe.prefix, tpt1.symbol.owner, tpt1.symbol.typeParams, argtypes, "")
-                result // you only get to see the wrapped tree after running this check :-p
-              }.setType(result.tpe).setPos(result.pos)
-            else result
-          } else if (tparams.isEmpty) {
-            AppliedTypeNoParametersError(tree, tpt1.tpe)
-          } else {
-            //Console.println("\{tpt1}:\{tpt1.symbol}:\{tpt1.symbol.info}")
-            if (settings.isDebug) Console.println(s"$tpt1:${tpt1.symbol}:${tpt1.symbol.info}")//debug
-            AppliedTypeWrongNumberOfArgsError(tree, tpt1, tparams)
-          }
-        }
-      }
-
-      val sym: Symbol = tree.symbol
-      if ((sym ne null) && (sym ne NoSymbol)) sym.initialize
-
-      def typedPackageDef(pdef0: PackageDef) = {
-        val pdef = treeCopy.PackageDef(pdef0, pdef0.pid, pluginsEnterStats(this, namer.expandMacroAnnotations(pdef0.stats)))
-        val pid1 = typedPackageQualifier(pdef.pid).asInstanceOf[RefTree]
-        assert(sym.moduleClass ne NoSymbol, sym)
-        if (pid1.symbol.ne(NoSymbol) && !(pid1.symbol.hasPackageFlag || pid1.symbol.isModule))
-          reporter.error(pdef.pos, s"There is name conflict between the ${pid1.symbol.fullName} and the package ${sym.fullName}.")
-        val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
-          .typedStats(pdef.stats, NoSymbol)
-        treeCopy.PackageDef(tree, pid1, stats1) setType NoType
-      }
-
-      /*
-       * The typer with the correct context for a method definition. If the method is a default getter for
-       * a constructor default, the resulting typer has a constructor context (fixes scala/bug#5543).
-       */
-      def defDefTyper(ddef: DefDef) = {
-        val isConstrDefaultGetter = ddef.mods.hasDefault && sym.owner.isModuleClass &&
-          nme.defaultGetterToMethod(sym.name) == nme.CONSTRUCTOR
-        newTyper(context.makeNewScope(ddef, sym)).constrTyperIf(isConstrDefaultGetter)
-      }
-
-      def typedAlternative(alt: Alternative) = {
-        context withinPatAlternative (
-          treeCopy.Alternative(tree, alt.trees mapConserve (alt => typed(alt, mode, pt))) setType pt
-          )
-      }
-      def typedStar(tree: Star) = {
-        if (!context.starPatterns && !isPastTyper)
-          StarPatternWithVarargParametersError(tree)
-
-        treeCopy.Star(tree, typed(tree.elem, mode, pt)) setType makeFullyDefined(pt)
-      }
-
-      def typedTry(tree: Try) = {
-        def warn(pos: Position, name: Name) = {
-          val msg = s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning."
-          context.warning(pos, msg, WarningCategory.Other)
-        }
-        def issueTryWarnings(tree: Try): Try = {
-          def checkForCatchAll(cdef: CaseDef): Unit = {
-            def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
-            if (cdef.guard.isEmpty) cdef.pat match {
-              case Bind(name, i @ Ident(_)) if unbound(i) => warn(cdef.pat.pos, name)
-              case i @ Ident(name) if unbound(i)          => warn(cdef.pat.pos, name)
-              case _                                      =>
-            }
-          }
-          if (!isPastTyper) tree match {
-            case Try(_, Nil, fin) =>
-              if (fin eq EmptyTree)
-                context.warning(tree.pos, "A try without a catch or finally is equivalent to putting its body in a block; no exceptions are handled.", WarningCategory.Other)
-            case Try(_, catches, _) =>
-              catches foreach checkForCatchAll
-          }
-          tree
-        }
-
-
-        val Try(block, catches, fin) = tree
-        val block1   = typed(block, pt)
-        val cases    = catches match {
-          case CaseDef(EmptyTree, EmptyTree, catchExpr) :: Nil =>
-            val e = typed(catchExpr, functionType(List(ThrowableTpe), pt))
-            val catcher =
-              if (isPartialFunctionType(e.tpe)) treeBuilder.makeCatchFromExpr(e)
-              else {
-                warn(e.pos, nme.WILDCARD)
-                treeBuilder.makeCatchFromFunc(e)
-              }
-            catcher :: Nil
-          case _ => catches
-        }
-        val catches1 = typedCases(cases, ThrowableTpe, pt)
-        val fin1     = if (fin.isEmpty) fin else typed(fin, UnitTpe)
-
-        def finish(ownType: Type) = treeCopy.Try(tree, block1, catches1, fin1) setType ownType
-
-        issueTryWarnings(
-          if (isFullyDefined(pt))
-            finish(pt)
-          else block1 :: catches1 map (_.tpe.deconst) match {
-            case tpes if sameWeakLubAsLub(tpes) => finish(lub(tpes))
-            case tpes                           =>
-              val lub      = weakLub(tpes)
-              val block2   = adapt(block1, mode, lub)
-              val catches2 = catches1 map (adaptCase(_, mode, lub))
-              treeCopy.Try(tree, block2, catches2, fin1) setType lub
-          }
-        )
-      }
-
-      def typedThrow(tree: Throw) = {
-        val expr1 = typedByValueExpr(tree.expr, ThrowableTpe)
-        treeCopy.Throw(tree, expr1) setType NothingTpe
-      }
-
-      def typedTyped(tree: Typed) = {
-        if (treeInfo isWildcardStarType tree.tpt)
-          typedStarInPattern(tree, mode.onlySticky, pt)
-        else if (mode.inPatternMode)
-          typedInPattern(tree, mode.onlySticky, pt)
-        else tree match {
-          // find out whether the programmer is trying to eta-expand a macro def
-          // to do that we need to typecheck the tree first (we need a symbol of the eta-expandee)
-          // that typecheck must not trigger macro expansions, so we explicitly prohibit them
-          // however we cannot do `context.withMacrosDisabled`
-          // because `expr` might contain nested macro calls (see scala/bug#6673).
-          // Otherwise, (check for dead code, and) eta-expand.
-          case MethodValue(expr) =>
-            // Need to type in FUNmode so that we accept a method type (which also means we can't use our pt),
-            // this does mean no overloading is performed. The main reason to ignore pt and move to FUNmode is that
-            // the `m` in `m _` could involve an implicit conversion, which will go through adapt after converting,
-            // which will run afoul of the restriction that a method-typed tree is only allowed when a function type is expected.
-            // We peeled off the `_` marker for the typed1 call, so we don't know that the user has requested eta-expansion.
-            // See scala/bug#8299.
-            val funTyped = typed1(suppressMacroExpansion(expr), mode | FUNmode, WildcardType)
-            if (funTyped.tpe.isInstanceOf[OverloadedType]) inferExprAlternative(funTyped, pt)
-            funTyped match {
-              case macroDef if treeInfo.isMacroApplication(macroDef) => MacroEtaError(macroDef)
-              case methodValue                                       => typedEta(checkDead(context, methodValue))
-            }
-          case Typed(expr, tpt) =>
-            val tpt1  = typedType(tpt, mode)                           // type the ascribed type first
-            val exprWithAttachment =
-              if (definitions.isUnitType(tpt1.tpe)) expr.updateAttachment(TypedExpectingUnitAttachment)
-              else expr
-            val expr1 = typed(exprWithAttachment, mode.onlySticky, tpt1.tpe.deconst) // then type the expression with tpt1 as the expected type
-            treeCopy.Typed(tree, expr1, tpt1) setType tpt1.tpe
-        }
-      }
-
-      def typedTypeApply(tree: TypeApply) = {
-        val fun = tree.fun
-        val args = tree.args
-        // @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer)
-        //@M! we must type fun in order to type the args, as that requires the kinds of fun's type parameters.
-        // However, args should apparently be done first, to save context.undetparams. Unfortunately, the args
-        // *really* have to be typed *after* fun. We escape from this classic Catch-22 by simply saving&restoring undetparams.
-
-        // @M TODO: the compiler still bootstraps&all tests pass when this is commented out..
-        //val undets = context.undetparams
-
-        // @M: fun is typed in TAPPmode because it is being applied to its actual type parameters
-        val fun1 = typed(fun, mode.forFunMode | TAPPmode)
-        val tparams = if (fun1.symbol == null) Nil else fun1.symbol.typeParams
-
-        //@M TODO: val undets_fun = context.undetparams  ?
-        // "do args first" (by restoring the context.undetparams) in order to maintain context.undetparams on the function side.
-
-        // @M TODO: the compiler still bootstraps when this is commented out.. TODO: run tests
-        //context.undetparams = undets
-
-        // @M maybe the well-kindedness check should be done when checking the type arguments conform to the type parameters' bounds?
-        val args1 = if (sameLength(args, tparams)) map2Conserve(args, tparams) {
-          (arg, tparam) => typedHigherKindedType(arg, mode, Kind.FromParams(tparam.typeParams))
-        }
-        else {
-          //@M  this branch is correctly hit for an overloaded polymorphic type. It also has to handle erroneous cases.
-          // Until the right alternative for an overloaded method is known, be very liberal,
-          // typedTypeApply will find the right alternative and then do the same check as
-          // in the then-branch above. (see pos/tcpoly_overloaded.scala)
-          // this assert is too strict: be tolerant for errors like trait A { def foo[m[x], g]=error(""); def x[g] = foo[g/*ERR: missing argument type*/] }
-          //assert(fun1.symbol.info.isInstanceOf[OverloadedType] || fun1.symbol.isError) //, (fun1.symbol,fun1.symbol.info,fun1.symbol.info.getClass,args,tparams))
-          args mapConserve (typedHigherKindedType(_, mode))
-        }
-
-        //@M TODO: context.undetparams = undets_fun ?
-        Typer.this.typedTypeApply(tree, mode, fun1, args1)
-      }
-
-      def typedApplyDynamic(tree: ApplyDynamic) = {
-        assert(phase.erasedTypes, "typedApplyDynamic called before erasure")
-        val qual1 = typed(tree.qual, AnyRefTpe)
-        val args1 = tree.args mapConserve (arg => typed(arg, AnyRefTpe))
-        treeCopy.ApplyDynamic(tree, qual1, args1) setType AnyRefTpe
-      }
-
-      def typedReferenceToBoxed(tree: ReferenceToBoxed) = {
-        val id = tree.ident
-        val id1 = typed1(id, mode, pt) match { case id: Ident => id case x => throw new MatchError(x) }
-        // [Eugene] am I doing it right?
-        val erasedTypes = phaseId(currentPeriod) >= currentRun.erasurePhase.id
-        val tpe = capturedVariableType(id.symbol, erasedTypes = erasedTypes)
-        treeCopy.ReferenceToBoxed(tree, id1) setType tpe
-      }
-
-      // Warn about likely interpolated strings which are missing their interpolators
-      def warnMissingInterpolator(lit: Literal): Unit = if (!isPastTyper) {
-        // attempt to avoid warning about trees munged by macros
-        def isMacroExpansion = {
-          // context.tree is not the expandee; it is plain new SC(ps).m(args)
-          //context.tree exists (t => (t.pos includes lit.pos) && hasMacroExpansionAttachment(t))
-          // testing pos works and may suffice
-          //openMacros exists (_.macroApplication.pos includes lit.pos)
-          // tests whether the lit belongs to the expandee of an open macro
-          openMacros exists (_.macroApplication.attachments.get[MacroExpansionAttachment] match {
-            case Some(MacroExpansionAttachment(_, t: Tree)) => t exists (_ == lit)
-            case _                                          => false
-          })
-        }
-        // An interpolation desugars to `StringContext(parts).m(args)`, so obviously not missing.
-        // `implicitNotFound` annotations have strings with `${A}`, so never warn for that.
-        // Also don't warn for macro expansion.
-        def mightBeMissingInterpolation: Boolean = context.enclosingApply.tree match {
-          case Apply(Select(Apply(RefTree(_, nme.StringContextName), _), _), _) => false
-          case Apply(Select(New(RefTree(_, tpnme.implicitNotFound)), _), _)     => false
-          case _                                                                => !isMacroExpansion
-        }
-        def maybeWarn(s: String): Unit = {
-          def warn(message: String) = context.warning(lit.pos, s"possible missing interpolator: $message", WarningCategory.LintMissingInterpolator)
-          def isPlausible(id: String): Boolean = {
-            def requiresNoArgs(tp: Type): Boolean = tp match {
-              case PolyType(_, restpe)     => requiresNoArgs(restpe)
-              case MethodType(Nil, restpe) => requiresNoArgs(restpe)  // may be a curried method - can't tell yet
-              case MethodType(p :: _, _)   => p.isImplicit            // implicit method requires no args
-              case _                       => true                    // catches all others including NullaryMethodType
-            }
-            def isNullaryTerm: Boolean = {
-              val maybe = context.lookupSymbol(TermName(id), _ => true).symbol
-              maybe != NoSymbol && !maybe.hasPackageFlag && !maybe.isModule && maybe.alternatives.exists(x => requiresNoArgs(x.info))
-            }
-            id == "this" || isNullaryTerm
-          }
-          val suspiciousExprs  = InterpolatorCodeRegex.findAllMatchIn(s)
-          def suspiciousIdents = InterpolatorIdentRegex.findAllIn(s)
-
-          if (suspiciousExprs.hasNext) {
-            def isCheapIdent(expr: String) = Character.isJavaIdentifierStart(expr.charAt(0)) && expr.tail.forall(Character.isJavaIdentifierPart)
-            def warnableExpr(expr: String) = !expr.isEmpty && (!isCheapIdent(expr) || isPlausible(expr))
-            val exprs = suspiciousExprs.map(_ group 1).toList
-            // short-circuit on leading ${}
-            if (!exprs.head.isEmpty && exprs.exists(warnableExpr))
-              warn("detected an interpolated expression") // "${...}"
-          } else
-            suspiciousIdents.find(id => isPlausible(id.substring(1))).foreach(id => warn(s"detected interpolated identifier `$id`"))
-        }
-        lit match {
-          case Literal(Constant(s: String)) if mightBeMissingInterpolation => maybeWarn(s)
-          case _                                                           =>
-        }
-      }
-
-      def typedLiteral(tree: Literal) = {
-        if (settings.warnMissingInterpolator) warnMissingInterpolator(tree)
-
-        tree setType (if (tree.value.tag == UnitTag) UnitTpe else ConstantType(tree.value))
-      }
-
-      def typedSingletonTypeTree(tree: SingletonTypeTree) = {
-        val refTyped = typedTypeSelectionQualifier(tree.ref, WildcardType)
-
-        if (refTyped.isErrorTyped) setError(tree)
-        else {
-          // .resultType unwraps NullaryMethodType (accessor of a path)
-          // .deconst unwraps the ConstantType to a LiteralType (for literal-based singleton types)
-          if (!treeInfo.admitsTypeSelection(refTyped)) UnstableTreeError(tree)
-          else treeCopy.SingletonTypeTree(tree, refTyped).setType(refTyped.tpe.resultType.deconst)
-        }
-      }
-
-      def typedTypeBoundsTree(tree: TypeBoundsTree) = {
-        val lo1 = if (tree.lo.isEmpty) TypeTree(NothingTpe) else typedType(tree.lo, mode)
-        val hi1 = if (tree.hi.isEmpty) TypeTree(AnyTpe) else typedType(tree.hi, mode)
-        treeCopy.TypeBoundsTree(tree, lo1, hi1) setType TypeBounds(lo1.tpe, hi1.tpe)
-      }
-
-      def typedExistentialTypeTree(tree: ExistentialTypeTree) = {
-        val tree1 = typerWithLocalContext(context.makeNewScope(tree, context.owner)){
-          typer =>
-            if (context.inTypeConstructorAllowed)
-              typer.context.withinTypeConstructorAllowed(typer.typedExistentialTypeTree(tree, mode))
-            else
-              typer.typedExistentialTypeTree(tree, mode)
-        }
-        checkExistentialsFeature(tree1.pos, tree1.tpe, "the existential type")
-        tree1
-      }
-
-      def typedTypeTree(tree: TypeTree) = {
-        if (tree.original != null) {
-          val newTpt = typedType(tree.original, mode)
-          tree setType newTpt.tpe
-          newTpt match {
-            case tt @ TypeTree() => tree setOriginal tt.original
-            case _ => tree
-          }
-        }
-        else {
-          // we should get here only when something before failed
-          // and we try again (@see tryTypedApply). In that case we can assign
-          // whatever type to tree; we just have to survive until a real error message is issued.
-          devWarning(tree.pos, s"Assigning Any type to TypeTree because tree.original is null: tree is $tree/${System.identityHashCode(tree)}, sym=${tree.symbol}, tpe=${tree.tpe}")
-          tree setType AnyTpe
-        }
-      }
-      def typedFunction(fun: Function) = {
-        if (fun.symbol == NoSymbol)
-          fun.symbol = context.owner.newAnonymousFunctionValue(fun.pos)
-
-        typerWithLocalContext(context.makeNewScope(fun, fun.symbol))(_.typedFunction(fun, mode, pt))
-      }
-
-      // Trees only allowed during pattern mode.
-      def typedInPatternMode(tree: Tree): Tree = tree match {
-        case tree: Alternative => typedAlternative(tree)
-        case tree: Star        => typedStar(tree)
-        case _                 => abort(s"unexpected tree in pattern mode: ${tree.getClass}\n$tree")
-      }
-
-      @inline def typedTypTree(tree: TypTree): Tree = tree match {
-        case tree: TypeTree                     => typedTypeTree(tree)
-        case tree: AppliedTypeTree              => typedAppliedTypeTree(tree)
-        case tree: TypeBoundsTree               => typedTypeBoundsTree(tree)
-        case tree: SingletonTypeTree            => typedSingletonTypeTree(tree)
-        case tree: SelectFromTypeTree           => typedSelect(tree, typedType(tree.qualifier, mode), tree.name)
-        case tree: CompoundTypeTree             => typedCompoundTypeTree(tree)
-        case tree: ExistentialTypeTree          => typedExistentialTypeTree(tree)
-        case tree: TypeTreeWithDeferredRefCheck => tree // TODO: retype the wrapped tree? TTWDRC would have to change to hold the wrapped tree (not a closure)
-        case _                                  => abort(s"unexpected type-representing tree: ${tree.getClass}\n$tree")
-      }
-
-      @inline def typedMemberDef(tree: MemberDef): Tree = tree match {
-        case tree: ValDef     => typedValDef(tree)
-        case tree: DefDef     => defDefTyper(tree).typedDefDef(tree)
-        case tree: ClassDef   => newTyper(context.makeNewScope(tree, sym)).typedClassDef(tree)
-        case tree: ModuleDef  => newTyper(context.makeNewScope(tree, sym.moduleClass)).typedModuleDef(tree)
-        case tree: TypeDef    => typedTypeDef(tree)
-        case tree: PackageDef => typedPackageDef(tree)
-        case _                => abort(s"unexpected member def: ${tree.getClass}\n$tree")
-      }
-
-      // Trees not allowed during pattern mode.
-      def typedOutsidePatternMode(tree: Tree): Tree = tree match {
-        case tree: Block            => typerWithLocalContext(context.makeNewScope(tree, context.owner))(_.typedBlock(tree, mode, pt))
-        case tree: If               => typedIf(tree)
-        case tree: TypeApply        => typedTypeApply(tree)
-        case tree: Function         => typedFunction(tree)
-        case tree: Match            => typedVirtualizedMatch(tree)
-        case tree: New              => typedNew(tree)
-        case tree: Assign           => typedAssign(tree.lhs, tree.rhs)
-        case tree: NamedArg         => typedAssign(tree.lhs, tree.rhs)
-        case tree: Super            => typedSuper(tree)
-        case tree: Annotated        => typedAnnotated(tree)
-        case tree: Return           => typedReturn(tree)
-        case tree: Try              => typedTry(tree)
-        case tree: Throw            => typedThrow(tree)
-        case tree: ArrayValue       => typedArrayValue(tree)
-        case tree: ApplyDynamic     => typedApplyDynamic(tree)
-        case tree: ReferenceToBoxed => typedReferenceToBoxed(tree)
-        case tree: LabelDef         => labelTyper(tree).typedLabelDef(tree)
-        case tree: DocDef           => typedDocDef(tree, mode, pt)
-        case _                      => abort(s"unexpected tree: ${tree.getClass}\n$tree")
-      }
-
-      // Trees allowed in or out of pattern mode.
-      @inline def typedInAnyMode(tree: Tree): Tree = tree match {
-        case tree: Ident   => typedIdentOrWildcard(tree)
-        case tree: Bind    => typedBind(tree)
-        case tree: Apply   => typedApply(tree)
-        case tree: Select  => typedSelectOrSuperCall(tree)
-        case tree: Literal => typedLiteral(tree)
-        case tree: Typed   => typedTyped(tree)
-        case tree: This    => typedThis(tree)  // scala/bug#6104
-        case tree: UnApply => abort(s"unexpected UnApply $tree") // turns out UnApply never reaches here
-        case _             =>
-          if (mode.inPatternMode)
-            typedInPatternMode(tree)
-          else
-            typedOutsidePatternMode(tree)
-      }
-
-      // begin typed1
-      tree match {
-        case tree: TypTree   => typedTypTree(tree)
-        case tree: MemberDef => typedMemberDef(tree)
-        case _               => typedInAnyMode(tree)
-      }
-    }
-
-    def typed(tree: Tree, mode: Mode, pt: Type): Tree = {
-      lastTreeToTyper = tree
-      val startByType = if (settings.areHotStatisticsEnabled) statistics.pushTimer(byTypeStack, byTypeNanos(tree.getClass)) else null
-      if (settings.areHotStatisticsEnabled) statistics.incCounter(visitsByType, tree.getClass)
-      val shouldPrintTyping = printTypings && !phase.erasedTypes && !noPrintTyping(tree)
-      val shouldPopTypingStack = shouldPrintTyping && typingStack.beforeNextTyped(tree, mode, pt, context)
-
-      def shouldInsertStabilizersImpl = tree match {
-        case _ if phase.erasedTypes || mode.in(APPSELmode) || isMacroImplRef(tree) => false
-        case _: Select | _: Apply | _: TypeApply                                   => true
-        case _                                                                     => false
-      }
-
-      val shouldInsertStabilizers = shouldInsertStabilizersImpl
-      val mode1: Mode = if (shouldInsertStabilizers) mode | APPSELmode else mode
-      val savedPendingStabilizer = context.pendingStabilizers
-      if (shouldInsertStabilizers) context.pendingStabilizers = Nil
-
-      try {
-        val ptPlugins = pluginsPt(pt, this, tree, mode1)
-        def retypingOk = (
-          context.retyping
-            && (tree.tpe ne null)
-            && (tree.tpe.isErroneous || !(tree.tpe <:< ptPlugins))
-          )
-        if (retypingOk) {
-          tree.setType(null)
-          if (tree.hasSymbolField) tree.symbol = NoSymbol
-        }
-        val alreadyTyped = tree.tpe ne null
-        val shouldPrint = !alreadyTyped && !phase.erasedTypes
-        val ptWild = if (mode1.inPatternMode)
-          ptPlugins // scala/bug#5022 don't widen pt for patterns as types flow from it to the case body.
-        else
-          dropExistential(ptPlugins) // FIXME: document why this is done.
-        val tree1: Tree = if (alreadyTyped) tree else typed1(tree, mode1, ptWild)
-
-        if (shouldPrint)
-          typingStack.showTyped(tree1)
-
-        // Can happen during erroneous compilation - error(s) have been
-        // reported, but we need to avoid causing an NPE with this tree
-        if (tree1.tpe eq null)
-          return setError(tree)
-
-        tree1 setType pluginsTyped(tree1.tpe, this, tree1, mode1, ptPlugins)
-
-        val adapted =
-          if (tree1.isEmpty) tree1
-          else {
-            val result = adapt(tree1, mode1, ptPlugins, tree)
-            if (typerShouldExpandDeferredMacros) {
-              macroExpandAll(this, result)
-            } else result
-          }
-
-        val result =
-          if (shouldInsertStabilizers) addStabilizers(context.pendingStabilizers, adapted)
-          else adapted
-
-        if (shouldPrint)
-          typingStack.showAdapt(tree1, result, ptPlugins, context)
-
-        if (!isPastTyper)
-          signalDone(context.asInstanceOf[analyzer.Context], tree, result)
-
-        if (mode1.inPatternMode && !mode1.inPolyMode && result.isType)
-          PatternMustBeValue(result, pt)
-
-        if (shouldPopTypingStack) typingStack.showPop(result)
-
-        result
-      } catch {
-        case ex: CyclicReference if global.propagateCyclicReferences =>
-          throw ex
-        case ex: TypeError =>
-          tree.clearType()
-          // The only problematic case are (recoverable) cyclic reference errors which can pop up almost anywhere.
-          typingStack.printTyping(tree, "caught %s: while typing %s".format(ex, tree)) //DEBUG
-          reportTypeError(context, tree.pos, ex)
-          setError(tree)
-        case ex: Exception =>
-          // @M causes cyclic reference error
-          devWarning(s"exception when typing $tree, pt=$pt")
-          if (context != null && context.unit.exists && tree != null)
-            logError("AT: " + tree.pos, ex)
-          throw ex
-      } finally {
-        if (shouldPopTypingStack) typingStack.pop(tree)
-        if (settings.areHotStatisticsEnabled) statistics.popTimer(byTypeStack, startByType)
-        if (shouldInsertStabilizers) context.pendingStabilizers = savedPendingStabilizer
-      }
-    }
-
-    private def addStabilizers(newStabilizers: List[Tree], expr: Tree): Tree = {
-      if (newStabilizers.isEmpty) expr else {
-        devWarningIf(newStabilizers.forall(_.symbol.owner == context.owner))(s"${context.owner} - ${(newStabilizers.map(vd => (vd.symbol, vd.symbol.owner.fullNameString)), context.owner)}")
-        // Insert stabilizing ValDefs (if any) which might have been introduced during the typing of the original expression.
-        Block(newStabilizers.reverse, expr).setPos(expr.pos).setType(expr.tpe)
-      }
-    }
-
-    def atOwner(owner: Symbol): Typer =
-      newTyper(context.make(owner = owner))
-
-    def atOwner(tree: Tree, owner: Symbol): Typer =
-      newTyper(context.make(tree, owner))
-
-    /** Types expression or definition `tree`.
-     */
-    @inline final def typed(tree: Tree): Tree =
-      typed(tree, context.defaultModeForTyped, WildcardType)
-
-    @inline final def typedByValueExpr(tree: Tree, pt: Type = WildcardType): Tree = typed(tree, EXPRmode | BYVALmode, pt)
-
-    def typedPos(pos: Position, mode: Mode, pt: Type)(tree: Tree) = typed(atPos(pos)(tree), mode, pt)
-    def typedPos(pos: Position)(tree: Tree) = typed(atPos(pos)(tree))
-    // TODO: see if this formulation would impose any penalty, since
-    // it makes for a lot less casting.
-    // def typedPos[T <: Tree](pos: Position)(tree: T): T = typed(atPos(pos)(tree)).asInstanceOf[T]
-
-    /** Types expression `tree` with given prototype `pt`.
-     */
-    @inline final def typed(tree: Tree, pt: Type): Tree =
-      typed(tree, context.defaultModeForTyped, pt)
-
-    @inline final def typed(tree: Tree, mode: Mode): Tree =
-      typed(tree, mode, WildcardType)
-
-    /** Types qualifier `tree` of a select node.
-     *  E.g. is tree occurs in a context like `tree.m`.
-     */
-    @inline final def typedQualifier(tree: Tree, mode: Mode, pt: Type): Tree =
-      typed(checkRootOfQualifier(tree, mode), PolyQualifierModes | mode.onlyTypePat, pt) // TR: don't set BYVALmode, since qualifier might end up as by-name param to an implicit
-
-    /** Types qualifier `tree` of a select node.
-     *  E.g. is tree occurs in a context like `tree.m`.
-     */
-    @inline final def typedQualifier(tree: Tree, mode: Mode): Tree =
-      typedQualifier(tree, mode, WildcardType)
-
-    @inline final def typedQualifier(tree: Tree): Tree = typedQualifier(tree, NOmode, WildcardType)
-
-    // if a package id is a selection from _root_ in scope, warn about semantics and set symbol for typedQualifier
-    @inline final def typedPackageQualifier(tree: Tree): Tree = typedQualifier(checkRootOfPackageQualifier(tree))
-
-    def checkRootOfPackageQualifier(q: Tree): Tree = {
-      q match {
-        case Select(id @ Ident(nme.ROOTPKG), _) if !id.hasExistingSymbol && id.hasAttachment[RootSelection.type] =>
-          context.lookupSymbol(nme.ROOTPKG, p => p.hasPackageFlag && !p.isRootPackage) match {
-            case LookupSucceeded(_, sym) =>
-              runReporting.warning(
-                id.pos,
-                s"${nme.ROOTPKG} in root position in package definition does not refer to the root package, but to ${sym.fullLocationString}, which is in scope",
-                WarningCategory.Other,
-                context.owner)
-              id.removeAttachment[RootSelection.type]
-              id.setSymbol(sym)
-            case _ =>
-          }
-        case _ =>
-      }
-      q
-    }
-
-    /** If import from path starting with _root_, warn if there is a _root_ value in scope,
-     *  and ensure _root_ can only be the root package in that position.
-     */
-    def checkRootOfQualifier(q: Tree, mode: Mode): Tree = {
-      q match {
-        case Ident(nme.ROOTPKG) if !q.hasExistingSymbol && q.hasAttachment[RootSelection.type] =>
-          val startContext = if (mode.typingPatternOrTypePat) context.outer else context
-          startContext.lookupSymbol(nme.ROOTPKG, !_.isRootPackage) match {
-            case LookupSucceeded(_, sym) =>
-              runReporting.warning(
-                q.pos,
-                s"${nme.ROOTPKG} in root position of qualifier refers to the root package, not ${sym.fullLocationString}, which is in scope",
-                WarningCategory.Other,
-                context.owner)
-            case _ =>
-          }
-          q.setSymbol(rootMirror.RootPackage)
-        case _ =>
-      }
-      q
-    }
-
-    /** Types function part of an application */
-    @inline final def typedOperator(tree: Tree): Tree = typed(tree, OperatorModes)
-
-    // the qualifier type of a supercall constructor is its first parent class
-    private def typedSelectOrSuperQualifier(qual: Tree) =
-      context withinSuperInit typed(qual, PolyQualifierModes)
-
-    /** Types a pattern with prototype `pt` */
-    def typedPattern(tree: Tree, pt: Type): Tree = {
-      // We disable implicits because otherwise some constructs will
-      // type check which should not.  The pattern matcher does not
-      // perform implicit conversions in an attempt to consummate a match.
-
-      // on the one hand,
-      //   "abc" match { case Seq('a', 'b', 'c') => true }
-      // should be ruled out statically, otherwise this is a runtime
-      // error both because there is an implicit from String to Seq
-      // (even though such implicits are not used by the matcher) and
-      // because the typer is fine with concluding that "abc" might
-      // be of type "String with Seq[T]" and thus eligible for a call
-      // to unapplySeq.
-
-      // on the other hand, we want to be able to use implicits to add members retro-actively (e.g., add xml to StringContext)
-
-      // as a compromise, context.enrichmentEnabled tells adaptToMember to go ahead and enrich,
-      // but arbitrary conversions (in adapt) are disabled
-      // TODO: can we achieve the pattern matching bit of the string interpolation SIP without this?
-      typingInPattern(context.withImplicitsDisabledAllowEnrichment(typed(tree, PATTERNmode, pt)))
-    }
-
-    /** Types a (fully parameterized) type tree */
-    def typedType(tree: Tree, mode: Mode): Tree =
-      typed(tree, mode.forTypeMode, WildcardType)
-
-    /** Types a (fully parameterized) type tree */
-    def typedType(tree: Tree): Tree = typedType(tree, NOmode)
-
-    /** Types a higher-kinded type tree -- pt denotes the expected kind and must be one of `Kind.WildCard` and `Kind.FromParams` */
-    def typedHigherKindedType(tree: Tree, mode: Mode, pt: Type): Tree =
-      if (pt != Kind.Wildcard && pt.typeParams.isEmpty) typedType(tree, mode) // kind is known and it's *
-      else context withinTypeConstructorAllowed typed(tree, NOmode, pt)
-
-    def typedHigherKindedType(tree: Tree, mode: Mode): Tree =
-      context withinTypeConstructorAllowed typed(tree)
-
-    /** Types a type constructor tree used in a new or supertype */
-    def typedTypeConstructor(tree: Tree, mode: Mode): Tree = {
-      val result = typed(tree, mode.forTypeMode | FUNmode, WildcardType)
-
-      // get rid of type aliases for the following check (#1241)
-      result.tpe.dealias match {
-        case restpe @ TypeRef(pre, _, _) if !phase.erasedTypes && !pre.isStable && !context.unit.isJava =>
-          // The isJava exception if OK only because the only type constructors scalac gets
-          // to see are those in the signatures. These do not need a unique object as a prefix.
-          // The situation is different for new's and super's, but scalac does not look deep
-          // enough to see those. See #3938
-          ConstructorPrefixError(tree, restpe)
-        case _ =>
-          // must not normalize: type application must be (bounds-)checked (during RefChecks), see #2208
-          // during uncurry (after refchecks), all types are normalized
-          result
-      }
-    }
-
-    def typedTypeConstructor(tree: Tree): Tree = typedTypeConstructor(tree, NOmode)
-
-    def computeType(tree: Tree, pt: Type): Type = {
-      // macros employ different logic of `computeType`
-      assert(!context.owner.isMacro, context.owner)
-      val tree1 = typed(tree, pt)
-      transformed(tree) = tree1
-      val tpe = packedType(tree1, context.owner)
-      checkExistentialsFeature(tree.pos, tpe, "inferred existential type")
-      tpe
-    }
-
-    def computeMacroDefType(ddef: DefDef, pt: Type): Type = {
-      assert(context.owner.isMacro, context.owner)
-      assert(ddef.symbol.isMacro, ddef.symbol)
-
-      // macro defs are typechecked in `methodSig` (by calling this method) in order to establish their link to macro implementation asap
-      // if a macro def doesn't have explicitly specified return type, this method will be called again by `assignTypeToTree`
-      // here we guard against this case
-      val rhs1 =
-      if (transformed contains ddef.rhs) {
-        transformed(ddef.rhs)
-      } else {
-        val rhs1 = typedMacroBody(this, ddef)
-        transformed(ddef.rhs) = rhs1
-        rhs1
-      }
-
-      val isMacroBodyOkay = !ddef.symbol.isErroneous && !(rhs1 exists (_.isErroneous)) && rhs1 != EmptyTree
-      val shouldInheritMacroImplReturnType = ddef.tpt.isEmpty
-      if (isMacroBodyOkay && shouldInheritMacroImplReturnType) {
-        val commonMessage = "macro defs must have explicitly specified return types"
-        def reportFailure() = {
-          ddef.symbol.setFlag(IS_ERROR)
-          context.error(ddef.pos, commonMessage)
-        }
-        reportFailure()
-      }
-      AnyTpe
-    }
-
-    @inline final def transformedOr(tree: Tree, op: => Tree): Tree = lookupTransformed(tree) match {
-      case Some(tree1) => tree1
-      case _           => op
-    }
-
-    @inline
-    final def transformedOrTyped(tree: Tree, mode: Mode, pt: Type): Tree = {
-      lookupTransformed(tree) match {
-        case Some(tree1) => tree1
-        case _           => if (canSkipRhs(tree)) EmptyTree else typed(tree, mode, pt)
-      }
-    }
-    final def lookupTransformed(tree: Tree): Option[Tree] =
-      if (phase.erasedTypes) None // OPT save the hashmap lookup in erasure type and beyond
-      else transformed remove tree
-
-    private final def canSkipRhs(tree: Tree) = settings.Youtline.value && !tree.exists {
-      case Super(_, mix) =>
-        // conservative approximation of method bodies that may give rise to super accessors which must be
-        // stored in pickle.
-        context.owner.enclClass.isTrait || mix != tpnme.EMPTY
-      case _ => false
-    }
-  }
-
-  /** Finish computation of param aliases after typechecking is completed */
-  final def finishComputeParamAlias(): Unit = {
-    val classes = superConstructorCalls.keys.toArray
-    // superclasses before subclasses to avoid a data race between `superAcc.alias` and `acc.setAlias` below.
-    scala.util.Sorting.quickSort(classes)(Ordering.fromLessThan((a, b) => b.isLess(a)))
-
-    for (sym <- classes) {
-      for ((ownAcc, superAcc) <- superConstructorCalls.getOrElse(sym, Nil)) {
-        // We have a corresponding parameter in the super class.
-        val superClazz = sym.superClass
-        val alias = (
-          superAcc.initialize.alias // Is the param accessor is an alias for a field further up  the class hierarchy?
-            orElse (superAcc getterIn superAcc.owner) // otherwise, lookup the accessor for the super
-            filter (alias => superClazz.info.nonPrivateMember(alias.name) == alias) // the accessor must be public
-          )
-        if (alias.exists && !alias.accessed.isVariable && !isRepeatedParamType(alias.accessed.info)) {
-          ownAcc match {
-            case acc: TermSymbol if !acc.isVariable && !isByNameParamType(acc.info) =>
-              debuglog(s"$acc has alias ${alias.fullLocationString}")
-              acc setAlias alias
-            case _ =>
-          }
-        }
-      }
-    }
-    superConstructorCalls.clear()
   }
 
 }
-
-trait TypersStats {
-  self: TypesStats with Statistics =>
-  val typedIdentCount     = newCounter("#typechecked identifiers")
-  val typedSelectCount    = newCounter("#typechecked selections")
-  val typedApplyCount     = newCounter("#typechecked applications")
-  val subtypeFailed       = newSubCounter("  of which in failed", subtypeCount)
-  val findMemberFailed    = newSubCounter("  of which in failed", findMemberCount)
-  val failedSilentNanos   = newSubTimer("time spent in failed", typerNanos)
-  val failedApplyNanos    = newSubTimer("  failed apply", typerNanos)
-  val failedOpEqNanos     = newSubTimer("  failed op=", typerNanos)
-  val isReferencedNanos   = newSubTimer("time spent ref scanning", typerNanos)
-  val visitsByType        = newByClass("#visits by tree node", "typer")(newCounter(""))
-  val byTypeNanos         = newByClass("time spent by tree node", "typer")(newStackableTimer("", typerNanos))
-  val byTypeStack         = newTimerStack()
-}