From 41a7fe2d356e1958b1b4e2c72e505edea23387e2 Mon Sep 17 00:00:00 2001 From: "Ben L. Titzer" Date: Wed, 26 Jun 2024 10:55:34 -0400 Subject: [PATCH] Allow _ in match patterns --- aeneas/src/main/Version.v3 | 2 +- aeneas/src/ssa/VstSsaGen.v3 | 8 +++++--- aeneas/src/vst/Parser.v3 | 6 ++++-- aeneas/src/vst/Verifier.v3 | 9 ++++++--- aeneas/src/vst/Vst.v3 | 1 + doc/aeneas-issues.txt | 1 + test/core/parser/match_underscore00.v3 | 6 ++++++ test/core/parser/match_underscore01.v3 | 6 ++++++ test/core/parser/match_underscore02.v3 | 6 ++++++ test/core/parser/match_underscore03.v3 | 7 +++++++ test/core/parser/match_underscore04.v3 | 9 +++++++++ test/core/parser/match_underscore05.v3 | 6 ++++++ test/core/parser/match_underscore06.v3 | 6 ++++++ test/core/parser/match_underscore07.v3 | 6 ++++++ test/core/parser/match_underscore08.v3 | 6 ++++++ test/core/parser/match_underscore09.v3 | 6 ++++++ test/core/parser/match_underscore10.v3 | 6 ++++++ test/core/parser/match_underscore11.v3 | 6 ++++++ test/core/parser/match_underscore12.v3 | 6 ++++++ test/core/parser/match_underscore13.v3 | 6 ++++++ test/fail/match_cover00.v3 | 8 ++++++++ test/fail/match_cover01.v3 | 8 ++++++++ test/fail/match_cover02.v3 | 8 ++++++++ test/variants/match_underscore00.v3 | 10 ++++++++++ test/variants/match_underscore01.v3 | 10 ++++++++++ test/variants/match_underscore02.v3 | 12 ++++++++++++ test/variants/match_underscore03.v3 | 12 ++++++++++++ test/variants/match_underscore04.v3 | 13 +++++++++++++ test/variants/match_underscore05.v3 | 13 +++++++++++++ test/variants/match_underscore06.v3 | 13 +++++++++++++ test/variants/match_underscore07.v3 | 13 +++++++++++++ test/variants/match_underscore08.v3 | 13 +++++++++++++ test/variants/match_underscore09.v3 | 13 +++++++++++++ test/variants/seman/match_underscore00.v3 | 10 ++++++++++ test/variants/seman/match_underscore01.v3 | 10 ++++++++++ test/variants/seman/match_underscore02.v3 | 10 ++++++++++ test/variants/seman/match_underscore03.v3 | 10 ++++++++++ test/variants/seman/match_underscore04.v3 | 10 ++++++++++ test/variants/seman/match_underscore05.v3 | 10 ++++++++++ test/variants/seman/match_underscore06.v3 | 12 ++++++++++++ test/variants/seman/match_underscore07.v3 | 12 ++++++++++++ test/variants/seman/match_underscore08.v3 | 12 ++++++++++++ test/variants/seman/match_underscore09.v3 | 12 ++++++++++++ test/variants/seman/match_underscore10.v3 | 12 ++++++++++++ 44 files changed, 372 insertions(+), 9 deletions(-) create mode 100644 test/core/parser/match_underscore00.v3 create mode 100644 test/core/parser/match_underscore01.v3 create mode 100644 test/core/parser/match_underscore02.v3 create mode 100644 test/core/parser/match_underscore03.v3 create mode 100644 test/core/parser/match_underscore04.v3 create mode 100644 test/core/parser/match_underscore05.v3 create mode 100644 test/core/parser/match_underscore06.v3 create mode 100644 test/core/parser/match_underscore07.v3 create mode 100644 test/core/parser/match_underscore08.v3 create mode 100644 test/core/parser/match_underscore09.v3 create mode 100644 test/core/parser/match_underscore10.v3 create mode 100644 test/core/parser/match_underscore11.v3 create mode 100644 test/core/parser/match_underscore12.v3 create mode 100644 test/core/parser/match_underscore13.v3 create mode 100644 test/fail/match_cover00.v3 create mode 100644 test/fail/match_cover01.v3 create mode 100644 test/fail/match_cover02.v3 create mode 100644 test/variants/match_underscore00.v3 create mode 100644 test/variants/match_underscore01.v3 create mode 100644 test/variants/match_underscore02.v3 create mode 100644 test/variants/match_underscore03.v3 create mode 100644 test/variants/match_underscore04.v3 create mode 100644 test/variants/match_underscore05.v3 create mode 100644 test/variants/match_underscore06.v3 create mode 100644 test/variants/match_underscore07.v3 create mode 100644 test/variants/match_underscore08.v3 create mode 100644 test/variants/match_underscore09.v3 create mode 100644 test/variants/seman/match_underscore00.v3 create mode 100644 test/variants/seman/match_underscore01.v3 create mode 100644 test/variants/seman/match_underscore02.v3 create mode 100644 test/variants/seman/match_underscore03.v3 create mode 100644 test/variants/seman/match_underscore04.v3 create mode 100644 test/variants/seman/match_underscore05.v3 create mode 100644 test/variants/seman/match_underscore06.v3 create mode 100644 test/variants/seman/match_underscore07.v3 create mode 100644 test/variants/seman/match_underscore08.v3 create mode 100644 test/variants/seman/match_underscore09.v3 create mode 100644 test/variants/seman/match_underscore10.v3 diff --git a/aeneas/src/main/Version.v3 b/aeneas/src/main/Version.v3 index 124835580..e92fc0544 100644 --- a/aeneas/src/main/Version.v3 +++ b/aeneas/src/main/Version.v3 @@ -3,6 +3,6 @@ // Updated by VCS scripts. DO NOT EDIT. component Version { - def version: string = "III-7.1742"; + def version: string = "III-7.1743"; var buildData: string; } diff --git a/aeneas/src/ssa/VstSsaGen.v3 b/aeneas/src/ssa/VstSsaGen.v3 index 84b325fe9..c1242e115 100644 --- a/aeneas/src/ssa/VstSsaGen.v3 +++ b/aeneas/src/ssa/VstSsaGen.v3 @@ -603,11 +603,13 @@ class VstSsaGen extends VstVisitor { var ta = [keyType], args = [newKey], i = 0; var ic = ir.makeIrClass(newKeyType); for (pl = p.params.list; pl != null; pl = pl.tail) { // XXX: mark and skip unused params - var fieldRef = IrSpec.new(newKeyType, ta, ic.fields[i++]); - pl.head.ssa = VstSsaVar.new(); + var vdecl = pl.head, field = ic.fields[i++]; + if (vdecl.isUnderscore()) continue; // unused part of a match + var fieldRef = IrSpec.new(newKeyType, ta, field); + vdecl.ssa = VstSsaVar.new(); var op = V3Op.newVariantGetField(fieldRef); var load = env.add(op, [newKey], fieldRef.member.facts); - pl.head.ssa.instr = load; + vdecl.ssa.instr = load; if (load.inputs.length == 1 && load.input0() == newKey) { // loads of non-default variants don't need null checks if (p.decl().variantTag > 0) load.facts |= Fact.O_NO_NULL_CHECK; diff --git a/aeneas/src/vst/Parser.v3 b/aeneas/src/vst/Parser.v3 index dfeb37b0b..b59a388c7 100644 --- a/aeneas/src/vst/Parser.v3 +++ b/aeneas/src/vst/Parser.v3 @@ -774,8 +774,10 @@ component Parser { return MatchPattern.new(expr, params); } def parseMatchParam(p: ParserState) -> VarDecl { - var id = parseIdentVoid(p); - var v = VarDecl.new(id.name, null, null); + var token: Token; + if (p.curByte == '_') token = p.token(1); + else token = parseIdentVoid(p).name; + var v = VarDecl.new(token, null, null); v.isReadOnly = true; return v; } diff --git a/aeneas/src/vst/Verifier.v3 b/aeneas/src/vst/Verifier.v3 index 276e85552..cc722f2bd 100644 --- a/aeneas/src/vst/Verifier.v3 +++ b/aeneas/src/vst/Verifier.v3 @@ -1220,7 +1220,7 @@ class TypeChecker(ERROR: ErrorGen, file: VstFile) extends VstVisitor } if (mv.variantType != null) return checkVariantPattern(mv, pat); if (mv.enumType != null) return checkEnumPattern(mv, pat); - if (pat.params != null) return errAtRange(pat.params.range()).MatchError("match pattern cannot have parameters"); + if (pat.params != null) return errAtRange(pat.params.range()).MatchError(Strings.format1("match on type %s cannot have parameters", TYPE(mv.etype))); typeCheckExpr(e, mv.etype, "match case"); if (!VarExpr.?(e)) return errAtExpr(e).MatchError("match expression is not a constant"); var ve = VarExpr.!(e); @@ -1257,13 +1257,16 @@ class TypeChecker(ERROR: ErrorGen, file: VstFile) extends VstVisitor var ll = pat.params.list, pl = pat.decl().params.list; var typeArgs = vt.getTypeArgs(); while (ll != null) { + var vdecl = ll.head; if (pl == null) { var msg = Strings.format2("case %q.%s", vt.render, pat.decl().name()); errAtToken(ll.head.token).ArityMismatch(msg, Lists.length(pat.decl().params.list), Lists.length(pat.params.list)); return; } - ll.head.vtype = pl.head.vtype.substitute(typeArgs); - methodEnv.bindVar(ll.head); + if (!vdecl.isUnderscore()) { + vdecl.vtype = pl.head.vtype.substitute(typeArgs); + methodEnv.bindVar(vdecl); + } ll = ll.tail; pl = pl.tail; } diff --git a/aeneas/src/vst/Vst.v3 b/aeneas/src/vst/Vst.v3 index 9bd007941..20b59777d 100644 --- a/aeneas/src/vst/Vst.v3 +++ b/aeneas/src/vst/Vst.v3 @@ -85,6 +85,7 @@ class Decl(token: Token) { def render(buf: StringBuilder) -> StringBuilder { return buf.puts(token.image); } + def isUnderscore() -> bool { return Strings.equal("_", token.image); } // XXX: make a boolean field? } // Parsed parameter class ParamDecl extends VarDecl { diff --git a/doc/aeneas-issues.txt b/doc/aeneas-issues.txt index dc080ee66..106e29ace 100644 --- a/doc/aeneas-issues.txt +++ b/doc/aeneas-issues.txt @@ -109,6 +109,7 @@ ______ ______ __ _ ______ ______ ______ _____ ______ ______ _ _ ______ _ debugger: allow fuzzy match of files / line immutable arrays -- done ------- +* Allow _ in match patterns * wasm target allows omitting main * off-heap Range * stray updateVar for phis diff --git a/test/core/parser/match_underscore00.v3 b/test/core/parser/match_underscore00.v3 new file mode 100644 index 000000000..fe1fd5717 --- /dev/null +++ b/test/core/parser/match_underscore00.v3 @@ -0,0 +1,6 @@ +//@parse +def m() { + match (m) { + A(_) => ; + } +} diff --git a/test/core/parser/match_underscore01.v3 b/test/core/parser/match_underscore01.v3 new file mode 100644 index 000000000..e0c0b988a --- /dev/null +++ b/test/core/parser/match_underscore01.v3 @@ -0,0 +1,6 @@ +//@parse +def m() { + match (m) { + A(x, _) => ; + } +} diff --git a/test/core/parser/match_underscore02.v3 b/test/core/parser/match_underscore02.v3 new file mode 100644 index 000000000..52c1f9c5f --- /dev/null +++ b/test/core/parser/match_underscore02.v3 @@ -0,0 +1,6 @@ +//@parse = ParseError @ 4:19 +def m() { + match (m) { + _ _ => ; + } +} diff --git a/test/core/parser/match_underscore03.v3 b/test/core/parser/match_underscore03.v3 new file mode 100644 index 000000000..1fe46ebf2 --- /dev/null +++ b/test/core/parser/match_underscore03.v3 @@ -0,0 +1,7 @@ +//@parse +def m() { + match (m) { + A(_, _) => ; + _ => ; + } +} diff --git a/test/core/parser/match_underscore04.v3 b/test/core/parser/match_underscore04.v3 new file mode 100644 index 000000000..c30589036 --- /dev/null +++ b/test/core/parser/match_underscore04.v3 @@ -0,0 +1,9 @@ +//@parse +def m() { + match (m) { + A(_, _) => ; + x: T => ; + A(_, _) => ; + _ => ; + } +} diff --git a/test/core/parser/match_underscore05.v3 b/test/core/parser/match_underscore05.v3 new file mode 100644 index 000000000..69af23280 --- /dev/null +++ b/test/core/parser/match_underscore05.v3 @@ -0,0 +1,6 @@ +//@parse = ParseError @ 4:20 +def m() { + match (m) { + x: _ => ; + } +} diff --git a/test/core/parser/match_underscore06.v3 b/test/core/parser/match_underscore06.v3 new file mode 100644 index 000000000..09ed4bef3 --- /dev/null +++ b/test/core/parser/match_underscore06.v3 @@ -0,0 +1,6 @@ +//@parse +def m() { + match (m) { + x: T => _; + } +} diff --git a/test/core/parser/match_underscore07.v3 b/test/core/parser/match_underscore07.v3 new file mode 100644 index 000000000..7810922a2 --- /dev/null +++ b/test/core/parser/match_underscore07.v3 @@ -0,0 +1,6 @@ +//@parse = ParseError @ 4:21 +def m() { + match (m) { + x() _ => ; + } +} diff --git a/test/core/parser/match_underscore08.v3 b/test/core/parser/match_underscore08.v3 new file mode 100644 index 000000000..5eebbbce0 --- /dev/null +++ b/test/core/parser/match_underscore08.v3 @@ -0,0 +1,6 @@ +//@parse = ParseError @ 4:21 +def m() { + match (m) { + x(_ _) => ; + } +} diff --git a/test/core/parser/match_underscore09.v3 b/test/core/parser/match_underscore09.v3 new file mode 100644 index 000000000..5f9e9fc77 --- /dev/null +++ b/test/core/parser/match_underscore09.v3 @@ -0,0 +1,6 @@ +//@parse = ParseError @ 4:21 +def m() { + match (m) { + x(__) => ; + } +} diff --git a/test/core/parser/match_underscore10.v3 b/test/core/parser/match_underscore10.v3 new file mode 100644 index 000000000..4b7ac8ecc --- /dev/null +++ b/test/core/parser/match_underscore10.v3 @@ -0,0 +1,6 @@ +//@parse = ParseError @ 4:21 +def m() { + match (m) { + x(_,) => ; + } +} diff --git a/test/core/parser/match_underscore11.v3 b/test/core/parser/match_underscore11.v3 new file mode 100644 index 000000000..ab975a015 --- /dev/null +++ b/test/core/parser/match_underscore11.v3 @@ -0,0 +1,6 @@ +//@parse = ParseError @ 4:21 +def m() { + match (m) { + x(_a) => ; + } +} diff --git a/test/core/parser/match_underscore12.v3 b/test/core/parser/match_underscore12.v3 new file mode 100644 index 000000000..7c424fa8b --- /dev/null +++ b/test/core/parser/match_underscore12.v3 @@ -0,0 +1,6 @@ +//@parse +def m() { + match (m) { + x(a_) => ; + } +} diff --git a/test/core/parser/match_underscore13.v3 b/test/core/parser/match_underscore13.v3 new file mode 100644 index 000000000..5f77479a2 --- /dev/null +++ b/test/core/parser/match_underscore13.v3 @@ -0,0 +1,6 @@ +//@parse +def m() { + match (m) { + x(a_b) => ; + } +} diff --git a/test/fail/match_cover00.v3 b/test/fail/match_cover00.v3 new file mode 100644 index 000000000..4d13b631c --- /dev/null +++ b/test/fail/match_cover00.v3 @@ -0,0 +1,8 @@ +//@seman +type T(x: int); + +def m(t: T) { + match (t) { + T(_) => ; + } +} diff --git a/test/fail/match_cover01.v3 b/test/fail/match_cover01.v3 new file mode 100644 index 000000000..5b07a903f --- /dev/null +++ b/test/fail/match_cover01.v3 @@ -0,0 +1,8 @@ +//@seman +type T(x: int); + +def m(t: T) { + match (t) { + T => ; + } +} diff --git a/test/fail/match_cover02.v3 b/test/fail/match_cover02.v3 new file mode 100644 index 000000000..fb7eedf87 --- /dev/null +++ b/test/fail/match_cover02.v3 @@ -0,0 +1,8 @@ +//@seman +type T(x: int); + +def m(t: T) { + match (t) { + x: T => ; + } +} diff --git a/test/variants/match_underscore00.v3 b/test/variants/match_underscore00.v3 new file mode 100644 index 000000000..fd3dafffd --- /dev/null +++ b/test/variants/match_underscore00.v3 @@ -0,0 +1,10 @@ +//@execute 0=3; -3=0; 66=69 +type T { + case A(x: int); +} + +def main(a: int) -> int { + match (T.A(a)) { + A(_) => return a + 3; + } +} \ No newline at end of file diff --git a/test/variants/match_underscore01.v3 b/test/variants/match_underscore01.v3 new file mode 100644 index 000000000..8b58089fe --- /dev/null +++ b/test/variants/match_underscore01.v3 @@ -0,0 +1,10 @@ +//@execute 0=3; -3=0; 66=69 +type T { + case A(x: int, y: int); +} + +def main(a: int) -> int { + match (T.A(a, 11)) { + A(x, _) => return x + 3; + } +} \ No newline at end of file diff --git a/test/variants/match_underscore02.v3 b/test/variants/match_underscore02.v3 new file mode 100644 index 000000000..49ff486bd --- /dev/null +++ b/test/variants/match_underscore02.v3 @@ -0,0 +1,12 @@ +//@execute 0=3; -3=0; 66=69 +type T { + case A(x: int, y: int); +} + +def make: (int, int) -> T = T.A; + +def main(a: int) -> int { + match (make(a, 11)) { + A(x, _) => return x + 3; + } +} diff --git a/test/variants/match_underscore03.v3 b/test/variants/match_underscore03.v3 new file mode 100644 index 000000000..eea3dc16f --- /dev/null +++ b/test/variants/match_underscore03.v3 @@ -0,0 +1,12 @@ +//@execute 0=15; -3=15; 66=15 +type T { + case A(x: int, y: int); +} + +def make: (int, int) -> T = T.A; + +def main(a: int) -> int { + match (make(a, 12)) { + A(_, x) => return x + 3; + } +} diff --git a/test/variants/match_underscore04.v3 b/test/variants/match_underscore04.v3 new file mode 100644 index 000000000..559dcd5fa --- /dev/null +++ b/test/variants/match_underscore04.v3 @@ -0,0 +1,13 @@ +//@execute 0=100; 55=155 +type T { + case A(x: int, y: int, z: int); +} + +def make: (int, int, int) -> T = T.A; + +def main(a: int) -> int { + var t = make(a + 100, a + 200, a + 300); + match (t) { + A(x, _, _) => return x; + } +} diff --git a/test/variants/match_underscore05.v3 b/test/variants/match_underscore05.v3 new file mode 100644 index 000000000..15a715576 --- /dev/null +++ b/test/variants/match_underscore05.v3 @@ -0,0 +1,13 @@ +//@execute 0=200; 55=255 +type T { + case A(x: int, y: int, z: int); +} + +def make: (int, int, int) -> T = T.A; + +def main(a: int) -> int { + var t = make(a + 100, a + 200, a + 300); + match (t) { + A(_, x, _) => return x; + } +} diff --git a/test/variants/match_underscore06.v3 b/test/variants/match_underscore06.v3 new file mode 100644 index 000000000..15765a05e --- /dev/null +++ b/test/variants/match_underscore06.v3 @@ -0,0 +1,13 @@ +//@execute 0=300; 55=355 +type T { + case A(x: int, y: int, z: int); +} + +def make: (int, int, int) -> T = T.A; + +def main(a: int) -> int { + var t = make(a + 100, a + 200, a + 300); + match (t) { + A(_, _, x) => return x; + } +} diff --git a/test/variants/match_underscore07.v3 b/test/variants/match_underscore07.v3 new file mode 100644 index 000000000..60efb03c8 --- /dev/null +++ b/test/variants/match_underscore07.v3 @@ -0,0 +1,13 @@ +//@execute 0=400; 55=510 +type T { + case A(x: int, y: int, z: int); +} + +def make: (int, int, int) -> T = T.A; + +def main(a: int) -> int { + var t = make(a + 100, a + 200, a + 300); + match (t) { + A(x, _, z) => return x + z; + } +} diff --git a/test/variants/match_underscore08.v3 b/test/variants/match_underscore08.v3 new file mode 100644 index 000000000..8eda0b99b --- /dev/null +++ b/test/variants/match_underscore08.v3 @@ -0,0 +1,13 @@ +//@execute 0=100; 55=155 +type T { + case A(x: int, y: (int, int)); +} + +def make: (int, (int, int)) -> T = T.A; + +def main(a: int) -> int { + var t = make(a + 100, (a + 200, a + 300)); + match (t) { + A(x, _) => return x; + } +} diff --git a/test/variants/match_underscore09.v3 b/test/variants/match_underscore09.v3 new file mode 100644 index 000000000..d448de1f1 --- /dev/null +++ b/test/variants/match_underscore09.v3 @@ -0,0 +1,13 @@ +//@execute 0=500; 55=610 +type T { + case A(x: int, y: (int, int)); +} + +def make: (int, (int, int)) -> T = T.A; + +def main(a: int) -> int { + var t = make(a + 100, (a + 200, a + 300)); + match (t) { + A(_, y) => return y.0 + y.1; + } +} diff --git a/test/variants/seman/match_underscore00.v3 b/test/variants/seman/match_underscore00.v3 new file mode 100644 index 000000000..3b3ab0423 --- /dev/null +++ b/test/variants/seman/match_underscore00.v3 @@ -0,0 +1,10 @@ +//@seman +type T { + case A(x: int); +} + +def m(t: T) { + match (t) { + A(_) => ; + } +} diff --git a/test/variants/seman/match_underscore01.v3 b/test/variants/seman/match_underscore01.v3 new file mode 100644 index 000000000..ec3391a7e --- /dev/null +++ b/test/variants/seman/match_underscore01.v3 @@ -0,0 +1,10 @@ +//@seman +type T { + case A(x: int, y: int); +} + +def m(t: T) -> int { + match (t) { + A(x, _) => return x; + } +} diff --git a/test/variants/seman/match_underscore02.v3 b/test/variants/seman/match_underscore02.v3 new file mode 100644 index 000000000..6b487bd64 --- /dev/null +++ b/test/variants/seman/match_underscore02.v3 @@ -0,0 +1,10 @@ +//@seman +type T { + case A(x: int, y: int); +} + +def m(t: T) -> int { + match (t) { + A(_, y) => return y; + } +} diff --git a/test/variants/seman/match_underscore03.v3 b/test/variants/seman/match_underscore03.v3 new file mode 100644 index 000000000..d076eda65 --- /dev/null +++ b/test/variants/seman/match_underscore03.v3 @@ -0,0 +1,10 @@ +//@seman +type T { + case A(x: int, y: int); +} + +def m(t: T) -> int { + match (t) { + A(_, z) => return z; + } +} diff --git a/test/variants/seman/match_underscore04.v3 b/test/variants/seman/match_underscore04.v3 new file mode 100644 index 000000000..02393903e --- /dev/null +++ b/test/variants/seman/match_underscore04.v3 @@ -0,0 +1,10 @@ +//@seman = TypeError @ 8:22 +type T { + case A(x: int, y: int); +} + +def m(t: T) -> bool { + match (t) { + A(_, z) => return z; + } +} diff --git a/test/variants/seman/match_underscore05.v3 b/test/variants/seman/match_underscore05.v3 new file mode 100644 index 000000000..f6804345b --- /dev/null +++ b/test/variants/seman/match_underscore05.v3 @@ -0,0 +1,10 @@ +//@seman = ParamExprError @ 8:35 +type T { + case A(x: int, y: int); +} + +def m(t: T) -> bool { + match (t) { + A(_, z) => return _; + } +} diff --git a/test/variants/seman/match_underscore06.v3 b/test/variants/seman/match_underscore06.v3 new file mode 100644 index 000000000..fcf2d49ae --- /dev/null +++ b/test/variants/seman/match_underscore06.v3 @@ -0,0 +1,12 @@ +//@seman +type T { + case A(x: int, y: int); + case B(t: int, u: int); +} + +def m(t: T) -> int { + match (t) { + A(_, z) => return z; + B(_, z) => return z; + } +} diff --git a/test/variants/seman/match_underscore07.v3 b/test/variants/seman/match_underscore07.v3 new file mode 100644 index 000000000..69d0a9f5d --- /dev/null +++ b/test/variants/seman/match_underscore07.v3 @@ -0,0 +1,12 @@ +//@seman = UnresolvedIdentifier @ 10:35 +type T { + case A(x: int, y: int); + case B(t: int, u: int); +} + +def m(t: T) -> bool { + match (t) { + A(_, z) => return z; + B(_, _) => return z; + } +} diff --git a/test/variants/seman/match_underscore08.v3 b/test/variants/seman/match_underscore08.v3 new file mode 100644 index 000000000..26ed57cd4 --- /dev/null +++ b/test/variants/seman/match_underscore08.v3 @@ -0,0 +1,12 @@ +//@seman = TypeError @ 10:22 +type T { + case A(x: int, y: int); + case B(t: int, u: bool); +} + +def m(t: T) -> int { + match (t) { + A(_, z) => return z; + B(_, z) => return z; + } +} diff --git a/test/variants/seman/match_underscore09.v3 b/test/variants/seman/match_underscore09.v3 new file mode 100644 index 000000000..688122b6f --- /dev/null +++ b/test/variants/seman/match_underscore09.v3 @@ -0,0 +1,12 @@ +//@seman = TypeError @ 10:22 +type T { + case A(x: int, y: int, z: int); + case B(t: int, u: bool); +} + +def m(t: T) -> int { + match (t) { + A(x, _, z) => return z; + B(_, z) => return z; + } +} diff --git a/test/variants/seman/match_underscore10.v3 b/test/variants/seman/match_underscore10.v3 new file mode 100644 index 000000000..67c18e9f0 --- /dev/null +++ b/test/variants/seman/match_underscore10.v3 @@ -0,0 +1,12 @@ +//@seman +type T { + case A(x: int, y: int, z: int); + case B(t: int, u: int); +} + +def m(t: T) -> int { + match (t) { + A(x, _, z) => return z; + B(_, z) => return z; + } +}