Skip to content

Commit e13c919

Browse files
authored
Attempting to add match-failed + partial deconstructors. No support for partial deconstructor exhaustiveness groups yet. (#15)
* Attempting to add match-failed + partial deconstructors. No support for partial deconstructor exhaustiveness groups yet. * Error recovery.
1 parent b314dba commit e13c919

File tree

18 files changed

+445
-8
lines changed

18 files changed

+445
-8
lines changed

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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 11 additions & 1 deletion
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

Lines changed: 12 additions & 0 deletions
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

Lines changed: 13 additions & 0 deletions
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

Lines changed: 15 additions & 0 deletions
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

Lines changed: 3 additions & 2 deletions
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

Lines changed: 17 additions & 1 deletion
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

Lines changed: 15 additions & 1 deletion
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,11 @@ 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 != null &&
836+
!rec.patternDeclaration.patternFlags.contains(PatternFlags.TOTAL)) {
837+
continue;
838+
}
830839
for (Type component : components(selector.type)) {
831840
patternSet.add(makePatternDescription(component, patternLabel.pat));
832841
}
@@ -1585,6 +1594,7 @@ else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
15851594
if (!(exit instanceof ThrownPendingExit)) {
15861595
Assert.check(exit.tree.hasTag(RETURN) ||
15871596
exit.tree.hasTag(MATCH) ||
1597+
exit.tree.hasTag(MATCHFAIL) ||
15881598
log.hasErrorOn(exit.tree.pos()));
15891599
} else {
15901600
// uncaught throws will be reported later
@@ -1846,6 +1856,10 @@ public void visitMatch(JCMatch tree) {
18461856
recordExit(new PendingExit(tree));
18471857
}
18481858

1859+
public void visitMatchFail(JCMatchFail tree) {
1860+
recordExit(new PendingExit(tree));
1861+
}
1862+
18491863
public void visitThrow(JCThrow tree) {
18501864
scan(tree.expr);
18511865
Symbol sym = TreeInfo.symbol(tree.expr);

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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 15 additions & 0 deletions
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)) {

0 commit comments

Comments
 (0)