Skip to content

Commit f64ab0a

Browse files
committed
Attempting to add match-failed + partial deconstructors. No support for partial deconstructor exhaustiveness groups yet.
1 parent b314dba commit f64ab0a

File tree

18 files changed

+444
-8
lines changed

18 files changed

+444
-8
lines changed

src/jdk.compiler/share/classes/com/sun/source/tree/MatchTree.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@
4141
*
4242
* @since 23
4343
*/
44+
@PreviewFeature(feature= PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
45+
//TODO: maybe MatchSuccessTree?
4446
public interface MatchTree extends StatementTree {
4547

4648
/**
4749
* Returns the expression for this {@code match} statement.
4850
*
4951
* @return the expression
5052
*/
51-
@PreviewFeature(feature= PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
5253
List<? extends ExpressionTree> getArguments();
5354
}

src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,17 @@ public enum Kind {
722722
* @since 23
723723
*/
724724
@PreviewFeature(feature=PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
725-
MATCH(MatchTree.class);
725+
MATCH(MatchTree.class), //TODO: maybe MATCH_SUCCESS
726+
727+
/**
728+
* Used for instances of {@link MatchFailTree}.
729+
*
730+
* @since 25
731+
*/
732+
@PreviewFeature(feature=PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
733+
MATCH_FAILED(MatchFailTree.class),
734+
735+
;
726736

727737
Kind(Class<? extends Tree> intf) {
728738
associatedInterface = intf;

src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java

+12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
package com.sun.source.tree;
2727

28+
import jdk.internal.javac.PreviewFeature;
29+
2830
/**
2931
* A visitor of trees, in the style of the visitor design pattern.
3032
* Classes implementing this interface are used to operate
@@ -629,4 +631,14 @@ public interface TreeVisitor<R,P> {
629631
* @return a result value
630632
*/
631633
R visitMatchStatement(MatchTree node, P p);
634+
635+
/**
636+
* Visits an {@code MatchFailTree} node.
637+
* @param node the node being visited
638+
* @param p a parameter value
639+
* @return a result value
640+
* @since 25
641+
*/
642+
@PreviewFeature(feature=PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
643+
R visitMatchFailStatement(MatchFailTree node, P p);
632644
}

src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java

+13
Original file line numberDiff line numberDiff line change
@@ -1085,5 +1085,18 @@ public R visitMatchStatement(MatchTree node, P p) {
10851085
return defaultAction(node, p);
10861086
}
10871087

1088+
/**
1089+
* {@inheritDoc}
1090+
*
1091+
* @implSpec This implementation calls {@code defaultAction}.
1092+
*
1093+
* @param node {@inheritDoc}
1094+
* @param p {@inheritDoc}
1095+
* @return the result of {@code defaultAction}
1096+
*/
1097+
@Override
1098+
public R visitMatchFailStatement(MatchFailTree node, P p) {
1099+
return defaultAction(node, p);
1100+
}
10881101

10891102
}

src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java

+15
Original file line numberDiff line numberDiff line change
@@ -1240,4 +1240,19 @@ public R visitYield(YieldTree node, P p) {
12401240
public R visitMatchStatement(MatchTree node, P p) {
12411241
return scan(node.getArguments(), p);
12421242
}
1243+
1244+
/**
1245+
* {@inheritDoc}
1246+
*
1247+
* @implSpec This implementation scans the children in left to right order.
1248+
*
1249+
* @param node {@inheritDoc}
1250+
* @param p {@inheritDoc}
1251+
* @return the result of scanning
1252+
*/
1253+
@Override
1254+
public R visitMatchFailStatement(MatchFailTree node, P p) {
1255+
return null;
1256+
}
1257+
12431258
}

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,10 @@ public static EnumSet<Flag> asFlagSet(long flags) {
282282
*/
283283
public static final long THROWS = 1L<<47;
284284

285-
/*
286-
* Currently available: Bit 48.
285+
/**
286+
* Flag to indicate the given deconstructor is partial
287287
*/
288+
public static final long PARTIAL = 1L<<48; //Trees + Symbols
288289

289290
/**
290291
* Flag that marks a synthetic method body for a lambda expression

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -1200,12 +1200,16 @@ public void visitMethodDef(JCMethodDecl tree) {
12001200
}
12011201
}
12021202

1203+
//TODO: should these checks/flag setting be done in MemberEnter?
12031204
if (m.isPattern() && tree.thrown.nonEmpty()) {
12041205
log.error(tree.pos(), Errors.PatternDeclarationCantThrowException);
12051206
}
12061207

12071208
if (m.isDeconstructor()) {
12081209
m.patternFlags.add(PatternFlags.DECONSTRUCTOR);
1210+
if ((tree.mods.flags & Flags.PARTIAL) == 0) {
1211+
m.patternFlags.add(PatternFlags.TOTAL);
1212+
}
12091213
}
12101214

12111215
// annotation method checks
@@ -2457,6 +2461,14 @@ public void visitMatch(JCMatch tree) {
24572461
result = null;
24582462
}
24592463

2464+
@Override
2465+
public void visitMatchFail(JCMatchFail tree) {
2466+
if ((env.enclMethod.sym.flags_field & Flags.PARTIAL) == 0) {
2467+
log.error(tree.pos(), Errors.UnmarkedPartialDeconstructor);
2468+
}
2469+
result = null;
2470+
}
2471+
24602472
public void visitTypeTestStatement(JCInstanceOfStatement tree) {
24612473
attribExpr(tree.expr, env);
24622474
attribExpr(tree.pattern, env);
@@ -4647,7 +4659,11 @@ private List<MethodSymbol> candidatesWithArity(Type site, int nestedPatternCount
46474659
.collect(List.collector());
46484660

46494661
PatternType pt = new PatternType(recordComponents, syms.voidType, syms.methodClass);
4650-
patternDeclarations = patternDeclarations.prepend(new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, pt, site.tsym));
4662+
MethodSymbol synthetized = new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, pt, site.tsym);
4663+
4664+
synthetized.patternFlags.add(PatternFlags.DECONSTRUCTOR);
4665+
synthetized.patternFlags.add(PatternFlags.TOTAL);
4666+
patternDeclarations = patternDeclarations.prepend(synthetized);
46514667
}
46524668
}
46534669

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ private void clearPendingExits(boolean inMethod) {
633633
while (exits.nonEmpty()) {
634634
PendingExit exit = exits.head;
635635
exits = exits.tail;
636-
Assert.check((inMethod && (exit.tree.hasTag(RETURN) || exit.tree.hasTag(MATCH))) ||
636+
Assert.check((inMethod && (exit.tree.hasTag(RETURN) || exit.tree.hasTag(MATCH) || exit.tree.hasTag(MATCHFAIL))) ||
637637
log.hasErrorOn(exit.tree.pos()));
638638
}
639639
}
@@ -725,6 +725,10 @@ public void visitTypeTestStatement(JCInstanceOfStatement tree) {
725725
alive = alive.or(resolveBreaks(tree, prevPendingExits));
726726
}
727727

728+
public void visitMatchFail(JCMatchFail tree) {
729+
recordExit(new PendingExit(tree));
730+
}
731+
728732
public void visitForeachLoop(JCEnhancedForLoop tree) {
729733
visitVarDef(tree.var);
730734
ListBuffer<PendingExit> prevPendingExits = pendingExits;
@@ -827,6 +831,10 @@ private boolean exhausts(JCExpression selector, List<JCCase> cases) {
827831

828832
for (var l : c.labels) {
829833
if (l instanceof JCPatternCaseLabel patternLabel) {
834+
if (patternLabel.pat instanceof JCRecordPattern rec &&
835+
!rec.patternDeclaration.patternFlags.contains(PatternFlags.TOTAL)) {
836+
continue;
837+
}
830838
for (Type component : components(selector.type)) {
831839
patternSet.add(makePatternDescription(component, patternLabel.pat));
832840
}
@@ -1585,6 +1593,7 @@ else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
15851593
if (!(exit instanceof ThrownPendingExit)) {
15861594
Assert.check(exit.tree.hasTag(RETURN) ||
15871595
exit.tree.hasTag(MATCH) ||
1596+
exit.tree.hasTag(MATCHFAIL) ||
15881597
log.hasErrorOn(exit.tree.pos()));
15891598
} else {
15901599
// uncaught throws will be reported later
@@ -1846,6 +1855,10 @@ public void visitMatch(JCMatch tree) {
18461855
recordExit(new PendingExit(tree));
18471856
}
18481857

1858+
public void visitMatchFail(JCMatchFail tree) {
1859+
recordExit(new PendingExit(tree));
1860+
}
1861+
18491862
public void visitThrow(JCThrow tree) {
18501863
scan(tree.expr);
18511864
Symbol sym = TreeInfo.symbol(tree.expr);

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java

+8
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
104104
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
105105
import com.sun.tools.javac.tree.JCTree.JCLambda;
106+
import com.sun.tools.javac.tree.JCTree.JCMatchFail;
106107
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
107108
import com.sun.tools.javac.tree.JCTree.JCNewClass;
108109
import com.sun.tools.javac.tree.JCTree.JCPattern;
@@ -135,6 +136,7 @@ public static TransPatterns instance(Context context) {
135136
private final Symtab syms;
136137
private final Attr attr;
137138
private final Resolve rs;
139+
private final TypeEnvs typeEnvs;
138140
private final Types types;
139141
private final Operators operators;
140142
private final Names names;
@@ -196,6 +198,7 @@ protected TransPatterns(Context context) {
196198
syms = Symtab.instance(context);
197199
attr = Attr.instance(context);
198200
rs = Resolve.instance(context);
201+
typeEnvs = TypeEnvs.instance(context);
199202
make = TreeMaker.instance(context);
200203
types = Types.instance(context);
201204
operators = Operators.instance(context);
@@ -1043,6 +1046,11 @@ public void visitMatch(JCMatch tree) {
10431046
result = make.at(tree.pos).Block(0, stats.toList());
10441047
}
10451048

1049+
@Override
1050+
public void visitMatchFail(JCMatchFail tree) {
1051+
result = make.at(tree.pos).Return(makeNull());
1052+
}
1053+
10461054
private class PrimitiveGenerator extends Types.SignatureGenerator {
10471055

10481056
/**

src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java

+15
Original file line numberDiff line numberDiff line change
@@ -2949,6 +2949,20 @@ List<JCStatement> blockStatement() {
29492949
List<JCExpression> args = arguments();
29502950
accept(SEMI);
29512951
return List.of(toP(F.at(pos).Match(name, args)));
2952+
} else if (next.kind == SUB) {
2953+
Token nextNext = S.token(2);
2954+
if (nextNext.kind == IDENTIFIER) {
2955+
if (nextNext.name().contentEquals("fail")) {
2956+
checkSourceLevel(Feature.PATTERN_DECLARATIONS);
2957+
nextToken();
2958+
nextToken();
2959+
nextToken();
2960+
accept(LPAREN);
2961+
accept(RPAREN);
2962+
accept(SEMI);
2963+
return List.of(toP(F.at(pos).MatchFail()));
2964+
}
2965+
}
29522966
}
29532967
} else
29542968
if (token.name() == names.yield && allowYieldStatement) {
@@ -3627,6 +3641,7 @@ protected JCModifiers modifiersOpt(JCModifiers partial) {
36273641
case STRICTFP : flag = Flags.STRICTFP; break;
36283642
case MONKEYS_AT : flag = Flags.ANNOTATION; break;
36293643
case DEFAULT : flag = Flags.DEFAULT; break;
3644+
case CASE : flag = Flags.PARTIAL; break;
36303645
case ERROR : flag = 0; nextToken(); break;
36313646
case IDENTIFIER : {
36323647
if (isNonSealedClassStart(false)) {

src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties

+6
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,9 @@ compiler.err.missing.ret.stmt=\
944944
compiler.err.missing.match.stmt=\
945945
missing match statement
946946

947+
compiler.err.missing.match.stmt=\
948+
missing match statement
949+
947950
# 0: type
948951
compiler.misc.missing.ret.val=\
949952
missing return value
@@ -4290,3 +4293,6 @@ compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\
42904293
compiler.err.enclosing.class.type.non.denotable=\
42914294
enclosing class type: {0}\n\
42924295
is non-denotable, try casting to a denotable type
4296+
4297+
compiler.err.unmarked.partial.deconstructor=\
4298+
deconstructor not marked as partial, match-fail illegal

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java

+27
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ public enum Tag {
213213
*/
214214
MATCH,
215215

216+
/** Match fail statements, of type MatchFail.
217+
*/
218+
MATCHFAIL,
219+
216220
/** Method invocation expressions, of type Apply.
217221
*/
218222
APPLY,
@@ -1808,6 +1812,28 @@ public Tag getTag() {
18081812
}
18091813
}
18101814

1815+
/**
1816+
* The match-fail statement
1817+
*/
1818+
public static class JCMatchFail extends JCStatement implements MatchFailTree {
1819+
1820+
protected JCMatchFail() {
1821+
}
1822+
@Override
1823+
public void accept(Visitor v) { v.visitMatchFail(this); }
1824+
1825+
@DefinedBy(Api.COMPILER_TREE)
1826+
public Kind getKind() { return Kind.MATCH_FAILED; }
1827+
@Override @DefinedBy(Api.COMPILER_TREE)
1828+
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
1829+
return v.visitMatchFailStatement(this, d);
1830+
}
1831+
@Override
1832+
public Tag getTag() {
1833+
return MATCHFAIL;
1834+
}
1835+
}
1836+
18111837
/**
18121838
* A continue of a loop.
18131839
*/
@@ -3631,6 +3657,7 @@ public abstract static class Visitor {
36313657
public void visitBreak(JCBreak that) { visitTree(that); }
36323658
public void visitYield(JCYield that) { visitTree(that); }
36333659
public void visitMatch(JCMatch that) { visitTree(that); }
3660+
public void visitMatchFail(JCMatchFail that) { visitTree(that); }
36343661
public void visitContinue(JCContinue that) { visitTree(that); }
36353662
public void visitReturn(JCReturn that) { visitTree(that); }
36363663
public void visitThrow(JCThrow that) { visitTree(that); }

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java

+7
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ public JCTree visitMatchStatement(MatchTree node, P p) {
157157
return M.at(t.pos).Match(t.clazz, args);
158158
}
159159

160+
@DefinedBy(Api.COMPILER_TREE)
161+
public JCTree visitMatchFailStatement(MatchFailTree node, P p) {
162+
JCMatchFail t = (JCMatchFail) node;
163+
164+
return M.at(t.pos).MatchFail();
165+
}
166+
160167
@DefinedBy(Api.COMPILER_TREE)
161168
public JCTree visitCase(CaseTree node, P p) {
162169
JCCase t = (JCCase) node;

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java

+6
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,12 @@ public JCMatch Match(Name clazz, List<JCExpression> args) {
402402
return tree;
403403
}
404404

405+
public JCMatchFail MatchFail() {
406+
JCMatchFail tree = new JCMatchFail();
407+
tree.pos = pos;
408+
return tree;
409+
}
410+
405411
public JCMethodInvocation Apply(List<JCExpression> typeargs,
406412
JCExpression fn,
407413
List<JCExpression> args)

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java

+3
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ public void visitMatch(JCMatch tree) {
238238
scan(tree.args);
239239
}
240240

241+
public void visitMatchFail(JCMatchFail tree) {
242+
}
243+
241244
public void visitContinue(JCContinue tree) {
242245
}
243246

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java

+5
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ public void visitMatch(JCMatch tree) {
279279
result = tree;
280280
}
281281

282+
@Override
283+
public void visitMatchFail(JCMatchFail tree) {
284+
result = tree;
285+
}
286+
282287
public void visitContinue(JCContinue tree) {
283288
result = tree;
284289
}

0 commit comments

Comments
 (0)