package scala package reflect package internal import Flags._ import util._ trait ReificationSupport { self: SymbolTable => import definitions._ class ReificationSupportImpl extends ReificationSupportApi { def selectType(owner: Symbol, name: String): TypeSymbol = select(owner, newTypeName(name)).asType def selectTerm(owner: Symbol, name: String): TermSymbol = { val result = select(owner, newTermName(name)).asTerm if (result.isOverloaded) result.suchThat(!_.isMethod).asTerm else result } protected def select(owner: Symbol, name: Name): Symbol = { val result = owner.info decl name if (result ne NoSymbol) result else mirrorThatLoaded(owner).missingHook(owner, name) orElse { throw new ScalaReflectionException("%s %s in %s not found".format(if (name.isTermName) "term" else "type", name, owner.fullName)) } } def selectOverloadedMethod(owner: Symbol, name: String, index: Int): MethodSymbol = { val result = owner.info.decl(newTermName(name)).alternatives(index) if (result ne NoSymbol) result.asMethod else throw new ScalaReflectionException("overloaded method %s #%d in %s not found".format(name, index, owner.fullName)) } def newFreeTerm(name: String, value: => Any, flags: Long = 0L, origin: String = null): FreeTermSymbol = newFreeTermSymbol(newTermName(name), value, flags, origin).markFlagsCompleted(mask = AllFlags) def newFreeType(name: String, flags: Long = 0L, origin: String = null): FreeTypeSymbol = newFreeTypeSymbol(newTypeName(name), flags, origin).markFlagsCompleted(mask = AllFlags) def newNestedSymbol(owner: Symbol, name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol = owner.newNestedSymbol(name, pos, flags, isClass).markFlagsCompleted(mask = AllFlags) def newScopeWith(elems: Symbol*): Scope = self.newScopeWith(elems: _*) def setAnnotations[S <: Symbol](sym: S, annots: List[AnnotationInfo]): S = sym.setAnnotations(annots) def setInfo[S <: Symbol](sym: S, tpe: Type): S = sym.setInfo(tpe).markAllCompleted() def mkThis(sym: Symbol): Tree = self.This(sym) def mkSelect(qualifier: Tree, sym: Symbol): Select = self.Select(qualifier, sym) def mkIdent(sym: Symbol): Ident = self.Ident(sym) def mkTypeTree(tp: Type): TypeTree = self.TypeTree(tp) def ThisType(sym: Symbol): Type = self.ThisType(sym) def SingleType(pre: Type, sym: Symbol): Type = self.SingleType(pre, sym) def SuperType(thistpe: Type, supertpe: Type): Type = self.SuperType(thistpe, supertpe) def ConstantType(value: Constant): ConstantType = self.ConstantType(value) def TypeRef(pre: Type, sym: Symbol, args: List[Type]): Type = self.TypeRef(pre, sym, args) def RefinedType(parents: List[Type], decls: Scope, typeSymbol: Symbol): RefinedType = self.RefinedType(parents, decls, typeSymbol) def ClassInfoType(parents: List[Type], decls: Scope, typeSymbol: Symbol): ClassInfoType = self.ClassInfoType(parents, decls, typeSymbol) def MethodType(params: List[Symbol], resultType: Type): MethodType = self.MethodType(params, resultType) def NullaryMethodType(resultType: Type): NullaryMethodType = self.NullaryMethodType(resultType) def PolyType(typeParams: List[Symbol], resultType: Type): PolyType = self.PolyType(typeParams, resultType) def ExistentialType(quantified: List[Symbol], underlying: Type): ExistentialType = self.ExistentialType(quantified, underlying) def AnnotatedType(annotations: List[Annotation], underlying: Type): AnnotatedType = self.AnnotatedType(annotations, underlying) def TypeBounds(lo: Type, hi: Type): TypeBounds = self.TypeBounds(lo, hi) def BoundedWildcardType(bounds: TypeBounds): BoundedWildcardType = self.BoundedWildcardType(bounds) def thisPrefix(sym: Symbol): Type = sym.thisPrefix def setType[T <: Tree](tree: T, tpe: Type): T = { tree.setType(tpe); tree } def setSymbol[T <: Tree](tree: T, sym: Symbol): T = { tree.setSymbol(sym); tree } def toStats(tree: Tree): List[Tree] = tree match { case EmptyTree => Nil case SyntacticBlock(stats) => stats case defn if defn.isDef => defn :: Nil case imp: Import => imp :: Nil case _ => throw new IllegalArgumentException(s"can't flatten $tree") } def mkAnnotation(tree: Tree): Tree = tree match { case SyntacticNew(Nil, SyntacticApplied(SyntacticAppliedType(_, _), _) :: Nil, noSelfType, Nil) => tree case _ => throw new IllegalArgumentException(s"Tree ${showRaw(tree)} isn't a correct representation of annotation." + """Consider reformatting it into a q"new $name[..$targs](...$argss)" shape""") } def mkAnnotation(trees: List[Tree]): List[Tree] = trees.map(mkAnnotation) def mkParam(argss: List[List[Tree]], extraFlags: FlagSet = NoFlags, excludeFlags: FlagSet = DEFERRED): List[List[ValDef]] = argss.map { args => args.map { mkParam(_, extraFlags, excludeFlags) } } def mkParam(tree: Tree, extraFlags: FlagSet, excludeFlags: FlagSet): ValDef = tree match { case Typed(Ident(name: TermName), tpt) => mkParam(ValDef(NoMods, name, tpt, EmptyTree), extraFlags, excludeFlags) case vd: ValDef => var newmods = vd.mods & (~excludeFlags) if (vd.rhs.nonEmpty) newmods |= DEFAULTPARAM copyValDef(vd)(mods = newmods | extraFlags) case _ => throw new IllegalArgumentException(s"$tree is not valid representation of a parameter, " + """consider reformatting it into q"val $name: $T = $default" shape""") } def mkImplicitParam(args: List[Tree]): List[ValDef] = args.map(mkImplicitParam) def mkImplicitParam(tree: Tree): ValDef = mkParam(tree, IMPLICIT | PARAM, NoFlags) def mkTparams(tparams: List[Tree]): List[TypeDef] = tparams.map { case td: TypeDef => copyTypeDef(td)(mods = (td.mods | PARAM) & (~DEFERRED)) case other => throw new IllegalArgumentException(s"can't splice $other as type parameter") } def mkRefineStat(stat: Tree): Tree = { stat match { case dd: DefDef => require(dd.rhs.isEmpty, "can't use DefDef with non-empty body as refine stat") case vd: ValDef => require(vd.rhs.isEmpty, "can't use ValDef with non-empty rhs as refine stat") case td: TypeDef => case _ => throw new IllegalArgumentException(s"not legal refine stat: $stat") } stat } def mkRefineStat(stats: List[Tree]): List[Tree] = stats.map(mkRefineStat) def mkPackageStat(stat: Tree): Tree = { stat match { case cd: ClassDef => case md: ModuleDef => case pd: PackageDef => case _ => throw new IllegalArgumentException(s"not legal package stat: $stat") } stat } def mkPackageStat(stats: List[Tree]): List[Tree] = stats.map(mkPackageStat) object ScalaDot extends ScalaDotExtractor { def apply(name: Name): Tree = gen.scalaDot(name) def unapply(tree: Tree): Option[Name] = tree match { case Select(id @ Ident(nme.scala_), name) if id.symbol == ScalaPackage => Some(name) case _ => None } } def mkEarlyDef(defn: Tree): Tree = defn match { case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred => copyValDef(vdef)(mods = mods | PRESUPER) case tdef @ TypeDef(mods, _, _, _) => copyTypeDef(tdef)(mods = mods | PRESUPER) case _ => throw new IllegalArgumentException(s"not legal early def: $defn") } def mkEarlyDef(defns: List[Tree]): List[Tree] = defns.map(mkEarlyDef) def mkRefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym def freshTermName(prefix: String = nme.FRESH_TERM_NAME_PREFIX): TermName = self.freshTermName(prefix) def freshTypeName(prefix: String): TypeName = self.freshTypeName(prefix) protected implicit def fresh: FreshNameCreator = self.currentFreshNameCreator object ImplicitParams extends ImplicitParamsExtractor { def apply(paramss: List[List[Tree]], implparams: List[Tree]): List[List[Tree]] = if (implparams.nonEmpty) paramss :+ mkImplicitParam(implparams) else paramss def unapply(vparamss: List[List[ValDef]]): Some[(List[List[ValDef]], List[ValDef])] = vparamss match { case init :+ (last @ (initlast :: _)) if initlast.mods.isImplicit => Some((init, last)) case _ => Some((vparamss, Nil)) } } object FlagsRepr extends FlagsReprExtractor { def apply(bits: Long): FlagSet = bits def unapply(flags: Long): Some[Long] = Some(flags) } /** Construct/deconstruct type application term trees. * Treats other term trees as zero-argument type applications. */ object SyntacticTypeApplied extends SyntacticTypeAppliedExtractor { def apply(tree: Tree, targs: List[Tree]): Tree = if (targs.isEmpty) tree else if (tree.isTerm) TypeApply(tree, targs) else throw new IllegalArgumentException(s"can't apply type arguments to $tree") def unapply(tree: Tree): Option[(Tree, List[Tree])] = tree match { case TypeApply(fun, targs) => Some((fun, targs)) case _ if tree.isTerm => Some((tree, Nil)) case _ => None } } /** Construct/deconstruct applied type trees. * Treats other types as zero-arity applied types. */ object SyntacticAppliedType extends SyntacticTypeAppliedExtractor { def apply(tree: Tree, targs: List[Tree]): Tree = if (targs.isEmpty) tree else if (tree.isType) AppliedTypeTree(tree, targs) else throw new IllegalArgumentException(s"can't create applied type from non-type $tree") def unapply(tree: Tree): Option[(Tree, List[Tree])] = tree match { case MaybeTypeTreeOriginal(AppliedTypeTree(tpe, targs)) => Some((tpe, targs)) case _ if tree.isType => Some((tree, Nil)) case _ => None } } object SyntacticApplied extends SyntacticAppliedExtractor { def apply(tree: Tree, argss: List[List[Tree]]): Tree = argss.foldLeft(tree) { (f, args) => Apply(f, args.map(treeInfo.assignmentToMaybeNamedArg)) } def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = tree match { case UnApply(treeInfo.Unapplied(Select(fun, nme.unapply)), pats) => Some((fun, pats :: Nil)) case treeInfo.Applied(fun, targs, argss) => fun match { case Select(_: New, nme.CONSTRUCTOR) => Some((tree, Nil)) case _ => val callee = if (fun.isTerm) SyntacticTypeApplied(fun, targs) else SyntacticAppliedType(fun, targs) Some((callee, argss)) } } } // recover constructor contents generated by gen.mkTemplate protected object UnCtor { def unapply(tree: Tree): Option[(Modifiers, List[List[ValDef]], List[Tree])] = tree match { case DefDef(mods, nme.MIXIN_CONSTRUCTOR, _, _, _, SyntacticBlock(lvdefs :+ _)) => Some((mods | Flag.TRAIT, Nil, lvdefs)) case DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, _, SyntacticBlock(lvdefs :+ _ :+ _)) => Some((mods, vparamss, lvdefs)) case _ => None } } // undo gen.mkTemplate protected class UnMkTemplate(isCaseClass: Boolean) { def unapply(templ: Template): Option[(List[Tree], ValDef, Modifiers, List[List[ValDef]], List[Tree], List[Tree])] = { val Template(parents, selfType, _) = templ val tbody = treeInfo.untypecheckedTemplBody(templ) def result(ctorMods: Modifiers, vparamss: List[List[ValDef]], edefs: List[Tree], body: List[Tree]) = Some((parents, selfType, ctorMods, vparamss, edefs, body)) def indexOfCtor(trees: List[Tree]) = trees.indexWhere { case UnCtor(_, _, _) => true ; case _ => false } if (tbody forall treeInfo.isInterfaceMember) result(NoMods | Flag.TRAIT, Nil, Nil, tbody) else if (indexOfCtor(tbody) == -1) None else { val (rawEdefs, rest) = tbody.span(treeInfo.isEarlyDef) val (gvdefs, etdefs) = rawEdefs.partition(treeInfo.isEarlyValDef) val (fieldDefs, UnCtor(ctorMods, ctorVparamss, lvdefs) :: body) = rest.splitAt(indexOfCtor(rest)) val evdefs = gvdefs.zip(lvdefs).map { // TODO: in traits, early val defs are defdefs case (gvdef @ ValDef(_, _, tpt: TypeTree, _), ValDef(_, _, _, rhs)) => copyValDef(gvdef)(tpt = tpt.original, rhs = rhs) case (tr1, tr2) => throw new MatchError((tr1, tr2)) } val edefs = evdefs ::: etdefs if (ctorMods.isTrait) result(ctorMods, Nil, edefs, body) else { // undo conversion from (implicit ... ) to ()(implicit ... ) when it's the only parameter section // except that case classes require the explicit leading empty parameter list val vparamssRestoredImplicits = ctorVparamss match { case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit && !isCaseClass => tail case other => other } // undo flag modifications by merging flag info from constructor args and fieldDefs val modsMap = fieldDefs.map { case ValDef(mods, name, _, _) => name -> mods }.toMap def ctorArgsCorrespondToFields = vparamssRestoredImplicits.flatten.forall { vd => modsMap.contains(vd.name) } if (!ctorArgsCorrespondToFields) None else { val vparamss = mmap(vparamssRestoredImplicits) { vd => val originalMods = modsMap(vd.name) | (vd.mods.flags & DEFAULTPARAM) atPos(vd.pos)(ValDef(originalMods, vd.name, vd.tpt, vd.rhs)) } result(ctorMods, vparamss, edefs, body) } } } } def asCase = new UnMkTemplate(isCaseClass = true) } protected object UnMkTemplate extends UnMkTemplate(isCaseClass = false) protected def mkSelfType(tree: Tree) = tree match { case vd: ValDef => require(vd.rhs.isEmpty, "self types must have empty right hand side") copyValDef(vd)(mods = (vd.mods | PRIVATE) & (~DEFERRED)) case _ => throw new IllegalArgumentException(s"$tree is not a valid representation of self type, " + """consider reformatting into q"val $self: $T" shape""") } object SyntacticClassDef extends SyntacticClassDefExtractor { def apply(mods: Modifiers, name: TypeName, tparams: List[Tree], constrMods: Modifiers, vparamss: List[List[Tree]], earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = { val extraFlags = PARAMACCESSOR | (if (mods.isCase) CASEACCESSOR else 0L) val vparamss0 = mkParam(vparamss, extraFlags, excludeFlags = DEFERRED | PARAM) val tparams0 = mkTparams(tparams) val parents0 = gen.mkParents(mods, if (mods.isCase) parents.filter { case ScalaDot(tpnme.Product | tpnme.Serializable | tpnme.AnyRef) => false case _ => true } else parents ) val body0 = earlyDefs ::: body val selfType0 = mkSelfType(selfType) val templ = gen.mkTemplate(parents0, selfType0, constrMods, vparamss0, body0) gen.mkClassDef(mods, name, tparams0, templ) } def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers, List[List[ValDef]], List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case ClassDef(mods, name, tparams, impl) => val X = if (mods.isCase) UnMkTemplate.asCase else UnMkTemplate impl match { case X(parents, selfType, ctorMods, vparamss, earlyDefs, body) if (!ctorMods.isTrait && !ctorMods.hasFlag(JAVA)) => Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfType, body)) case _ => None } case _ => None } } object SyntacticTraitDef extends SyntacticTraitDefExtractor { def apply(mods: Modifiers, name: TypeName, tparams: List[Tree], earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = { val mods0 = mods | TRAIT | ABSTRACT val templ = gen.mkTemplate(parents, mkSelfType(selfType), Modifiers(TRAIT), Nil, earlyDefs ::: body) gen.mkClassDef(mods0, name, mkTparams(tparams), templ) } def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case ClassDef(mods, name, tparams, UnMkTemplate(parents, selfType, ctorMods, vparamss, earlyDefs, body)) if mods.isTrait => Some((mods, name, tparams, earlyDefs, parents, selfType, body)) case _ => None } } object SyntacticObjectDef extends SyntacticObjectDefExtractor { def apply(mods: Modifiers, name: TermName, earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ModuleDef = ModuleDef(mods, name, gen.mkTemplate(parents, mkSelfType(selfType), NoMods, Nil, earlyDefs ::: body)) def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case ModuleDef(mods, name, UnMkTemplate(parents, selfType, _, _, earlyDefs, body)) => Some((mods, name, earlyDefs, parents, selfType, body)) case _ => None } } object SyntacticPackageObjectDef extends SyntacticPackageObjectDefExtractor { def apply(name: TermName, earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): PackageDef = gen.mkPackageObject(SyntacticObjectDef(NoMods, name, earlyDefs, parents, selfType, body)) def unapply(tree: Tree): Option[(TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case PackageDef(Ident(name: TermName), List(SyntacticObjectDef(NoMods, nme.PACKAGEkw, earlyDefs, parents, selfType, body))) => Some((name, earlyDefs, parents, selfType, body)) case _ => None } } // match references to `scala.$name` protected class ScalaMemberRef(symbols: Seq[Symbol]) { def result(name: Name): Option[Symbol] = symbols.collect { case sym if sym.name == name => sym }.headOption def unapply(tree: Tree): Option[Symbol] = tree match { case id @ Ident(name) if symbols.contains(id.symbol) && name == id.symbol.name => Some(id.symbol) case Select(scalapkg @ Ident(nme.scala_), name) if scalapkg.symbol == ScalaPackage => result(name) case Select(Select(Ident(nme.ROOTPKG), nme.scala_), name) => result(name) case _ => None } } protected object TupleClassRef extends ScalaMemberRef(TupleClass.seq) protected object TupleCompanionRef extends ScalaMemberRef(TupleClass.seq.map { _.companionModule }) protected object UnitClassRef extends ScalaMemberRef(Seq(UnitClass)) protected object FunctionClassRef extends ScalaMemberRef(FunctionClass.seq) object SyntacticTuple extends SyntacticTupleExtractor { def apply(args: List[Tree]): Tree = { require(args.isEmpty || TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported") gen.mkTuple(args) } def unapply(tree: Tree): Option[List[Tree]] = tree match { case Literal(Constant(())) => Some(Nil) case Apply(MaybeTypeTreeOriginal(SyntacticTypeApplied(MaybeSelectApply(TupleCompanionRef(sym)), targs)), args) if sym == TupleClass(args.length).companionModule && (targs.isEmpty || targs.length == args.length) => Some(args) case _ if tree.isTerm => Some(tree :: Nil) case _ => None } } object SyntacticTupleType extends SyntacticTupleExtractor { def apply(args: List[Tree]): Tree = { require(args.isEmpty || TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported") gen.mkTupleType(args) } def unapply(tree: Tree): Option[List[Tree]] = tree match { case MaybeTypeTreeOriginal(UnitClassRef(_)) => Some(Nil) case MaybeTypeTreeOriginal(AppliedTypeTree(TupleClassRef(sym), args)) if sym == TupleClass(args.length) => Some(args) case _ if tree.isType => Some(tree :: Nil) case _ => None } } object SyntacticFunctionType extends SyntacticFunctionTypeExtractor { def apply(argtpes: List[Tree], restpe: Tree): Tree = { require(FunctionClass(argtpes.length).exists, s"Function types with ${argtpes.length} arity aren't supported") gen.mkFunctionTypeTree(argtpes, restpe) } def unapply(tree: Tree): Option[(List[Tree], Tree)] = tree match { case MaybeTypeTreeOriginal(AppliedTypeTree(FunctionClassRef(sym), args @ (argtpes :+ restpe))) if sym == FunctionClass(args.length - 1) => Some((argtpes, restpe)) case _ => None } } object SyntheticUnit { def unapply(tree: Tree): Boolean = tree match { case Literal(Constant(())) if tree.hasAttachment[SyntheticUnitAttachment.type] => true case _ => false } } /** Syntactic combinator that abstracts over Block tree. * * Apart from providing a more straightforward api that exposes * block as a list of elements rather than (stats, expr) pair * it also: * * 1. Strips trailing synthetic units which are inserted by the * compiler if the block ends with a definition rather * than an expression or is empty. * * 2. Matches non-block term trees and recognizes them as * single-element blocks for sake of consistency with * compiler's default to treat single-element blocks with * expressions as just expressions. The only exception is q"" * which is not considered to be a block. */ object SyntacticBlock extends SyntacticBlockExtractor { def apply(stats: List[Tree]): Tree = gen.mkBlock(stats) def unapply(tree: Tree): Option[List[Tree]] = tree match { case bl @ self.Block(stats, SyntheticUnit()) => Some(treeInfo.untypecheckedBlockBody(bl)) case bl @ self.Block(stats, expr) => Some(treeInfo.untypecheckedBlockBody(bl) :+ expr) case SyntheticUnit() => Some(Nil) case _ if tree.isTerm && tree.nonEmpty => Some(tree :: Nil) case _ => None } } object SyntacticFunction extends SyntacticFunctionExtractor { def apply(params: List[Tree], body: Tree): Function = { val params0 :: Nil = mkParam(params :: Nil, PARAM) require(params0.forall { _.rhs.isEmpty }, "anonymous functions don't support parameters with default values") Function(params0, body) } def unapply(tree: Function): Option[(List[ValDef], Tree)] = Function.unapply(tree) } object SyntacticNew extends SyntacticNewExtractor { def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): Tree = gen.mkNew(parents, mkSelfType(selfType), earlyDefs ::: body, NoPosition, NoPosition) def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case treeInfo.Applied(Select(New(SyntacticAppliedType(ident, targs)), nme.CONSTRUCTOR), Nil, List(Nil)) => Some((Nil, SyntacticAppliedType(ident, targs) :: Nil, noSelfType, Nil)) case treeInfo.Applied(Select(New(SyntacticAppliedType(ident, targs)), nme.CONSTRUCTOR), Nil, argss) => Some((Nil, SyntacticApplied(SyntacticAppliedType(ident, targs), argss) :: Nil, noSelfType, Nil)) case SyntacticBlock(SyntacticClassDef(_, tpnme.ANON_CLASS_NAME, Nil, _, ListOfNil, earlyDefs, parents, selfType, body) :: Apply(Select(New(Ident(tpnme.ANON_CLASS_NAME)), nme.CONSTRUCTOR), Nil) :: Nil) => Some((earlyDefs, parents, selfType, body)) case _ => None } } object SyntacticDefDef extends SyntacticDefDefExtractor { def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef = { val tparams0 = mkTparams(tparams) val vparamss0 = mkParam(vparamss, PARAM) val rhs0 = { if (name != nme.CONSTRUCTOR) rhs else rhs match { case Block(_, _) => rhs case _ => Block(List(rhs), gen.mkSyntheticUnit) } } DefDef(mods, name, tparams0, vparamss0, tpt, rhs0) } def unapply(tree: Tree): Option[(Modifiers, TermName, List[TypeDef], List[List[ValDef]], Tree, Tree)] = tree match { case DefDef(mods, nme.CONSTRUCTOR, tparams, vparamss, tpt, Block(List(expr), Literal(Constant(())))) => Some((mods, nme.CONSTRUCTOR, tparams, vparamss, tpt, expr)) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => Some((mods, name, tparams, vparamss, tpt, rhs)) case _ => None } } protected class SyntacticValDefBase(isMutable: Boolean) extends SyntacticValDefExtractor { def modifiers(mods: Modifiers): Modifiers = if (isMutable) mods | MUTABLE else mods def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef = ValDef(modifiers(mods), name, tpt, rhs) def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)] = tree match { case ValDef(mods, name, tpt, rhs) if mods.hasFlag(MUTABLE) == isMutable => Some((mods, name, tpt, rhs)) case _ => None } } object SyntacticValDef extends SyntacticValDefBase(isMutable = false) object SyntacticVarDef extends SyntacticValDefBase(isMutable = true) object SyntacticAssign extends SyntacticAssignExtractor { def apply(lhs: Tree, rhs: Tree): Tree = gen.mkAssign(lhs, rhs) def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { case Assign(lhs, rhs) => Some((lhs, rhs)) case AssignOrNamedArg(lhs, rhs) => Some((lhs, rhs)) case Apply(Select(fn, nme.update), args :+ rhs) => Some((atPos(fn.pos)(Apply(fn, args)), rhs)) case _ => None } } def UnliftListElementwise[T](unliftable: Unliftable[T]) = new UnliftListElementwise[T] { def unapply(lst: List[Tree]): Option[List[T]] = { val unlifted = lst.flatMap { unliftable.unapply(_) } if (unlifted.length == lst.length) Some(unlifted) else None } } def UnliftListOfListsElementwise[T](unliftable: Unliftable[T]) = new UnliftListOfListsElementwise[T] { def unapply(lst: List[List[Tree]]): Option[List[List[T]]] = { val unlifted = lst.map { l => l.flatMap { unliftable.unapply(_) } } if (unlifted.flatten.length == lst.flatten.length) Some(unlifted) else None } } object SyntacticValFrom extends SyntacticValFromExtractor { def apply(pat: Tree, rhs: Tree): Tree = gen.ValFrom(pat, gen.mkCheckIfRefutable(pat, rhs)) def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { case gen.ValFrom(pat, UnCheckIfRefutable(pat1, rhs1)) if pat.equalsStructure(pat1) => Some((pat, rhs1)) case gen.ValFrom(pat, rhs) => Some((pat, rhs)) case _ => None } } object SyntacticValEq extends SyntacticValEqExtractor { def apply(pat: Tree, rhs: Tree): Tree = gen.ValEq(pat, rhs) def unapply(tree: Tree): Option[(Tree, Tree)] = gen.ValEq.unapply(tree) } object SyntacticFilter extends SyntacticFilterExtractor { def apply(tree: Tree): Tree = gen.Filter(tree) def unapply(tree: Tree): Option[Tree] = gen.Filter.unapply(tree) } // If a tree in type position isn't provided by the user (e.g. `tpt` fields of // `ValDef` and `DefDef`, function params etc), then it's going to be parsed as // TypeTree with empty original and empty tpe. This extractor matches such trees // so that one can write q"val x = 2" to match typecheck(q"val x = 2"). Note that // TypeTree() is the only possible representation for empty trees in type positions. // We used to sometimes receive EmptyTree in such cases, but not anymore. object SyntacticEmptyTypeTree extends SyntacticEmptyTypeTreeExtractor { def apply(): TypeTree = self.TypeTree() def unapply(tt: TypeTree): Boolean = tt.original == null || tt.original.isEmpty } // match a sequence of desugared `val $pat = $value` protected object UnPatSeq { def unapply(trees: List[Tree]): Option[List[(Tree, Tree)]] = { val imploded = implodePatDefs(trees) val patvalues = imploded.flatMap { case SyntacticPatDef(_, pat, EmptyTree, rhs) => Some((pat, rhs)) case ValDef(_, name, SyntacticEmptyTypeTree(), rhs) => Some((Bind(name, self.Ident(nme.WILDCARD)), rhs)) case ValDef(_, name, tpt, rhs) => Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), rhs)) case _ => None } if (patvalues.length == imploded.length) Some(patvalues) else None } } // implode multiple-statement desugaring of pattern definitions // into single-statement valdefs with nme.QUASIQUOTE_PAT_DEF name object implodePatDefs extends Transformer { override def transform(tree: Tree) = tree match { case templ: Template => deriveTemplate(templ)(transformStats) case block: Block => val Block(init, last) = block Block(transformStats(init), transform(last)).copyAttrs(block) case ValDef(mods, name1, SyntacticEmptyTypeTree(), Match(MaybeTyped(MaybeUnchecked(value), tpt), CaseDef(pat, EmptyTree, Ident(name2)) :: Nil)) if name1 == name2 => ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value)) case _ => super.transform(tree) } def transformStats(trees: List[Tree]): List[Tree] = trees match { case Nil => Nil case ValDef(mods, _, SyntacticEmptyTypeTree(), Match(MaybeTyped(MaybeUnchecked(value), tpt), CaseDef(pat, EmptyTree, SyntacticTuple(ids)) :: Nil)) :: tail if mods.hasFlag(SYNTHETIC) && mods.hasFlag(ARTIFACT) => ids match { case Nil => ValDef(NoMods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value)) :: transformStats(tail) case _ => val mods = tail.take(1).head.asInstanceOf[ValDef].mods ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value)) :: transformStats(tail.drop(ids.length)) } case other :: tail => transform(other) :: transformStats(tail) } def apply(tree: Tree) = transform(tree) def apply(trees: List[Tree]) = transformStats(trees) } object SyntacticPatDef extends SyntacticPatDefExtractor { def apply(mods: Modifiers, pat: Tree, tpt: Tree, rhs: Tree): List[ValDef] = tpt match { case SyntacticEmptyTypeTree() => gen.mkPatDef(mods, pat, rhs) case _ => gen.mkPatDef(mods, Typed(pat, tpt), rhs) } def unapply(tree: Tree): Option[(Modifiers, Tree, Tree, Tree)] = tree match { case ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), rhs) => Some((mods, pat, tpt, rhs)) case _ => None } } // match a sequence of desugared `val $pat = $value` with a tuple in the end protected object UnPatSeqWithRes { def unapply(tree: Tree): Option[(List[(Tree, Tree)], List[Tree])] = tree match { case SyntacticBlock(UnPatSeq(trees) :+ SyntacticTuple(elems)) => Some((trees, elems)) case _ => None } } // undo gen.mkSyntheticParam protected object UnSyntheticParam { def unapply(tree: Tree): Option[TermName] = tree match { case ValDef(mods, name, _, EmptyTree) if mods.hasFlag(SYNTHETIC) && mods.hasFlag(PARAM) => Some(name) case _ => None } } // undo gen.mkVisitor protected object UnVisitor { def unapply(tree: Tree): Option[(TermName, List[CaseDef])] = tree match { case Function(UnSyntheticParam(x1) :: Nil, Match(MaybeUnchecked(Ident(x2)), cases)) if x1 == x2 => Some((x1, cases)) case _ => None } } // undo gen.mkFor:makeClosure protected object UnClosure { def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { case Function(ValDef(Modifiers(PARAM, _, _), name, tpt, EmptyTree) :: Nil, body) => tpt match { case SyntacticEmptyTypeTree() => Some((Bind(name, self.Ident(nme.WILDCARD)), body)) case _ => Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), body)) } case UnVisitor(_, CaseDef(pat, EmptyTree, body) :: Nil) => Some((pat, body)) case _ => None } } // match call to either withFilter or filter // TODO: now that we no longer rewrite `filter` to `withFilter`, maybe this extractor should only look for `withFilter`? protected object FilterCall { def unapply(tree: Tree): Option[(Tree,Tree)] = tree match { case Apply(Select(obj, nme.withFilter | nme.filter), arg :: Nil) => Some((obj, arg)) case _ => None } } // transform a chain of withFilter calls into a sequence of for filters protected object UnFilter { def unapply(tree: Tree): Some[(Tree, List[Tree])] = tree match { case UnCheckIfRefutable(_, _) => Some((tree, Nil)) case FilterCall(UnFilter(rhs, rest), UnClosure(_, test)) => Some((rhs, rest :+ SyntacticFilter(test))) case _ => Some((tree, Nil)) } } // undo gen.mkCheckIfRefutable protected object UnCheckIfRefutable { def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { case FilterCall(rhs, UnVisitor(name, CaseDef(pat, EmptyTree, Literal(Constant(true))) :: CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(false))) :: Nil)) if name.toString.contains(nme.CHECK_IF_REFUTABLE_STRING) => Some((pat, rhs)) case _ => None } } // undo gen.mkFor:makeCombination accounting for possible extra implicit argument protected class UnForCombination(name: TermName) { def unapply(tree: Tree) = tree match { case SyntacticApplied(SyntacticTypeApplied(sel @ Select(lhs, meth), _), (f :: Nil) :: Nil) if name == meth && sel.hasAttachment[ForAttachment.type] => Some((lhs, f)) case SyntacticApplied(SyntacticTypeApplied(sel @ Select(lhs, meth), _), (f :: Nil) :: _ :: Nil) if name == meth && sel.hasAttachment[ForAttachment.type] => Some((lhs, f)) case _ => None } } protected object UnMap extends UnForCombination(nme.map) protected object UnForeach extends UnForCombination(nme.foreach) protected object UnFlatMap extends UnForCombination(nme.flatMap) // undo desugaring done in gen.mkFor protected object UnFor { def unapply(tree: Tree): Option[(List[Tree], Tree)] = { val interm = tree match { case UnFlatMap(UnFilter(rhs, filters), UnClosure(pat, UnFor(rest, body))) => Some(((pat, rhs), filters ::: rest, body)) case UnForeach(UnFilter(rhs, filters), UnClosure(pat, UnFor(rest, body))) => Some(((pat, rhs), filters ::: rest, body)) case UnMap(UnFilter(rhs, filters), UnClosure(pat, cbody)) => Some(((pat, rhs), filters, gen.Yield(cbody))) case UnForeach(UnFilter(rhs, filters), UnClosure(pat, cbody)) => Some(((pat, rhs), filters, cbody)) case _ => None } interm.flatMap { case ((Bind(_, SyntacticTuple(_)) | SyntacticTuple(_), UnFor(SyntacticValFrom(pat, rhs) :: innerRest, gen.Yield(UnPatSeqWithRes(pats, elems2)))), outerRest, fbody) => val valeqs = pats.map { case (pat, rhs) => SyntacticValEq(pat, rhs) } Some((SyntacticValFrom(pat, rhs) :: innerRest ::: valeqs ::: outerRest, fbody)) case ((pat, rhs), filters, body) => Some((SyntacticValFrom(pat, rhs) :: filters, body)) } } } // check that enumerators are valid protected def mkEnumerators(enums: List[Tree]): List[Tree] = { require(enums.nonEmpty, "enumerators can't be empty") enums.head match { case SyntacticValFrom(_, _) => case t => throw new IllegalArgumentException(s"$t is not a valid first enumerator of for loop") } enums.tail.foreach { case SyntacticValEq(_, _) | SyntacticValFrom(_, _) | SyntacticFilter(_) => case t => throw new IllegalArgumentException(s"$t is not a valid representation of a for loop enumerator") } enums } object SyntacticFor extends SyntacticForExtractor { def apply(enums: List[Tree], body: Tree): Tree = gen.mkFor(mkEnumerators(enums), body) def unapply(tree: Tree) = tree match { case UnFor(enums, gen.Yield(body)) => None case UnFor(enums, body) => Some((enums, body)) case _ => None } } object SyntacticForYield extends SyntacticForExtractor { def apply(enums: List[Tree], body: Tree): Tree = gen.mkFor(mkEnumerators(enums), gen.Yield(body)) def unapply(tree: Tree) = tree match { case UnFor(enums, gen.Yield(body)) => Some((enums, body)) case _ => None } } // use typetree's original instead of typetree itself protected object MaybeTypeTreeOriginal { def unapply(tree: Tree): Some[Tree] = tree match { case tt: TypeTree => Some(tt.original) case _ => Some(tree) } } // drop potential extra call to .apply protected object MaybeSelectApply { def unapply(tree: Tree): Some[Tree] = tree match { case Select(f, nme.apply) => Some(f) case other => Some(other) } } // drop potential @scala.unchecked annotation protected object MaybeUnchecked { def unapply(tree: Tree): Some[Tree] = tree match { case Annotated(SyntacticNew(Nil, ScalaDot(tpnme.unchecked) :: Nil, noSelfType, Nil), annottee) => Some(annottee) case Typed(annottee, MaybeTypeTreeOriginal( Annotated(SyntacticNew(Nil, ScalaDot(tpnme.unchecked) :: Nil, noSelfType, Nil), _))) => Some(annottee) case annottee => Some(annottee) } } protected object MaybeTyped { def unapply(tree: Tree): Some[(Tree, Tree)] = tree match { case Typed(v, tpt) => Some((v, tpt)) case v => Some((v, SyntacticEmptyTypeTree())) } } protected def mkCases(cases: List[Tree]): List[CaseDef] = cases.map { case c: CaseDef => c case tree => throw new IllegalArgumentException(s"$tree is not valid representation of pattern match case") } object SyntacticPartialFunction extends SyntacticPartialFunctionExtractor { def apply(cases: List[Tree]): Match = Match(EmptyTree, mkCases(cases)) def unapply(tree: Tree): Option[List[CaseDef]] = tree match { case Match(EmptyTree, cases) => Some(cases) case Typed( Block( List(ClassDef(clsMods, tpnme.ANON_FUN_NAME, Nil, Template( List(abspf: TypeTree, ser: TypeTree), noSelfType, List( DefDef(_, nme.CONSTRUCTOR, _, _, _, _), DefDef(_, nme.applyOrElse, _, _, _, Match(_, cases :+ CaseDef(Bind(nme.DEFAULT_CASE, Ident(nme.WILDCARD)), _, _))), DefDef(_, nme.isDefinedAt, _, _, _, _))))), Apply(Select(New(Ident(tpnme.ANON_FUN_NAME)), termNames.CONSTRUCTOR), List())), pf: TypeTree) if pf.tpe != null && pf.tpe.typeSymbol.eq(PartialFunctionClass) && abspf.tpe != null && abspf.tpe.typeSymbol.eq(AbstractPartialFunctionClass) && ser.tpe != null && ser.tpe.typeSymbol.eq(SerializableClass) && clsMods.hasFlag(FINAL) && clsMods.hasFlag(SYNTHETIC) => Some(cases) case _ => None } } object SyntacticMatch extends SyntacticMatchExtractor { def apply(scrutinee: Tree, cases: List[Tree]) = { require(scrutinee.nonEmpty, "match's scrutinee may not be empty") Match(scrutinee, mkCases(cases)) } def unapply(tree: Match): Option[(Tree, List[CaseDef])] = tree match { case Match(scrutinee, cases) if scrutinee.nonEmpty => Some((scrutinee, cases)) case _ => None } } object SyntacticTry extends SyntacticTryExtractor { def apply(block: Tree, catches: List[Tree], finalizer: Tree) = Try(block, mkCases(catches), finalizer) def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] = Try.unapply(tree) } object SyntacticTermIdent extends SyntacticTermIdentExtractor { def apply(name: TermName, isBackquoted: Boolean): Ident = { val id = self.Ident(name) if (isBackquoted) id updateAttachment BackquotedIdentifierAttachment id } def unapply(id: Ident): Option[(TermName, Boolean)] = id.name match { case name: TermName => Some((name, id.hasAttachment[BackquotedIdentifierAttachment.type])) case _ => None } } object SyntacticTypeIdent extends SyntacticTypeIdentExtractor { def apply(name: TypeName): Ident = self.Ident(name) def unapply(tree: Tree): Option[TypeName] = tree match { case MaybeTypeTreeOriginal(Ident(name: TypeName)) => Some(name) case _ => None } } /** Facade over Imports and ImportSelectors that lets to structurally * deconstruct/reconstruct them. * * Selectors are represented in the following way: * 1. q"import foo._" <==> q"import foo.${pq"_"}" * 2. q"import foo.bar" <==> q"import foo.${pq"bar"}" * 3. q"import foo.{bar => baz}" <==> q"import foo.${pq"bar -> baz"}" * 4. q"import foo.{bar => _}" <==> q"import foo.${pq"bar -> _"}" * * All names in selectors are TermNames despite the fact ImportSelector * can theoretically contain TypeNames too (but they never do in practice.) */ object SyntacticImport extends SyntacticImportExtractor { // construct/deconstruct {_} import selector private object WildcardSelector { def apply(offset: Int): ImportSelector = ImportSelector(nme.WILDCARD, offset, null, -1) def unapply(sel: ImportSelector): Option[Int] = sel match { case ImportSelector(nme.WILDCARD, offset, null, -1) => Some(offset) case _ => None } } // construct/deconstruct {foo} import selector private object NameSelector { def apply(name: TermName, offset: Int): ImportSelector = ImportSelector(name, offset, name, offset) def unapply(sel: ImportSelector): Option[(TermName, Int)] = sel match { case ImportSelector(name1, offset1, name2, offset2) if name1 == name2 && offset1 == offset2 => Some((name1.toTermName, offset1)) case _ => None } } // construct/deconstruct {foo => bar} import selector private object RenameSelector { def apply(name1: TermName, offset1: Int, name2: TermName, offset2: Int): ImportSelector = ImportSelector(name1, offset1, name2, offset2) def unapply(sel: ImportSelector): Option[(TermName, Int, TermName, Int)] = sel match { case ImportSelector(_, _, null | nme.WILDCARD, _) => None case ImportSelector(name1, offset1, name2, offset2) if name1 != name2 => Some((name1.toTermName, offset1, name2.toTermName, offset2)) case _ => None } } // construct/deconstruct {foo => _} import selector private object UnimportSelector { def apply(name: TermName, offset: Int): ImportSelector = ImportSelector(name, offset, nme.WILDCARD, -1) def unapply(sel: ImportSelector): Option[(TermName, Int)] = sel match { case ImportSelector(name, offset, nme.WILDCARD, _) => Some((name.toTermName, offset)) case _ => None } } // represent {_} import selector as pq"_" private object WildcardSelectorRepr { def apply(pos: Position): Tree = atPos(pos)(self.Ident(nme.WILDCARD)) def unapply(tree: Tree): Option[Position] = tree match { case self.Ident(nme.WILDCARD) => Some(tree.pos) case _ => None } } // represent {foo} import selector as pq"foo" private object NameSelectorRepr { def apply(name: TermName, pos: Position): Tree = atPos(pos)(Bind(name, WildcardSelectorRepr(pos))) def unapply(tree: Tree): Option[(TermName, Position)] = tree match { case Bind(name, WildcardSelectorRepr(_)) => Some((name.toTermName, tree.pos)) case _ => None } } // pq"left -> right" private object Arrow { def apply(left: Tree, right: Tree): Apply = Apply(self.Ident(nme.MINGT), left :: right :: Nil) def unapply(tree: Apply): Option[(Tree, Tree)] = tree match { case Apply(self.Ident(nme.MINGT), left :: right :: Nil) => Some((left, right)) case _ => None } } // represent {foo => bar} import selector as pq"foo -> bar" private object RenameSelectorRepr { def apply(name1: TermName, pos1: Position, name2: TermName, pos2: Position): Tree = { val left = NameSelectorRepr(name1, pos1) val right = NameSelectorRepr(name2, pos2) atPos(wrappingPos(left :: right :: Nil))(Arrow(left, right)) } def unapply(tree: Tree): Option[(TermName, Position, TermName, Position)] = tree match { case Arrow(NameSelectorRepr(name1, pos1), NameSelectorRepr(name2, pos2)) => Some((name1.toTermName, pos1, name2.toTermName, pos2)) case _ => None } } // represent {foo => _} import selector as pq"foo -> _" private object UnimportSelectorRepr { def apply(name: TermName, pos: Position): Tree = atPos(pos)(Arrow(NameSelectorRepr(name, pos), WildcardSelectorRepr(pos))) def unapply(tree: Tree): Option[(TermName, Position)] = tree match { case Arrow(NameSelectorRepr(name, pos), WildcardSelectorRepr(_)) => Some((name, pos)) case _ => None } } private def derivedPos(t: Tree, offset: Int): Position = if (t.pos == NoPosition) NoPosition else t.pos.withPoint(offset) private def derivedOffset(pos: Position): Int = if (pos == NoPosition) -1 else pos.point def apply(expr: Tree, selectors: List[Tree]): Import = { val importSelectors = selectors.map { case WildcardSelectorRepr(pos) => WildcardSelector(derivedOffset(pos)) case NameSelectorRepr(name, pos) => NameSelector(name, derivedOffset(pos)) case RenameSelectorRepr(name1, pos1, name2, pos2) => RenameSelector(name1, derivedOffset(pos1), name2, derivedOffset(pos2)) case UnimportSelectorRepr(name, pos) => UnimportSelector(name, derivedOffset(pos)) case tree => throw new IllegalArgumentException(s"${showRaw(tree)} doesn't correspond to import selector") } Import(expr, importSelectors) } def unapply(imp: Import): Some[(Tree, List[Tree])] = { val selectors = imp.selectors.map { case WildcardSelector(offset) => WildcardSelectorRepr(derivedPos(imp, offset)) case NameSelector(name, offset) => NameSelectorRepr(name, derivedPos(imp, offset)) case RenameSelector(name1, offset1, name2, offset2) => RenameSelectorRepr(name1, derivedPos(imp, offset1), name2, derivedPos(imp, offset2)) case UnimportSelector(name, offset) => UnimportSelectorRepr(name, derivedPos(imp, offset)) } Some((imp.expr, selectors)) } } object SyntacticSelectType extends SyntacticSelectTypeExtractor { def apply(qual: Tree, name: TypeName): Select = Select(qual, name) def unapply(tree: Tree): Option[(Tree, TypeName)] = tree match { case MaybeTypeTreeOriginal(Select(qual, name: TypeName)) => Some((qual, name)) case _ => None } } object SyntacticSelectTerm extends SyntacticSelectTermExtractor { def apply(qual: Tree, name: TermName): Select = Select(qual, name) def unapply(tree: Tree): Option[(Tree, TermName)] = tree match { case Select(qual, name: TermName) => Some((qual, name)) case _ => None } } object SyntacticCompoundType extends SyntacticCompoundTypeExtractor { def apply(parents: List[Tree], defns: List[Tree]) = CompoundTypeTree(Template(gen.mkParents(NoMods, parents), noSelfType, defns)) def unapply(tree: Tree): Option[(List[Tree], List[Tree])] = tree match { case MaybeTypeTreeOriginal(CompoundTypeTree(Template(parents, _, defns))) => Some((parents, defns)) case _ => None } } object SyntacticSingletonType extends SyntacitcSingletonTypeExtractor { def apply(ref: Tree): SingletonTypeTree = SingletonTypeTree(ref) def unapply(tree: Tree): Option[Tree] = tree match { case MaybeTypeTreeOriginal(SingletonTypeTree(ref)) => Some(ref) case _ => None } } object SyntacticTypeProjection extends SyntacticTypeProjectionExtractor { def apply(qual: Tree, name: TypeName): SelectFromTypeTree = SelectFromTypeTree(qual, name) def unapply(tree: Tree): Option[(Tree, TypeName)] = tree match { case MaybeTypeTreeOriginal(SelectFromTypeTree(qual, name)) => Some((qual, name)) case _ => None } } object SyntacticAnnotatedType extends SyntacticAnnotatedTypeExtractor { def apply(tpt: Tree, annot: Tree): Annotated = Annotated(annot, tpt) def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { case MaybeTypeTreeOriginal(Annotated(annot, tpt)) => Some((tpt, annot)) case _ => None } } object SyntacticExistentialType extends SyntacticExistentialTypeExtractor { def apply(tpt: Tree, where: List[Tree]): ExistentialTypeTree = ExistentialTypeTree(tpt, where.map { case md: MemberDef => md case tree => throw new IllegalArgumentException(s"$tree is not legal forSome definition") }) def unapply(tree: Tree): Option[(Tree, List[MemberDef])] = tree match { case MaybeTypeTreeOriginal(ExistentialTypeTree(tpt, where)) => Some((tpt, where)) case _ => None } } } val build = new ReificationSupportImpl }