aboutsummaryrefslogblamecommitdiff
path: root/src/dotty/tools/dotc/ast/untpd.scala
blob: cc7cefbac488e34273639246e2f656c5ca3d9e37 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                                                                      
                                                                                     
                   
                    


                                    
                                                                   
 
                                                                        
 





                                       


                                                                            
                                                                                        

                        
 




                                                                   
                              
                                                      
                       
                                                                                            
                                                                                                
   
 

                                                                                   
                                                    






                                                                                                    



                                                                  






                                                                                                               









                                                                      
                                               






                                                                                        
                                                                                            
 

                                                                                   
 









                                                                                                 













































                                                                                  




























                                                                                 
                                                                


                                                                      
                                               
 
                                                                      


                                                                    
                                               
 











                                                                                                                  




                                                                               
                                                                                            


                                                                                          
                                                                                                   

                                                                                                           
                                                                                                                           


                                                                                  



                                                                                                                  
                                                                                                            
                                                                               


                                                                                     
                                                                                                                      

                                                                                                                                                                    
                                                                          
                                                                                                                                           

                                                                                           
                                                                              




                                                                                         


                                                  
     
                                                                              
                                    


                                                        
                                                        
                                     
                                        




                                                           


                                                          
                                                 
   






                                            




                                            


                                                              
                                                                                                              
 

                                                                                    
 
                                         
 

                                                       
 


                                                              
                                    
 

                                                                                                                                   
 
                                                       
                             
 
                                                                     
                                                        
 



                                                                           
 



                                                                   
 

                                                                                                                  
 
                                                                                                 
                                                                                   
 



                                                                     

                                                                               
   
 


                                                                                         


                                                                                 
 
                                                                       


                           

                                                                           


                                                             
 


                                                                         









                                                                                
     




                                                                                                    


                                                                                                             
     
                                                         
                                                     
                                                      
     


                                                                                             
     
                                                                         
                                                                               
                                                            
     
                                                                             
                                                                                                   
                                                                
     
                                                                
                                                                        
                                                         
     
                                                               
                                                                       
                                                        
     
                                                  
                                              
                                                 
     
                                                           
                                                     
                                                    
     
                                                    
                                                   

                                                   
                                                                  
                                                                              
                                                           
     
                                                                  
                                                                              
                                                           
     
                                                                          
                                                                                 
                                                             
     
                                                                       
                                                                              
                                                          
     
                                                                 
                                                                            
                                                          
     
                                                                  
                                                                             
                                                           
     
                                                                                              
                                                                                                
                                                                       
     
                                                                                                  
                                                                                                                       
                                                                    


     
                                                                                          
                                                                                  

                                                     

                                                                                      
                            
                                

                                                             
                                  
                                                            
                                      
                                                                
                               
                                              
                              
                                             
                       
                                      
                          
                                         

                                        
                                 
                                                           
                                 
                                                           
                                   
                                                             
                                
                                                          
                                
                                                          
                                 
                                                           
                                             
                                                                          
                                          
                                                                               
                               
                                                                                         




                             
                                                                       
                                                                                    
                                   
                     

                                                     

                            

                                              











                                      

                         















                                             

                                             

                               



                               
 




                                                                                      

                                                                                                                  
                                                                                                   

                                         
 
package dotty.tools
package dotc
package ast

import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
import Denotations._, SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
import Decorators._
import util.Property
import language.higherKinds
import collection.mutable.ListBuffer

object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {

  // ----- Tree cases that exist in untyped form only ------------------

  trait OpTree extends Tree {
    def op: Name
    override def isTerm = op.isTermName
    override def isType = op.isTypeName
  }

  /** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice
   *  @param owner  The current owner at the time the tree was defined
   */
  abstract case class TypedSplice(tree: tpd.Tree)(val owner: Symbol) extends ProxyTree {
    def forwardTo = tree
  }

  object TypedSplice {
    def apply(tree: tpd.Tree)(implicit ctx: Context): TypedSplice =
      new TypedSplice(tree)(ctx.owner) {}
  }

  /** mods object name impl */
  case class ModuleDef(name: TermName, impl: Template)
    extends MemberDef {
    type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef
    def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this)(name.toTermName, impl)
  }

  case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree

  case class SymbolLit(str: String) extends TermTree

  /** An interpolated string
   *  @param segments  a list of two element tickets consisting of string literal and argument tree,
   *                   possibly with a simple string literal as last element of the list
   */
  case class InterpolatedString(id: TermName, segments: List[Tree]) extends TermTree

  case class Function(args: List[Tree], body: Tree) extends Tree {
    override def isTerm = body.isTerm
    override def isType = body.isType
  }
  /** A function created from a wildcard expression
   *  @param  placeHolderParams  a list of definitions of synthetic parameters
   *  @param  body               the function body where wildcards are replaced by
   *                             references to synthetic parameters.
   */
  class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body)

  case class InfixOp(left: Tree, op: Name, right: Tree) extends OpTree
  case class PostfixOp(od: Tree, op: Name) extends OpTree
  case class PrefixOp(op: Name, od: Tree) extends OpTree
  case class Parens(t: Tree) extends ProxyTree {
    def forwardTo = t
  }
  case class Tuple(trees: List[Tree]) extends Tree {
    override def isTerm = trees.isEmpty || trees.head.isTerm
    override def isType = !isTerm
  }
  case class Throw(expr: Tree) extends TermTree
  case class WhileDo(cond: Tree, body: Tree) extends TermTree
  case class DoWhile(body: Tree, cond: Tree) extends TermTree
  case class ForYield(enums: List[Tree], expr: Tree) extends TermTree
  case class ForDo(enums: List[Tree], body: Tree) extends TermTree
  case class GenFrom(pat: Tree, expr: Tree) extends Tree
  case class GenAlias(pat: Tree, expr: Tree) extends Tree
  case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree
  case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree

  class PolyTypeDef(name: TypeName, override val tparams: List[TypeDef], rhs: Tree)
    extends TypeDef(name, rhs)

  /** A block arising from a right-associative infix operation, where, e.g.
   *
   *     a +: b
   *
   *  is expanded to
   *
   *     { val x = a; b.+:(x) }
   */
  class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp)

  // ----- Modifiers -----------------------------------------------------

 /** Modifiers and annotations for definitions
   *  @param flags          The set flags
   *  @param privateWithin  If a private or protected has is followed by a
   *                        qualifier [q], the name q, "" as a typename otherwise.
   *  @param annotations    The annotations preceding the modifiers
   */
  case class Modifiers (
    flags: FlagSet = EmptyFlags,
    privateWithin: TypeName = tpnme.EMPTY,
    annotations: List[Tree] = Nil) extends Positioned with Cloneable {

    def is(fs: FlagSet): Boolean = flags is fs
    def is(fc: FlagConjunction): Boolean = flags is fc

    def | (fs: FlagSet): Modifiers = withFlags(flags | fs)
    def & (fs: FlagSet): Modifiers = withFlags(flags & fs)
    def &~(fs: FlagSet): Modifiers = withFlags(flags &~ fs)

    def toTypeFlags: Modifiers = withFlags(flags.toTypeFlags)
    def toTermFlags: Modifiers = withFlags(flags.toTermFlags)

    def withFlags(flags: FlagSet) =
      if (this.flags == flags) this
      else copy(flags = flags)

    def withAddedAnnotation(annot: Tree): Modifiers =
      if (annotations.exists(_ eq annot)) this
      else withAnnotations(annotations :+ annot)

    def withAnnotations(annots: List[Tree]): Modifiers =
      if (annots eq annotations) this
      else copy(annotations = annots)

    def withPrivateWithin(pw: TypeName) =
      if (pw.isEmpty) this
      else copy(privateWithin = pw)

    def hasFlags = flags != EmptyFlags
    def hasAnnotations = annotations.nonEmpty
    def hasPrivateWithin = privateWithin != tpnme.EMPTY
  }

  @sharable val EmptyModifiers: Modifiers = new Modifiers()

  // ----- TypeTrees that refer to other tree's symbols -------------------

  /** A type tree that gets its type from some other tree's symbol. Enters the
   *  type tree in the References attachment of the `from` tree as a side effect.
   */
  abstract class DerivedTypeTree extends TypeTree(EmptyTree) {

    private var myWatched: Tree = EmptyTree

    /** The watched tree; used only for printing */
    def watched: Tree = myWatched

    /** Install the derived type tree as a dependency on `original` */
    def watching(original: DefTree): this.type = {
      myWatched = original
      val existing = original.attachmentOrElse(References, Nil)
      original.putAttachment(References, this :: existing)
      this
    }

    /** A hook to ensure that all necessary symbols are completed so that
     *  OriginalSymbol attachments are propagated to this tree
     */
    def ensureCompletions(implicit ctx: Context): Unit = ()

    /** The method that computes the type of this tree */
    def derivedType(originalSym: Symbol)(implicit ctx: Context): Type
  }

    /** Property key containing TypeTrees whose type is computed
   *  from the symbol in this type. These type trees have marker trees
   *  TypeRefOfSym or InfoOfSym as their originals.
   */
  val References = new Property.Key[List[Tree]]

  /** Property key for TypeTrees marked with TypeRefOfSym or InfoOfSym
   *  which contains the symbol of the original tree from which this
   *  TypeTree is derived.
   */
  val OriginalSymbol = new Property.Key[Symbol]

  // ------ Creation methods for untyped only -----------------

  def Ident(name: Name): Ident = new Ident(name)
  def BackquotedIdent(name: Name): BackquotedIdent = new BackquotedIdent(name)
  def Select(qualifier: Tree, name: Name): Select = new Select(qualifier, name)
  def SelectWithSig(qualifier: Tree, name: Name, sig: Signature): Select = new SelectWithSig(qualifier, name, sig)
  def This(qual: TypeName): This = new This(qual)
  def Super(qual: Tree, mix: TypeName): Super = new Super(qual, mix)
  def Apply(fun: Tree, args: List[Tree]): Apply = new Apply(fun, args)
  def TypeApply(fun: Tree, args: List[Tree]): TypeApply = new TypeApply(fun, args)
  def Literal(const: Constant): Literal = new Literal(const)
  def New(tpt: Tree): New = new New(tpt)
  def Typed(expr: Tree, tpt: Tree): Typed = new Typed(expr, tpt)
  def NamedArg(name: Name, arg: Tree): NamedArg = new NamedArg(name, arg)
  def Assign(lhs: Tree, rhs: Tree): Assign = new Assign(lhs, rhs)
  def Block(stats: List[Tree], expr: Tree): Block = new Block(stats, expr)
  def If(cond: Tree, thenp: Tree, elsep: Tree): If = new If(cond, thenp, elsep)
  def Closure(env: List[Tree], meth: Tree, tpt: Tree): Closure = new Closure(env, meth, tpt)
  def Match(selector: Tree, cases: List[CaseDef]): Match = new Match(selector, cases)
  def CaseDef(pat: Tree, guard: Tree, body: Tree): CaseDef = new CaseDef(pat, guard, body)
  def Return(expr: Tree, from: Tree): Return = new Return(expr, from)
  def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree): Try = new Try(expr, cases, finalizer)
  def SeqLiteral(elems: List[Tree], elemtpt: Tree): SeqLiteral = new SeqLiteral(elems, elemtpt)
  def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt)
  def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree): Inlined = new Inlined(call, bindings, expansion)
  def TypeTree(original: Tree): TypeTree = new TypeTree(original)
  def TypeTree() = new TypeTree(EmptyTree)
  def SingletonTypeTree(ref: Tree): SingletonTypeTree = new SingletonTypeTree(ref)
  def AndTypeTree(left: Tree, right: Tree): AndTypeTree = new AndTypeTree(left, right)
  def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right)
  def RefinedTypeTree(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = new RefinedTypeTree(tpt, refinements)
  def AppliedTypeTree(tpt: Tree, args: List[Tree]): AppliedTypeTree = new AppliedTypeTree(tpt, args)
  def TypeLambdaTree(tparams: List[TypeDef], body: Tree): TypeLambdaTree = new TypeLambdaTree(tparams, body)
  def ByNameTypeTree(result: Tree): ByNameTypeTree = new ByNameTypeTree(result)
  def TypeBoundsTree(lo: Tree, hi: Tree): TypeBoundsTree = new TypeBoundsTree(lo, hi)
  def Bind(name: Name, body: Tree): Bind = new Bind(name, body)
  def Alternative(trees: List[Tree]): Alternative = new Alternative(trees)
  def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree]): UnApply = new UnApply(fun, implicits, patterns)
  def ValDef(name: TermName, tpt: Tree, rhs: LazyTree): ValDef = new ValDef(name, tpt, rhs)
  def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs)
  def TypeDef(name: TypeName, rhs: Tree): TypeDef = new TypeDef(name, rhs)
  def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList): Template = new Template(constr, parents, self, body)
  def Import(expr: Tree, selectors: List[untpd.Tree]): Import = new Import(expr, selectors)
  def PackageDef(pid: RefTree, stats: List[Tree]): PackageDef = new PackageDef(pid, stats)
  def Annotated(arg: Tree, annot: Tree): Annotated = new Annotated(arg, annot)

  // ------ Additional creation methods for untyped only -----------------

  // def TypeTree(tpe: Type): TypeTree = TypeTree().withType(tpe) todo: move to untpd/tpd

  /**     new pre.C[Ts](args1)...(args_n)
   *  ==>
   *      (new pre.C).<init>[Ts](args1)...(args_n)
   */
  def New(tpt: Tree, argss: List[List[Tree]])(implicit ctx: Context): Tree = {
    val (tycon, targs) = tpt match {
      case AppliedTypeTree(tycon, targs) =>
        (tycon, targs)
      case TypedSplice(AppliedTypeTree(tycon, targs)) =>
        (TypedSplice(tycon), targs map (TypedSplice(_)))
      case TypedSplice(tpt1: Tree) =>
        val argTypes = tpt1.tpe.argTypes
        val tycon = tpt1.tpe.withoutArgs(argTypes)
        def wrap(tpe: Type) = TypeTree(tpe) withPos tpt.pos
        (wrap(tycon), argTypes map wrap)
      case _ =>
        (tpt, Nil)
    }
    var prefix: Tree = Select(New(tycon), nme.CONSTRUCTOR)
    if (targs.nonEmpty) prefix = TypeApply(prefix, targs)
    ensureApplied((prefix /: argss)(Apply(_, _)))
  }

  def Block(stat: Tree, expr: Tree): Block =
    Block(stat :: Nil, expr)

  def Apply(fn: Tree, arg: Tree): Apply =
    Apply(fn, arg :: Nil)

  def ensureApplied(tpt: Tree) = tpt match {
    case _: Apply => tpt
    case _ => Apply(tpt, Nil)
  }

  def AppliedTypeTree(tpt: Tree, arg: Tree): AppliedTypeTree =
    AppliedTypeTree(tpt, arg :: Nil)

  def TypeTree(tpe: Type)(implicit ctx: Context): TypedSplice = TypedSplice(TypeTree().withTypeUnchecked(tpe))

  def TypeDef(name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef =
    if (tparams.isEmpty) TypeDef(name, rhs) else new PolyTypeDef(name, tparams, rhs)

  def unitLiteral = Literal(Constant(()))

  def ref(tp: NamedType)(implicit ctx: Context): Tree =
    TypedSplice(tpd.ref(tp))

  def rootDot(name: Name) = Select(Ident(nme.ROOTPKG), name)
  def scalaDot(name: Name) = Select(rootDot(nme.scala_), name)
  def scalaUnit = scalaDot(tpnme.Unit)
  def scalaAny = scalaDot(tpnme.Any)

  def makeConstructor(tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef =
    DefDef(nme.CONSTRUCTOR, tparams, vparamss, TypeTree(), rhs)

  def emptyConstructor(implicit ctx: Context): DefDef =
    makeConstructor(Nil, Nil)

  def makeSelfDef(name: TermName, tpt: Tree)(implicit ctx: Context) =
    ValDef(name, tpt, EmptyTree).withFlags(PrivateLocal)

  def makeTupleOrParens(ts: List[Tree])(implicit ctx: Context) = ts match {
    case t :: Nil => Parens(t)
    case _ => Tuple(ts)
  }

  def makeTuple(ts: List[Tree])(implicit ctx: Context) = ts match {
    case t :: Nil => t
    case _ => Tuple(ts)
  }

  def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = EmptyModifiers)(implicit ctx: Context): ValDef =
    ValDef(pname, tpe, EmptyTree).withMods(mods | Param)

  def makeSyntheticParameter(n: Int = 1, tpt: Tree = TypeTree())(implicit ctx: Context): ValDef =
    ValDef(nme.syntheticParamName(n), tpt, EmptyTree).withFlags(SyntheticTermParam)

  /** A reference to given definition. If definition is a repeated
   *  parameter, the reference will be a repeated argument.
   */
  def refOfDef(tree: MemberDef)(implicit ctx: Context) = tree match {
    case ValDef(_, PostfixOp(_, nme.raw.STAR), _) => repeated(Ident(tree.name))
    case _ => Ident(tree.name)
  }

  /** A repeated argument such as `arg: _*` */
  def repeated(arg: Tree)(implicit ctx: Context) = Typed(arg, Ident(tpnme.WILDCARD_STAR))

// ----- Accessing modifiers ----------------------------------------------------

  abstract class ModsDecorator { def mods: Modifiers }

  implicit class modsDeco(val mdef: MemberDef)(implicit ctx: Context) {
    def mods = mdef.rawMods
  }

// --------- Copier/Transformer/Accumulator classes for untyped trees -----

  override val cpy: UntypedTreeCopier = new UntypedTreeCopier

  class UntypedTreeCopier extends TreeCopier {

    def postProcess(tree: Tree, copied: Tree): copied.ThisTree[Untyped] =
      copied.asInstanceOf[copied.ThisTree[Untyped]]

    def postProcess(tree: Tree, copied: MemberDef): copied.ThisTree[Untyped] = {
      tree match {
        case tree: MemberDef => copied.withMods(tree.rawMods)
        case _ => copied
      }
    }.asInstanceOf[copied.ThisTree[Untyped]]

    def ModuleDef(tree: Tree)(name: TermName, impl: Template) = tree match {
      case tree: ModuleDef if (name eq tree.name) && (impl eq tree.impl) => tree
      case _ => untpd.ModuleDef(name, impl).withPos(tree.pos)
    }
    def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree) = tree match {
      case tree: ParsedTry
        if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree
      case _ => untpd.ParsedTry(expr, handler, finalizer).withPos(tree.pos)
    }
    def PolyTypeDef(tree: Tree)(name: TypeName, tparams: List[TypeDef], rhs: Tree) = tree match {
      case tree: PolyTypeDef if (name eq tree.name) && (tparams eq tree.tparams) && (rhs eq tree.rhs) => tree
      case _ => new PolyTypeDef(name, tparams, rhs).withPos(tree.pos)
    }
    def SymbolLit(tree: Tree)(str: String) = tree match {
      case tree: SymbolLit if str == tree.str => tree
      case _ => untpd.SymbolLit(str).withPos(tree.pos)
    }
    def InterpolatedString(tree: Tree)(id: TermName, segments: List[Tree]) = tree match {
      case tree: InterpolatedString if (id eq tree.id) && (segments eq tree.segments) => tree
      case _ => untpd.InterpolatedString(id, segments).withPos(tree.pos)
    }
    def Function(tree: Tree)(args: List[Tree], body: Tree) = tree match {
      case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
      case _ => untpd.Function(args, body).withPos(tree.pos)
    }
    def InfixOp(tree: Tree)(left: Tree, op: Name, right: Tree) = tree match {
      case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree
      case _ => untpd.InfixOp(left, op, right).withPos(tree.pos)
    }
    def PostfixOp(tree: Tree)(od: Tree, op: Name) = tree match {
      case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree
      case _ => untpd.PostfixOp(od, op).withPos(tree.pos)
    }
    def PrefixOp(tree: Tree)(op: Name, od: Tree) = tree match {
      case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree
      case _ => untpd.PrefixOp(op, od).withPos(tree.pos)
    }
    def Parens(tree: Tree)(t: Tree) = tree match {
      case tree: Parens if t eq tree.t => tree
      case _ => untpd.Parens(t).withPos(tree.pos)
    }
    def Tuple(tree: Tree)(trees: List[Tree]) = tree match {
      case tree: Tuple if trees eq tree.trees => tree
      case _ => untpd.Tuple(trees).withPos(tree.pos)
    }
    def Throw(tree: Tree)(expr: Tree) = tree match {
      case tree: Throw if expr eq tree.expr => tree
      case _ => untpd.Throw(expr).withPos(tree.pos)
    }
    def WhileDo(tree: Tree)(cond: Tree, body: Tree) = tree match {
      case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree
      case _ => untpd.WhileDo(cond, body).withPos(tree.pos)
    }
    def DoWhile(tree: Tree)(body: Tree, cond: Tree) = tree match {
      case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree
      case _ => untpd.DoWhile(body, cond).withPos(tree.pos)
    }
    def ForYield(tree: Tree)(enums: List[Tree], expr: Tree) = tree match {
      case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree
      case _ => untpd.ForYield(enums, expr).withPos(tree.pos)
    }
    def ForDo(tree: Tree)(enums: List[Tree], body: Tree) = tree match {
      case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree
      case _ => untpd.ForDo(enums, body).withPos(tree.pos)
    }
    def GenFrom(tree: Tree)(pat: Tree, expr: Tree) = tree match {
      case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree
      case _ => untpd.GenFrom(pat, expr).withPos(tree.pos)
    }
    def GenAlias(tree: Tree)(pat: Tree, expr: Tree) = tree match {
      case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree
      case _ => untpd.GenAlias(pat, expr).withPos(tree.pos)
    }
    def ContextBounds(tree: Tree)(bounds: TypeBoundsTree, cxBounds: List[Tree]) = tree match {
      case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree
      case _ => untpd.ContextBounds(bounds, cxBounds).withPos(tree.pos)
    }
    def PatDef(tree: Tree)(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) = tree match {
      case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
      case _ => untpd.PatDef(mods, pats, tpt, rhs).withPos(tree.pos)
    }
  }

  abstract class UntypedTreeMap(cpy: UntypedTreeCopier = untpd.cpy) extends TreeMap(cpy) {
    override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
      case ModuleDef(name, impl) =>
        cpy.ModuleDef(tree)(name, transformSub(impl))
      case ParsedTry(expr, handler, finalizer) =>
        cpy.ParsedTry(tree)(transform(expr), transform(handler), transform(finalizer))
      case SymbolLit(str) =>
        cpy.SymbolLit(tree)(str)
      case InterpolatedString(id, segments) =>
        cpy.InterpolatedString(tree)(id, transform(segments))
      case Function(args, body) =>
        cpy.Function(tree)(transform(args), transform(body))
      case InfixOp(left, op, right) =>
        cpy.InfixOp(tree)(transform(left), op, transform(right))
      case PostfixOp(od, op) =>
        cpy.PostfixOp(tree)(transform(od), op)
      case PrefixOp(op, od) =>
        cpy.PrefixOp(tree)(op, transform(od))
      case Parens(t) =>
        cpy.Parens(tree)(transform(t))
      case Tuple(trees) =>
        cpy.Tuple(tree)(transform(trees))
      case Throw(expr) =>
        cpy.Throw(tree)(transform(expr))
      case WhileDo(cond, body) =>
        cpy.WhileDo(tree)(transform(cond), transform(body))
      case DoWhile(body, cond) =>
        cpy.DoWhile(tree)(transform(body), transform(cond))
      case ForYield(enums, expr) =>
        cpy.ForYield(tree)(transform(enums), transform(expr))
      case ForDo(enums, body) =>
        cpy.ForDo(tree)(transform(enums), transform(body))
      case GenFrom(pat, expr) =>
        cpy.GenFrom(tree)(transform(pat), transform(expr))
      case GenAlias(pat, expr) =>
        cpy.GenAlias(tree)(transform(pat), transform(expr))
      case ContextBounds(bounds, cxBounds) =>
        cpy.ContextBounds(tree)(transformSub(bounds), transform(cxBounds))
      case PatDef(mods, pats, tpt, rhs) =>
        cpy.PatDef(tree)(mods, transform(pats), transform(tpt), transform(rhs))
      case tree: PolyTypeDef =>
        cpy.PolyTypeDef(tree)(tree.name, transformSub(tree.tparams), transform(tree.rhs))
      case _ =>
        super.transform(tree)
    }
  }

  abstract class UntypedTreeAccumulator[X] extends TreeAccumulator[X] {
    override def foldOver(x: X, tree: Tree)(implicit ctx: Context): X = tree match {
      case ModuleDef(name, impl) =>
        this(x, impl)
      case ParsedTry(expr, handler, finalizer) =>
        this(this(this(x, expr), handler), finalizer)
      case SymbolLit(str) =>
        x
      case InterpolatedString(id, segments) =>
        this(x, segments)
      case Function(args, body) =>
        this(this(x, args), body)
      case InfixOp(left, op, right) =>
        this(this(x, left), right)
      case PostfixOp(od, op) =>
        this(x, od)
      case PrefixOp(op, od) =>
        this(x, od)
      case Parens(t) =>
        this(x, t)
      case Tuple(trees) =>
        this(x, trees)
      case Throw(expr) =>
        this(x, expr)
      case WhileDo(cond, body) =>
        this(this(x, cond), body)
      case DoWhile(body, cond) =>
        this(this(x, body), cond)
      case ForYield(enums, expr) =>
        this(this(x, enums), expr)
      case ForDo(enums, body) =>
        this(this(x, enums), body)
      case GenFrom(pat, expr) =>
        this(this(x, pat), expr)
      case GenAlias(pat, expr) =>
        this(this(x, pat), expr)
      case ContextBounds(bounds, cxBounds) =>
        this(this(x, bounds), cxBounds)
      case PatDef(mods, pats, tpt, rhs) =>
        this(this(this(x, pats), tpt), rhs)
      case tree: PolyTypeDef =>
        this(this(x, tree.tparams), tree.rhs)
      case TypedSplice(tree) =>
        this(x, tree)
      case _ =>
        super.foldOver(x, tree)
    }
  }

  /** Fold `f` over all tree nodes, in depth-first, prefix order */
  class UntypedDeepFolder[X](f: (X, Tree) => X) extends UntypedTreeAccumulator[X] {
    def apply(x: X, tree: Tree)(implicit ctx: Context): X = foldOver(f(x, tree), tree)
  }

  override def rename(tree: NameTree, newName: Name)(implicit ctx: Context): tree.ThisTree[Untyped] = tree match {
    case t: PolyTypeDef =>
      cpy.PolyTypeDef(t)(newName.asTypeName, t.tparams, t.rhs).asInstanceOf[tree.ThisTree[Untyped]]
    case _ => super.rename(tree, newName)
  }
}