Skip to content

Commit

Permalink
Attempting to add match-failed + partial deconstructors. No support f…
Browse files Browse the repository at this point in the history
…or partial deconstructor exhaustiveness groups yet.
  • Loading branch information
lahodaj committed Feb 7, 2025
1 parent b314dba commit f64ab0a
Show file tree
Hide file tree
Showing 18 changed files with 444 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@
*
* @since 23
*/
@PreviewFeature(feature= PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
//TODO: maybe MatchSuccessTree?
public interface MatchTree extends StatementTree {

/**
* Returns the expression for this {@code match} statement.
*
* @return the expression
*/
@PreviewFeature(feature= PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
List<? extends ExpressionTree> getArguments();
}
12 changes: 11 additions & 1 deletion src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,17 @@ public enum Kind {
* @since 23
*/
@PreviewFeature(feature=PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
MATCH(MatchTree.class);
MATCH(MatchTree.class), //TODO: maybe MATCH_SUCCESS

/**
* Used for instances of {@link MatchFailTree}.
*
* @since 25
*/
@PreviewFeature(feature=PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
MATCH_FAILED(MatchFailTree.class),

;

Kind(Class<? extends Tree> intf) {
associatedInterface = intf;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

package com.sun.source.tree;

import jdk.internal.javac.PreviewFeature;

/**
* A visitor of trees, in the style of the visitor design pattern.
* Classes implementing this interface are used to operate
Expand Down Expand Up @@ -629,4 +631,14 @@ public interface TreeVisitor<R,P> {
* @return a result value
*/
R visitMatchStatement(MatchTree node, P p);

/**
* Visits an {@code MatchFailTree} node.
* @param node the node being visited
* @param p a parameter value
* @return a result value
* @since 25
*/
@PreviewFeature(feature=PreviewFeature.Feature.PATTERN_DECLARATIONS, reflective=true)
R visitMatchFailStatement(MatchFailTree node, P p);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1085,5 +1085,18 @@ public R visitMatchStatement(MatchTree node, P p) {
return defaultAction(node, p);
}

/**
* {@inheritDoc}
*
* @implSpec This implementation calls {@code defaultAction}.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of {@code defaultAction}
*/
@Override
public R visitMatchFailStatement(MatchFailTree node, P p) {
return defaultAction(node, p);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1240,4 +1240,19 @@ public R visitYield(YieldTree node, P p) {
public R visitMatchStatement(MatchTree node, P p) {
return scan(node.getArguments(), p);
}

/**
* {@inheritDoc}
*
* @implSpec This implementation scans the children in left to right order.
*
* @param node {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of scanning
*/
@Override
public R visitMatchFailStatement(MatchFailTree node, P p) {
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,10 @@ public static EnumSet<Flag> asFlagSet(long flags) {
*/
public static final long THROWS = 1L<<47;

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

/**
* Flag that marks a synthetic method body for a lambda expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1200,12 +1200,16 @@ public void visitMethodDef(JCMethodDecl tree) {
}
}

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

if (m.isDeconstructor()) {
m.patternFlags.add(PatternFlags.DECONSTRUCTOR);
if ((tree.mods.flags & Flags.PARTIAL) == 0) {
m.patternFlags.add(PatternFlags.TOTAL);
}
}

// annotation method checks
Expand Down Expand Up @@ -2457,6 +2461,14 @@ public void visitMatch(JCMatch tree) {
result = null;
}

@Override
public void visitMatchFail(JCMatchFail tree) {
if ((env.enclMethod.sym.flags_field & Flags.PARTIAL) == 0) {
log.error(tree.pos(), Errors.UnmarkedPartialDeconstructor);
}
result = null;
}

public void visitTypeTestStatement(JCInstanceOfStatement tree) {
attribExpr(tree.expr, env);
attribExpr(tree.pattern, env);
Expand Down Expand Up @@ -4647,7 +4659,11 @@ private List<MethodSymbol> candidatesWithArity(Type site, int nestedPatternCount
.collect(List.collector());

PatternType pt = new PatternType(recordComponents, syms.voidType, syms.methodClass);
patternDeclarations = patternDeclarations.prepend(new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, pt, site.tsym));
MethodSymbol synthetized = new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, pt, site.tsym);

synthetized.patternFlags.add(PatternFlags.DECONSTRUCTOR);
synthetized.patternFlags.add(PatternFlags.TOTAL);
patternDeclarations = patternDeclarations.prepend(synthetized);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ private void clearPendingExits(boolean inMethod) {
while (exits.nonEmpty()) {
PendingExit exit = exits.head;
exits = exits.tail;
Assert.check((inMethod && (exit.tree.hasTag(RETURN) || exit.tree.hasTag(MATCH))) ||
Assert.check((inMethod && (exit.tree.hasTag(RETURN) || exit.tree.hasTag(MATCH) || exit.tree.hasTag(MATCHFAIL))) ||
log.hasErrorOn(exit.tree.pos()));
}
}
Expand Down Expand Up @@ -725,6 +725,10 @@ public void visitTypeTestStatement(JCInstanceOfStatement tree) {
alive = alive.or(resolveBreaks(tree, prevPendingExits));
}

public void visitMatchFail(JCMatchFail tree) {
recordExit(new PendingExit(tree));
}

public void visitForeachLoop(JCEnhancedForLoop tree) {
visitVarDef(tree.var);
ListBuffer<PendingExit> prevPendingExits = pendingExits;
Expand Down Expand Up @@ -827,6 +831,10 @@ private boolean exhausts(JCExpression selector, List<JCCase> cases) {

for (var l : c.labels) {
if (l instanceof JCPatternCaseLabel patternLabel) {
if (patternLabel.pat instanceof JCRecordPattern rec &&
!rec.patternDeclaration.patternFlags.contains(PatternFlags.TOTAL)) {
continue;
}
for (Type component : components(selector.type)) {
patternSet.add(makePatternDescription(component, patternLabel.pat));
}
Expand Down Expand Up @@ -1585,6 +1593,7 @@ else if ((tree.sym.flags() & (BLOCK | STATIC)) != BLOCK)
if (!(exit instanceof ThrownPendingExit)) {
Assert.check(exit.tree.hasTag(RETURN) ||
exit.tree.hasTag(MATCH) ||
exit.tree.hasTag(MATCHFAIL) ||
log.hasErrorOn(exit.tree.pos()));
} else {
// uncaught throws will be reported later
Expand Down Expand Up @@ -1846,6 +1855,10 @@ public void visitMatch(JCMatch tree) {
recordExit(new PendingExit(tree));
}

public void visitMatchFail(JCMatchFail tree) {
recordExit(new PendingExit(tree));
}

public void visitThrow(JCThrow tree) {
scan(tree.expr);
Symbol sym = TreeInfo.symbol(tree.expr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCLambda;
import com.sun.tools.javac.tree.JCTree.JCMatchFail;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCNewClass;
import com.sun.tools.javac.tree.JCTree.JCPattern;
Expand Down Expand Up @@ -135,6 +136,7 @@ public static TransPatterns instance(Context context) {
private final Symtab syms;
private final Attr attr;
private final Resolve rs;
private final TypeEnvs typeEnvs;
private final Types types;
private final Operators operators;
private final Names names;
Expand Down Expand Up @@ -196,6 +198,7 @@ protected TransPatterns(Context context) {
syms = Symtab.instance(context);
attr = Attr.instance(context);
rs = Resolve.instance(context);
typeEnvs = TypeEnvs.instance(context);
make = TreeMaker.instance(context);
types = Types.instance(context);
operators = Operators.instance(context);
Expand Down Expand Up @@ -1043,6 +1046,11 @@ public void visitMatch(JCMatch tree) {
result = make.at(tree.pos).Block(0, stats.toList());
}

@Override
public void visitMatchFail(JCMatchFail tree) {
result = make.at(tree.pos).Return(makeNull());
}

private class PrimitiveGenerator extends Types.SignatureGenerator {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2949,6 +2949,20 @@ List<JCStatement> blockStatement() {
List<JCExpression> args = arguments();
accept(SEMI);
return List.of(toP(F.at(pos).Match(name, args)));
} else if (next.kind == SUB) {
Token nextNext = S.token(2);
if (nextNext.kind == IDENTIFIER) {
if (nextNext.name().contentEquals("fail")) {
checkSourceLevel(Feature.PATTERN_DECLARATIONS);
nextToken();
nextToken();
nextToken();
accept(LPAREN);
accept(RPAREN);
accept(SEMI);
return List.of(toP(F.at(pos).MatchFail()));
}
}
}
} else
if (token.name() == names.yield && allowYieldStatement) {
Expand Down Expand Up @@ -3627,6 +3641,7 @@ protected JCModifiers modifiersOpt(JCModifiers partial) {
case STRICTFP : flag = Flags.STRICTFP; break;
case MONKEYS_AT : flag = Flags.ANNOTATION; break;
case DEFAULT : flag = Flags.DEFAULT; break;
case CASE : flag = Flags.PARTIAL; break;
case ERROR : flag = 0; nextToken(); break;
case IDENTIFIER : {
if (isNonSealedClassStart(false)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,9 @@ compiler.err.missing.ret.stmt=\
compiler.err.missing.match.stmt=\
missing match statement

compiler.err.missing.match.stmt=\
missing match statement

# 0: type
compiler.misc.missing.ret.val=\
missing return value
Expand Down Expand Up @@ -4290,3 +4293,6 @@ compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=\
compiler.err.enclosing.class.type.non.denotable=\
enclosing class type: {0}\n\
is non-denotable, try casting to a denotable type

compiler.err.unmarked.partial.deconstructor=\
deconstructor not marked as partial, match-fail illegal
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ public enum Tag {
*/
MATCH,

/** Match fail statements, of type MatchFail.
*/
MATCHFAIL,

/** Method invocation expressions, of type Apply.
*/
APPLY,
Expand Down Expand Up @@ -1808,6 +1812,28 @@ public Tag getTag() {
}
}

/**
* The match-fail statement
*/
public static class JCMatchFail extends JCStatement implements MatchFailTree {

protected JCMatchFail() {
}
@Override
public void accept(Visitor v) { v.visitMatchFail(this); }

@DefinedBy(Api.COMPILER_TREE)
public Kind getKind() { return Kind.MATCH_FAILED; }
@Override @DefinedBy(Api.COMPILER_TREE)
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitMatchFailStatement(this, d);
}
@Override
public Tag getTag() {
return MATCHFAIL;
}
}

/**
* A continue of a loop.
*/
Expand Down Expand Up @@ -3631,6 +3657,7 @@ public abstract static class Visitor {
public void visitBreak(JCBreak that) { visitTree(that); }
public void visitYield(JCYield that) { visitTree(that); }
public void visitMatch(JCMatch that) { visitTree(that); }
public void visitMatchFail(JCMatchFail that) { visitTree(that); }
public void visitContinue(JCContinue that) { visitTree(that); }
public void visitReturn(JCReturn that) { visitTree(that); }
public void visitThrow(JCThrow that) { visitTree(that); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ public JCTree visitMatchStatement(MatchTree node, P p) {
return M.at(t.pos).Match(t.clazz, args);
}

@DefinedBy(Api.COMPILER_TREE)
public JCTree visitMatchFailStatement(MatchFailTree node, P p) {
JCMatchFail t = (JCMatchFail) node;

return M.at(t.pos).MatchFail();
}

@DefinedBy(Api.COMPILER_TREE)
public JCTree visitCase(CaseTree node, P p) {
JCCase t = (JCCase) node;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,12 @@ public JCMatch Match(Name clazz, List<JCExpression> args) {
return tree;
}

public JCMatchFail MatchFail() {
JCMatchFail tree = new JCMatchFail();
tree.pos = pos;
return tree;
}

public JCMethodInvocation Apply(List<JCExpression> typeargs,
JCExpression fn,
List<JCExpression> args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ public void visitMatch(JCMatch tree) {
scan(tree.args);
}

public void visitMatchFail(JCMatchFail tree) {
}

public void visitContinue(JCContinue tree) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ public void visitMatch(JCMatch tree) {
result = tree;
}

@Override
public void visitMatchFail(JCMatchFail tree) {
result = tree;
}

public void visitContinue(JCContinue tree) {
result = tree;
}
Expand Down
Loading

0 comments on commit f64ab0a

Please sign in to comment.