diff options
6 files changed, 34 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 61ea9230a7..d122a1a207 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -623,15 +623,6 @@ self => syntaxError(tpt.pos, "no * parameter type allowed here", skipIt = false) } - /** Check that tree is a legal clause of a forSome. */ - def checkLegalExistential(t: Tree) = t match { - case TypeDef(_, _, _, TypeBoundsTree(_, _)) | - ValDef(_, _, _, EmptyTree) | EmptyTree => - ; - case _ => - syntaxError(t.pos, "not a legal existential clause", skipIt = false) - } - /* -------------- TOKEN CLASSES ------------------------------------------- */ def isModifier: Boolean = in.token match { @@ -885,9 +876,14 @@ self => } } private def makeExistentialTypeTree(t: Tree) = { - val whereClauses = refinement() - whereClauses foreach checkLegalExistential - ExistentialTypeTree(t, whereClauses) + // EmptyTrees in the result of refinement() stand for parse errors + // so it's okay for us to filter them out here + ExistentialTypeTree(t, refinement() flatMap { + case t @ TypeDef(_, _, _, TypeBoundsTree(_, _)) => Some(t) + case t @ ValDef(_, _, _, EmptyTree) => Some(t) + case EmptyTree => None + case _ => syntaxError(t.pos, "not a legal existential clause", skipIt = false); None + }) } /** {{{ diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index 241747e6d8..83da5141b9 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -2058,8 +2058,8 @@ trait Trees { self: Universe => * @group Extractors */ abstract class ExistentialTypeTreeExtractor { - def apply(tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree - def unapply(existentialTypeTree: ExistentialTypeTree): Option[(Tree, List[Tree])] + def apply(tpt: Tree, whereClauses: List[MemberDef]): ExistentialTypeTree + def unapply(existentialTypeTree: ExistentialTypeTree): Option[(Tree, List[MemberDef])] } /** The API that all existential type trees support @@ -2069,8 +2069,12 @@ trait Trees { self: Universe => /** The underlying type of the existential type. */ def tpt: Tree - /** The clauses of the definition of the existential type. */ - def whereClauses: List[Tree] + /** The clauses of the definition of the existential type. + * Elements are one of the following: + * 1) TypeDef with TypeBoundsTree right-hand side + * 2) ValDef with empty right-hand side + */ + def whereClauses: List[MemberDef] } /** A synthetic tree holding an arbitrary type. Not to be confused with @@ -2533,7 +2537,7 @@ trait Trees { self: Universe => /** Creates a `ExistentialTypeTree` node from the given components, having a given `tree` as a prototype. * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result. */ - def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[MemberDef]): ExistentialTypeTree } // ---------------------- traversing and transforming ------------------------------ @@ -2654,6 +2658,8 @@ trait Trees { self: Universe => def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] = treess mapConserve (transformValDefs(_)) /** Transforms a list of `CaseDef` nodes. */ + def transformMemberDefs(trees: List[MemberDef]): List[MemberDef] = + trees mapConserve (tree => transform(tree).asInstanceOf[MemberDef]) def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] = trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef]) /** Transforms a list of `Ident` nodes. */ diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index cc6e55192f..91ba552012 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -409,7 +409,7 @@ trait Importers extends api.Importers { to: SymbolTable => case from.TypeBoundsTree(lo, hi) => new TypeBoundsTree(importTree(lo), importTree(hi)) case from.ExistentialTypeTree(tpt, whereClauses) => - new ExistentialTypeTree(importTree(tpt), whereClauses map importTree) + new ExistentialTypeTree(importTree(tpt), whereClauses map importMemberDef) case from.EmptyTree => EmptyTree case null => @@ -475,6 +475,7 @@ trait Importers extends api.Importers { to: SymbolTable => new ImportSelector(importName(sel.name), sel.namePos, if (sel.rename != null) importName(sel.rename) else null, sel.renamePos) def importValDef(tree: from.ValDef): ValDef = importTree(tree).asInstanceOf[ValDef] def importTypeDef(tree: from.TypeDef): TypeDef = importTree(tree).asInstanceOf[TypeDef] + def importMemberDef(tree: from.MemberDef): MemberDef = importTree(tree).asInstanceOf[MemberDef] def importTemplate(tree: from.Template): Template = importTree(tree).asInstanceOf[Template] def importRefTree(tree: from.RefTree): RefTree = importTree(tree).asInstanceOf[RefTree] def importIdent(tree: from.Ident): Ident = importTree(tree).asInstanceOf[Ident] diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index d191fbd38f..4a518f6c56 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -541,7 +541,7 @@ trait Trees extends api.Trees { extends TypTree with TypeBoundsTreeApi object TypeBoundsTree extends TypeBoundsTreeExtractor - case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) + case class ExistentialTypeTree(tpt: Tree, whereClauses: List[MemberDef]) extends TypTree with ExistentialTypeTreeApi object ExistentialTypeTree extends ExistentialTypeTreeExtractor @@ -694,7 +694,7 @@ trait Trees extends api.Trees { new AppliedTypeTree(tpt, args).copyAttrs(tree) def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree) = new TypeBoundsTree(lo, hi).copyAttrs(tree) - def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[MemberDef]) = new ExistentialTypeTree(tpt, whereClauses).copyAttrs(tree) } @@ -910,7 +910,7 @@ trait Trees extends api.Trees { if (lo0 == lo) && (hi0 == hi) => t case _ => treeCopy.TypeBoundsTree(tree, lo, hi) } - def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]) = tree match { + def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[MemberDef]) = tree match { case t @ ExistentialTypeTree(tpt0, whereClauses0) if (tpt0 == tpt) && (whereClauses0 == whereClauses) => t case _ => treeCopy.ExistentialTypeTree(tree, tpt, whereClauses) @@ -1421,7 +1421,7 @@ trait Trees extends api.Trees { case CompoundTypeTree(templ) => treeCopy.CompoundTypeTree(tree, transformTemplate(templ)) case ExistentialTypeTree(tpt, whereClauses) => - treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses)) + treeCopy.ExistentialTypeTree(tree, transform(tpt), transformMemberDefs(whereClauses)) case Return(expr) => treeCopy.Return(tree, transform(expr)) case Alternative(trees) => diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index a6c34935ad..3d222fce10 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -487,6 +487,7 @@ abstract class UnPickler { def nameRef() = readNameRef() def tparamRef() = readTypeDefRef() def vparamRef() = readValDefRef() + def memberRef() = readMemberDefRef() def constRef() = readConstantRef() def idRef() = readIdentRef() def termNameRef() = readNameRef().toTermName @@ -520,7 +521,7 @@ abstract class UnPickler { case CLASStree => ClassDef(modsRef, typeNameRef, rep(tparamRef), implRef) case COMPOUNDTYPEtree => CompoundTypeTree(implRef) case DEFDEFtree => DefDef(modsRef, termNameRef, rep(tparamRef), rep(rep(vparamRef)), ref, ref) - case EXISTENTIALTYPEtree => ExistentialTypeTree(ref, all(ref)) + case EXISTENTIALTYPEtree => ExistentialTypeTree(ref, all(memberRef)) case FUNCTIONtree => Function(rep(vparamRef), ref) case IMPORTtree => Import(ref, selectorsRef) case LABELtree => LabelDef(termNameRef, rep(idRef), ref) @@ -634,6 +635,12 @@ abstract class UnPickler { case other => errorBadSignature("expected an TypeDef (" + other + ")") } + protected def readMemberDefRef(): MemberDef = + readTreeRef() match { + case tree:MemberDef => tree + case other => + errorBadSignature("expected an MemberDef (" + other + ")") + } protected def errorBadSignature(msg: String) = throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg) diff --git a/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala index c5cac3ea45..fe90d7222f 100644 --- a/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala +++ b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala @@ -92,7 +92,7 @@ trait ArbitraryTreesAndNames { yield DefDef(mods, name, tparams, vparamss, tpt, rhs) def genExistentialTypeTree(size: Int) = - for(tpt <- genTree(size - 1); where <- smallList(size, genTree(size - 1))) + for(tpt <- genTree(size - 1); where <- smallList(size, oneOf(genValDef(size - 1), genTypeDef(size - 1)))) yield ExistentialTypeTree(tpt, where) def genFunction(size: Int) = |