Skip to content

Commit

Permalink
Separate PatternType from MethodType (#13)
Browse files Browse the repository at this point in the history
* An experiment on PatternType.

* Fixing test.

* Fixing build.

* Fixing tests.

* Cleanup.
  • Loading branch information
lahodaj authored Jan 17, 2025
1 parent 77a1ffe commit f0ec972
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ public String visitMethodType(MethodType t, Locale locale) {
visit(t.restype, locale);
}

@Override
public String visitPatternType(PatternType t, Locale locale) {
return "(" + printMethodArgs(t.bindingtypes, false, locale) + ")" +
visit(t.restype, locale);
}

@Override
public String visitPackageType(PackageType t, Locale locale) {
return t.tsym.getQualifiedName().toString();
Expand Down
122 changes: 113 additions & 9 deletions src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
Original file line number Diff line number Diff line change
Expand Up @@ -285,15 +285,12 @@ protected boolean needsStripping() {
@Override
public Type visitMethodType(MethodType t, S s) {
List<Type> argtypes = t.argtypes;
List<Type> bindingtypes = t.bindingtypes;
Type restype = t.restype;
List<Type> thrown = t.thrown;
List<Type> bindingtypes1 = bindingtypes != null ? visit(bindingtypes, s) : null;
List<Type> argtypes1 = visit(argtypes, s);
Type restype1 = visit(restype, s);
List<Type> thrown1 = visit(thrown, s);
if (argtypes1 == argtypes &&
bindingtypes1 == bindingtypes &&
restype1 == restype &&
thrown1 == thrown) return t;
else {
Expand All @@ -303,7 +300,6 @@ protected boolean needsStripping() {
return true;
}
};
methodType.bindingtypes = bindingtypes1;
return methodType;
}
}
Expand All @@ -312,6 +308,22 @@ protected boolean needsStripping() {
public Type visitForAll(ForAll t, S s) {
return visit(t.qtype, s);
}

@Override
public Type visitPatternType(PatternType t, S s) {
List<Type> bindingtypes = t.bindingtypes;
List<Type> bindingtypes1 = visit(bindingtypes, s);
if (bindingtypes1 == bindingtypes) return t;
else {
PatternType patternType = new PatternType(bindingtypes1, /*XXX*/t.restype, t.tsym) {
@Override
protected boolean needsStripping() {
return true;
}
};
return patternType;
}
}
}

/** map a type function over all immediate descendants of this type
Expand Down Expand Up @@ -722,6 +734,8 @@ public static List<Type> filter(List<Type> ts, Predicate<Type> tf) {
*/
public MethodType asMethodType() { throw new AssertionError(); }

public PatternType asPatternType() { throw new AssertionError(); }

/** Complete loading all classes in this type.
*/
public void complete() {}
Expand Down Expand Up @@ -1479,7 +1493,6 @@ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
public static class MethodType extends Type implements ExecutableType, LoadableConstant {

public List<Type> argtypes;
public List<Type> bindingtypes;
public Type restype;
public List<Type> thrown;

Expand Down Expand Up @@ -1528,7 +1541,7 @@ public String toString() {
public List<Type> getParameterTypes() { return argtypes; }

@DefinedBy(Api.LANGUAGE_MODEL)
public List<Type> getBindingTypes() { return bindingtypes; }
public List<Type> getBindingTypes() { return List.nil(); }

@DefinedBy(Api.LANGUAGE_MODEL)
public Type getReturnType() { return restype; }
Expand All @@ -1542,7 +1555,6 @@ public Type getReceiverType() {
public boolean isErroneous() {
return
isErroneous(argtypes) ||
bindingtypes != null && isErroneous(bindingtypes) ||
restype != null && restype.isErroneous();
}

Expand All @@ -1560,8 +1572,6 @@ public boolean contains(Type elem) {
public void complete() {
for (List<Type> l = argtypes; l.nonEmpty(); l = l.tail)
l.head.complete();
for (List<Type> l = bindingtypes; l.nonEmpty(); l = l.tail)
l.head.complete();
restype.complete();
recvtype.complete();
for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
Expand Down Expand Up @@ -1923,6 +1933,99 @@ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
}
}

public static class PatternType extends Type implements ExecutableType {
public List<Type> bindingtypes;
public Type restype;

public PatternType(List<Type> bindingtypes,
Type restype, //TODO:
TypeSymbol methodClass) {
super(methodClass, List.nil());
this.bindingtypes = bindingtypes;
this.restype = restype;
}

@Override
public TypeTag getTag() {
return TypeTag.PATTERN;
}

public <R,S> R accept(Type.Visitor<R,S> v, S s) {
return v.visitPatternType(this, s);
}

/** The Java source which this type represents.
*
* XXX 06/09/99 iris This isn't correct Java syntax, but it probably
* should be.
*/
@DefinedBy(Api.LANGUAGE_MODEL)
public String toString() {
StringBuilder sb = new StringBuilder();
appendAnnotationsString(sb);
sb.append("(out");
sb.append(bindingtypes);
sb.append(')');
return sb.toString();
}

@DefinedBy(Api.LANGUAGE_MODEL)
public List<Type> getParameterTypes() { return List.nil(); }

@DefinedBy(Api.LANGUAGE_MODEL)
public List<Type> getBindingTypes() { return bindingtypes; }

@DefinedBy(Api.LANGUAGE_MODEL)
public Type getReturnType() { return restype; }
@DefinedBy(Api.LANGUAGE_MODEL)
public Type getReceiverType() {
return Type.noType;
}
@DefinedBy(Api.LANGUAGE_MODEL)
public List<Type> getThrownTypes() { return List.nil(); }

@Override
public PatternType asPatternType() { return this; }

public boolean isErroneous() {
return
bindingtypes != null && isErroneous(bindingtypes);
}

@Override
public int poolTag() {
return ClassFile.CONSTANT_MethodType; //TODO
}

public boolean contains(Type elem) {
return elem.equalsIgnoreMetadata(this);
}

public void complete() {
for (List<Type> l = bindingtypes; l.nonEmpty(); l = l.tail)
l.head.complete();
}

@DefinedBy(Api.LANGUAGE_MODEL)
public List<TypeVar> getTypeVariables() {
return List.nil();
}

public TypeSymbol asElement() {
return null;
}

@DefinedBy(Api.LANGUAGE_MODEL)
public TypeKind getKind() {
return TypeKind.EXECUTABLE;
}

@DefinedBy(Api.LANGUAGE_MODEL)
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitExecutable(this, p);
}
}

/** A class for inference variables, for use during method/diamond type
* inference. An inference variable has upper/lower bounds and a set
* of equality constraints. Such bounds are set during subtyping, type-containment,
Expand Down Expand Up @@ -2444,6 +2547,7 @@ public interface Visitor<R,S> {
R visitWildcardType(WildcardType t, S s);
R visitArrayType(ArrayType t, S s);
R visitMethodType(MethodType t, S s);
R visitPatternType(PatternType t, S s);
R visitPackageType(PackageType t, S s);
R visitModuleType(ModuleType t, S s);
R visitTypeVar(TypeVar t, S s);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,12 @@ public Type visitMethodType(MethodType t, List<TypeCompound> s) {
return t;
}

@Override
public Type visitPatternType(Type.PatternType t, List<TypeCompound> s) {
// Impossible?
return t;
}

@Override
public Type visitPackageType(PackageType t, List<TypeCompound> s) {
// Impossible?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public enum TypeTag {
/** The tag of all (monomorphic) method types.
*/
METHOD,
PATTERN,

/** The tag of all package "types".
*/
Expand Down
27 changes: 20 additions & 7 deletions src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,11 @@ public Boolean visitMethodType(MethodType t, Type s) {
return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType());
}

@Override
public Boolean visitPatternType(PatternType t, Type s) {
return hasSameArgs(t, s);
}

@Override
public Boolean visitPackageType(PackageType t, Type s) {
return t == s;
Expand Down Expand Up @@ -3299,12 +3304,16 @@ public Boolean visitType(Type t, Type s) {
@Override
public Boolean visitMethodType(MethodType t, Type s) {
if (s.hasTag(METHOD)) {
if (t.bindingtypes != null && t.bindingtypes.size() > 0) return containsTypeEquivalent(t.bindingtypes, s.getBindingTypes());
else return containsTypeEquivalent(t.argtypes, s.getParameterTypes());
return containsTypeEquivalent(t.argtypes, s.getParameterTypes());
}
return false;
}

@Override
public Boolean visitPatternType(PatternType t, Type s) {
return containsTypeEquivalent(t.bindingtypes, s.getBindingTypes());
}

@Override
public Boolean visitForAll(ForAll t, Type s) {
if (!s.hasTag(FORALL))
Expand Down Expand Up @@ -4941,6 +4950,7 @@ public abstract static class DefaultTypeVisitor<R,S> implements Type.Visitor<R,S
public R visitWildcardType(WildcardType t, S s) { return visitType(t, s); }
public R visitArrayType(ArrayType t, S s) { return visitType(t, s); }
public R visitMethodType(MethodType t, S s) { return visitType(t, s); }
public R visitPatternType(PatternType t, S s) { return visitType(t, s); }
public R visitPackageType(PackageType t, S s) { return visitType(t, s); }
public R visitModuleType(ModuleType t, S s) { return visitType(t, s); }
public R visitTypeVar(TypeVar t, S s) { return visitType(t, s); }
Expand Down Expand Up @@ -5200,11 +5210,7 @@ public void assembleSig(Type type) {
case METHOD:
MethodType mt = (MethodType) type;
append('(');
if (mt.bindingtypes != null && mt.bindingtypes.size() > 0) {
assembleSig(mt.bindingtypes);
} else {
assembleSig(mt.argtypes);
}
assembleSig(mt.argtypes);
append(')');
assembleSig(mt.restype);
if (hasTypeVar(mt.thrown)) {
Expand All @@ -5214,6 +5220,13 @@ public void assembleSig(Type type) {
}
}
break;
case PATTERN:
PatternType pt = (PatternType) type;
append('(');
assembleSig(pt.bindingtypes);
append(')');
assembleSig(pt.restype);
break;
case WILDCARD: {
Type.WildcardType ta = (Type.WildcardType) type;
switch (ta.kind) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.ANNOTATION;
import static com.sun.tools.javac.code.Flags.BLOCK;
import static com.sun.tools.javac.code.Flags.PATTERN;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.TypeTag.*;
Expand Down Expand Up @@ -4592,9 +4593,8 @@ private List<MethodSymbol> patternDeclarationCandidatesWithArity(Type site, int
.map(rc -> types.memberType(site, rc))
.collect(List.collector());

MethodType mt = new MethodType(List.nil(), syms.voidType, List.nil(), syms.methodClass);
mt.bindingtypes = recordComponents;
patternDeclarations = patternDeclarations.prepend(new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, mt, site.tsym));
PatternType pt = new PatternType(recordComponents, syms.voidType, syms.methodClass);
patternDeclarations = patternDeclarations.prepend(new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, pt, site.tsym));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3592,7 +3592,7 @@ public PatternDescription makePatternDescription(Type selectorType, JCPattern pa

MethodSymbol patternDeclaration = ((JCRecordPattern) pattern).patternDeclaration;
if (!record.type.isErroneous() && patternDeclaration != null) {
componentTypes = patternDeclaration.type.asMethodType().bindingtypes.toArray(Type[]::new);
componentTypes = patternDeclaration.type.asPatternType().bindingtypes.toArray(Type[]::new);
}
else {
componentTypes = record.nested.map(t -> types.createErrorType(t.type)).toArray(s -> new Type[s]);;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2653,12 +2653,12 @@ public void visitMethodDef(JCMethodDecl tree) {

m.params = m.params.prepend(implicitThisParam.sym);
Type olderasure = m.erasure(types);
//create an external type for the pattern:
var mt = new MethodType(
olderasure.getParameterTypes().prepend(tree.sym.owner.type),
olderasure.getReturnType(),
olderasure.getThrownTypes(),
syms.methodClass);
mt.bindingtypes = olderasure.getBindingTypes();

m.erasure_field = mt;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,20 @@ Type signature(MethodSymbol msym,
}
thrownbuf.append(exc);
}
MethodType mtype = new MethodType(argbuf.toList(),
restype,
thrownbuf.toList(),
syms.methodClass);
if (bindings != null) {
mtype.bindingtypes = bindingsbuf.toList();
}
if (msym.isPattern()) {
Assert.check(params.isEmpty());
return new PatternType(bindingsbuf.toList(), restype, syms.methodClass);
} else {
Assert.check(bindings == null);
MethodType mtype = new MethodType(argbuf.toList(),
restype,
thrownbuf.toList(),
syms.methodClass);

mtype.recvtype = recvtype;
mtype.recvtype = recvtype;

return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype);
return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype);
}
}

/* ********************************************************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ protected void read(Symbol sym, int attrLen) {

// todo: check if special handling is needed similar to generic methods for binding types

msym.type.asMethodType().bindingtypes = patternType.getParameterTypes();
msym.type = new PatternType(patternType.getParameterTypes(), syms.voidType, syms.methodClass);
}
}
},
Expand Down Expand Up @@ -2776,7 +2776,7 @@ MethodSymbol readMethod() {
}

void validateMethodType(Name name, Type t) {
if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL)) ||
if ((!t.hasTag(TypeTag.METHOD) && !t.hasTag(TypeTag.FORALL) && !t.hasTag(TypeTag.PATTERN)) ||
(name == names.init && !t.getReturnType().hasTag(TypeTag.VOID))) {
throw badClassFile("method.descriptor.invalid", name);
}
Expand Down
Loading

0 comments on commit f0ec972

Please sign in to comment.