diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 739694b709b8..30f49dddc327 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -49,9 +49,6 @@ object desugar { case None, Exhaustive, IrrefutablePatDef, IrrefutableGenFrom } - /** Info of a variable in a pattern: The named tree and its type */ - private type VarInfo = (NameTree, Tree) - /** Is `name` the name of a method that can be invalidated as a compiler-generated * case class method if it clashes with a user-defined method? */ @@ -1685,16 +1682,6 @@ object desugar { TypeDef(tpnme.REFINE_CLASS, impl).withFlags(Trait) } - /** If tree is of the form `id` or `id: T`, return its name and type, otherwise return None. - */ - private object IdPattern { - def unapply(tree: Tree)(implicit ctx: Context): Option[VarInfo] = tree match { - case id: Ident if id.name != nme.WILDCARD => Some(id, TypeTree()) - case Typed(id: Ident, tpt) => Some((id, tpt)) - case _ => None - } - } - /** Returns list of all pattern variables, possibly with their types, * without duplicates */ diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index fcb619cfca13..9d9f45dccf8b 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -345,6 +345,18 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] def bodyKind(body: List[Tree])(implicit ctx: Context): FlagSet = body.foldLeft(NoInitsInterface)((fs, stat) => fs & defKind(stat)) + /** Info of a variable in a pattern: The named tree and its type */ + type VarInfo = (NameTree, Tree) + + /** An extractor for trees of the form `id` or `id: T` */ + object IdPattern { + def unapply(tree: Tree)(implicit ctx: Context): Option[VarInfo] = tree match { + case id: Ident if id.name != nme.WILDCARD => Some(id, TypeTree()) + case Typed(id: Ident, tpt) => Some((id, tpt)) + case _ => None + } + } + // todo: fill with other methods from TreeInfo that only apply to untpd.Tree's } diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 50b917574bc4..07e6640da01c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3052,11 +3052,17 @@ object Parsers { } else EmptyTree lhs match { - case (id @ Ident(name: TermName)) :: Nil if name != nme.WILDCARD => - val vdef = ValDef(name, tpt, rhs) + case IdPattern(id, t) :: Nil if t.isEmpty => + val vdef = ValDef(id.name.asTermName, tpt, rhs) if (isBackquoted(id)) vdef.pushAttachment(Backquoted, ()) finalizeDef(vdef, mods, start) case _ => + def isAllIds = lhs.forall { + case IdPattern(id, t) => t.isEmpty + case _ => false + } + if rhs.isEmpty && !isAllIds then + syntaxError(ExpectedTokenButFound(EQUALS, in.token), Span(in.lastOffset)) PatDef(mods, lhs, tpt, rhs) } } diff --git a/tests/neg/deferred-patdef.scala b/tests/neg/deferred-patdef.scala new file mode 100644 index 000000000000..11ec8c2218d5 --- /dev/null +++ b/tests/neg/deferred-patdef.scala @@ -0,0 +1,4 @@ +object M { + val (x, y): (Int, Int) // error: `=` expected + val 1: Int // error: `=` expected +}