Skip to content

Commit 8370156

Browse files
mcimadamorepull[bot]
authored andcommitted
8335159: Move method reference to lambda desugaring before Lower
8336320: NullPointerException: Cannot invoke Type.getTag because type is null after JDK-8334037 Reviewed-by: jlahoda, vromero
1 parent 0f04a62 commit 8370156

File tree

3 files changed

+307
-353
lines changed

3 files changed

+307
-353
lines changed

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

Lines changed: 0 additions & 335 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.util.stream.Collectors;
3030

3131
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
32-
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
3332
import com.sun.tools.javac.code.*;
3433
import com.sun.tools.javac.code.Kinds.KindSelector;
3534
import com.sun.tools.javac.code.Scope.WriteableScope;
@@ -39,7 +38,6 @@
3938
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
4039
import com.sun.tools.javac.resources.CompilerProperties.Notes;
4140
import com.sun.tools.javac.tree.*;
42-
import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
4341
import com.sun.tools.javac.util.*;
4442
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
4543
import com.sun.tools.javac.util.List;
@@ -67,8 +65,6 @@
6765
import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;
6866
import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
6967

70-
import javax.lang.model.type.TypeKind;
71-
7268
import static com.sun.tools.javac.tree.JCTree.Tag.*;
7369

7470
/** This pass translates away some syntactic sugar: inner classes,
@@ -3903,337 +3899,6 @@ public void visitLambda(JCLambda tree) {
39033899
result = tree;
39043900
}
39053901

3906-
@Override
3907-
public void visitReference(JCMemberReference tree) {
3908-
if (needsConversionToLambda(tree)) {
3909-
// Convert to a lambda, and process as such
3910-
MemberReferenceToLambda conv = new MemberReferenceToLambda(tree);
3911-
result = translate(conv.lambda());
3912-
} else {
3913-
super.visitReference(tree);
3914-
}
3915-
}
3916-
// where
3917-
boolean needsVarArgsConversion(JCMemberReference tree) {
3918-
return tree.varargsElement != null;
3919-
}
3920-
3921-
/**
3922-
* @return Is this an array operation like clone()
3923-
*/
3924-
boolean isArrayOp(JCMemberReference tree) {
3925-
return tree.sym.owner == syms.arrayClass;
3926-
}
3927-
3928-
boolean receiverAccessible(JCMemberReference tree) {
3929-
//hack needed to workaround 292 bug (7087658)
3930-
//when 292 issue is fixed we should remove this and change the backend
3931-
//code to always generate a method handle to an accessible method
3932-
return tree.ownerAccessible;
3933-
}
3934-
3935-
/**
3936-
* Erasure destroys the implementation parameter subtype
3937-
* relationship for intersection types.
3938-
* Have similar problems for union types too.
3939-
*/
3940-
boolean interfaceParameterIsIntersectionOrUnionType(JCMemberReference tree) {
3941-
List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
3942-
for (; tl.nonEmpty(); tl = tl.tail) {
3943-
Type pt = tl.head;
3944-
if (isIntersectionOrUnionType(pt))
3945-
return true;
3946-
}
3947-
return false;
3948-
}
3949-
3950-
boolean isIntersectionOrUnionType(Type t) {
3951-
switch (t.getKind()) {
3952-
case INTERSECTION:
3953-
case UNION:
3954-
return true;
3955-
case TYPEVAR:
3956-
TypeVar tv = (TypeVar) t;
3957-
return isIntersectionOrUnionType(tv.getUpperBound());
3958-
}
3959-
return false;
3960-
}
3961-
3962-
private boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage(Symbol targetReference,
3963-
Symbol currentClass) {
3964-
return ((targetReference.flags() & PROTECTED) != 0 &&
3965-
targetReference.packge() != currentClass.packge());
3966-
}
3967-
3968-
/**
3969-
* This method should be called only when target release <= 14
3970-
* where LambdaMetaFactory does not spin nestmate classes.
3971-
*
3972-
* This method should be removed when --release 14 is not supported.
3973-
*/
3974-
boolean isPrivateInOtherClass(JCMemberReference tree) {
3975-
assert !target.runtimeUseNestAccess();
3976-
return (tree.sym.flags() & PRIVATE) != 0 &&
3977-
!types.isSameType(
3978-
types.erasure(tree.sym.enclClass().asType()),
3979-
types.erasure(currentClass.asType()));
3980-
}
3981-
3982-
/**
3983-
* Does this reference need to be converted to a lambda
3984-
* (i.e. var args need to be expanded or "super" is used)
3985-
*/
3986-
boolean needsConversionToLambda(JCMemberReference tree) {
3987-
return interfaceParameterIsIntersectionOrUnionType(tree) ||
3988-
tree.hasKind(ReferenceKind.SUPER) ||
3989-
needsVarArgsConversion(tree) ||
3990-
isArrayOp(tree) ||
3991-
(!target.runtimeUseNestAccess() && isPrivateInOtherClass(tree)) ||
3992-
isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, currentClass) ||
3993-
!receiverAccessible(tree) ||
3994-
(tree.getMode() == ReferenceMode.NEW &&
3995-
tree.kind != ReferenceKind.ARRAY_CTOR &&
3996-
(tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner()));
3997-
}
3998-
3999-
/**
4000-
* Converts a method reference which cannot be used directly into a lambda
4001-
*/
4002-
private class MemberReferenceToLambda {
4003-
4004-
private final JCMemberReference tree;
4005-
private final ListBuffer<JCExpression> args = new ListBuffer<>();
4006-
private final ListBuffer<JCVariableDecl> params = new ListBuffer<>();
4007-
private final MethodSymbol owner = new MethodSymbol(0, names.empty, Type.noType, currentClass);
4008-
4009-
private JCExpression receiverExpression = null;
4010-
4011-
MemberReferenceToLambda(JCMemberReference tree) {
4012-
this.tree = tree;
4013-
}
4014-
4015-
JCExpression lambda() {
4016-
int prevPos = make.pos;
4017-
try {
4018-
make.at(tree);
4019-
4020-
//body generation - this can be either a method call or a
4021-
//new instance creation expression, depending on the member reference kind
4022-
VarSymbol rcvr = addParametersReturnReceiver();
4023-
JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
4024-
? expressionInvoke(rcvr)
4025-
: expressionNew();
4026-
4027-
JCLambda slam = make.Lambda(params.toList(), expr);
4028-
slam.target = tree.target;
4029-
slam.type = tree.type;
4030-
slam.pos = tree.pos;
4031-
slam.wasMethodReference = true;
4032-
if (receiverExpression != null) {
4033-
// use a let expression so that the receiver expression is evaluated eagerly
4034-
return make.at(tree.pos).LetExpr(
4035-
make.VarDef(rcvr, translate(receiverExpression)), slam).setType(tree.type);
4036-
} else {
4037-
return slam;
4038-
}
4039-
} finally {
4040-
make.at(prevPos);
4041-
}
4042-
}
4043-
4044-
/**
4045-
* Generate the parameter list for the converted member reference.
4046-
*
4047-
* @return The receiver variable symbol, if any
4048-
*/
4049-
VarSymbol addParametersReturnReceiver() {
4050-
Type samDesc = types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
4051-
List<Type> samPTypes = samDesc.getParameterTypes();
4052-
List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
4053-
4054-
// Determine the receiver, if any
4055-
VarSymbol rcvr;
4056-
switch (tree.kind) {
4057-
case BOUND:
4058-
// The receiver is explicit in the method reference
4059-
rcvr = new VarSymbol(SYNTHETIC, names.fromString("rec$"), tree.getQualifierExpression().type, owner);
4060-
rcvr.pos = tree.pos;
4061-
receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
4062-
break;
4063-
case UNBOUND:
4064-
// The receiver is the first parameter, extract it and
4065-
// adjust the SAM and unerased type lists accordingly
4066-
rcvr = addParameter("rec$", samDesc.getParameterTypes().head, false);
4067-
samPTypes = samPTypes.tail;
4068-
descPTypes = descPTypes.tail;
4069-
break;
4070-
default:
4071-
rcvr = null;
4072-
break;
4073-
}
4074-
List<Type> implPTypes = tree.sym.type.getParameterTypes();
4075-
int implSize = implPTypes.size();
4076-
int samSize = samPTypes.size();
4077-
// Last parameter to copy from referenced method, exclude final var args
4078-
int last = needsVarArgsConversion(tree) ? implSize - 1 : implSize;
4079-
4080-
// Failsafe -- assure match-up
4081-
boolean checkForIntersection = tree.varargsElement != null || implSize == descPTypes.size();
4082-
4083-
// Use parameter types of the implementation method unless the unerased
4084-
// SAM parameter type is an intersection type, in that case use the
4085-
// erased SAM parameter type so that the supertype relationship
4086-
// the implementation method parameters is not obscured.
4087-
// Note: in this loop, the lists implPTypes, samPTypes, and descPTypes
4088-
// are used as pointers to the current parameter type information
4089-
// and are thus not usable afterwards.
4090-
for (int i = 0; implPTypes.nonEmpty() && i < last; ++i) {
4091-
// By default use the implementation method parameter type
4092-
Type parmType = implPTypes.head;
4093-
if (checkForIntersection) {
4094-
if (descPTypes.head.getKind() == TypeKind.INTERSECTION) {
4095-
parmType = samPTypes.head;
4096-
}
4097-
// If the unerased parameter type is a type variable whose
4098-
// bound is an intersection (eg. <T extends A & B>) then
4099-
// use the SAM parameter type
4100-
if (descPTypes.head.getKind() == TypeKind.TYPEVAR) {
4101-
TypeVar tv = (TypeVar) descPTypes.head;
4102-
if (tv.getUpperBound().getKind() == TypeKind.INTERSECTION) {
4103-
parmType = samPTypes.head;
4104-
}
4105-
}
4106-
}
4107-
addParameter("x$" + i, parmType, true);
4108-
4109-
// Advance to the next parameter
4110-
implPTypes = implPTypes.tail;
4111-
samPTypes = samPTypes.tail;
4112-
descPTypes = descPTypes.tail;
4113-
}
4114-
// Flatten out the var args
4115-
for (int i = last; i < samSize; ++i) {
4116-
addParameter("xva$" + i, tree.varargsElement, true);
4117-
}
4118-
4119-
return rcvr;
4120-
}
4121-
4122-
private JCExpression makeReceiver(VarSymbol rcvr) {
4123-
if (rcvr == null) return null;
4124-
JCExpression rcvrExpr = make.Ident(rcvr);
4125-
boolean protAccess =
4126-
isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, currentClass);
4127-
Type rcvrType = tree.ownerAccessible && !protAccess ? tree.sym.enclClass().type
4128-
: tree.expr.type;
4129-
if (rcvrType == syms.arrayClass.type) {
4130-
// Map the receiver type to the actually type, not just "array"
4131-
rcvrType = tree.getQualifierExpression().type;
4132-
}
4133-
if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
4134-
rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
4135-
}
4136-
return rcvrExpr;
4137-
}
4138-
4139-
/**
4140-
* determine the receiver of the method call - the receiver can
4141-
* be a type qualifier, the synthetic receiver parameter or 'super'.
4142-
*/
4143-
private JCExpression expressionInvoke(VarSymbol rcvr) {
4144-
JCExpression qualifier =
4145-
(rcvr != null) ?
4146-
makeReceiver(rcvr) :
4147-
tree.getQualifierExpression();
4148-
4149-
//create the qualifier expression
4150-
JCFieldAccess select = make.Select(qualifier, tree.sym.name);
4151-
select.sym = tree.sym;
4152-
select.type = tree.sym.erasure(types);
4153-
4154-
//create the method call expression
4155-
JCExpression apply = make.Apply(List.nil(), select,
4156-
convertArgs(tree.sym, args.toList(), tree.varargsElement)).
4157-
setType(tree.sym.erasure(types).getReturnType());
4158-
4159-
apply = transTypes.coerce(attrEnv, apply,
4160-
types.erasure(tree.referentType.getReturnType()));
4161-
4162-
setVarargsIfNeeded(apply, tree.varargsElement);
4163-
return apply;
4164-
}
4165-
4166-
/**
4167-
* Lambda body to use for a 'new'.
4168-
*/
4169-
private JCExpression expressionNew() {
4170-
if (tree.kind == ReferenceKind.ARRAY_CTOR) {
4171-
//create the array creation expression
4172-
JCNewArray newArr = make.NewArray(
4173-
make.Type(types.elemtype(tree.getQualifierExpression().type)),
4174-
List.of(make.Ident(params.first())),
4175-
null);
4176-
newArr.type = tree.getQualifierExpression().type;
4177-
return newArr;
4178-
} else {
4179-
//create the instance creation expression
4180-
//note that method reference syntax does not allow an explicit
4181-
//enclosing class (so the enclosing class is null)
4182-
// but this may need to be patched up later with the proxy for the outer this
4183-
JCNewClass newClass = make.NewClass(null,
4184-
List.nil(),
4185-
make.Type(tree.getQualifierExpression().type),
4186-
convertArgs(tree.sym, args.toList(), tree.varargsElement),
4187-
null);
4188-
newClass.constructor = tree.sym;
4189-
newClass.constructorType = tree.sym.erasure(types);
4190-
newClass.type = tree.getQualifierExpression().type;
4191-
setVarargsIfNeeded(newClass, tree.varargsElement);
4192-
return newClass;
4193-
}
4194-
}
4195-
4196-
private VarSymbol addParameter(String name, Type p, boolean genArg) {
4197-
VarSymbol vsym = new VarSymbol(PARAMETER | SYNTHETIC, names.fromString(name), p, owner);
4198-
vsym.pos = tree.pos;
4199-
params.append(make.VarDef(vsym, null));
4200-
if (genArg) {
4201-
args.append(make.Ident(vsym));
4202-
}
4203-
return vsym;
4204-
}
4205-
}
4206-
4207-
/**
4208-
* Convert method/constructor arguments by inserting appropriate cast
4209-
* as required by type-erasure - this is needed when bridging a lambda/method
4210-
* reference, as the bridged signature might require downcast to be compatible
4211-
* with the generated signature.
4212-
*/
4213-
private List<JCExpression> convertArgs(Symbol meth, List<JCExpression> args, Type varargsElement) {
4214-
Assert.check(meth.kind == MTH);
4215-
List<Type> formals = types.erasure(meth.type).getParameterTypes();
4216-
if (varargsElement != null) {
4217-
Assert.check((meth.flags() & VARARGS) != 0);
4218-
}
4219-
return transTypes.translateArgs(args, formals, varargsElement, attrEnv);
4220-
}
4221-
4222-
/**
4223-
* Set varargsElement field on a given tree (must be either a new class tree
4224-
* or a method call tree)
4225-
*/
4226-
private void setVarargsIfNeeded(JCTree tree, Type varargsElement) {
4227-
if (varargsElement != null) {
4228-
switch (tree.getTag()) {
4229-
case APPLY: ((JCMethodInvocation)tree).varargsElement = varargsElement; break;
4230-
case NEWCLASS: ((JCNewClass)tree).varargsElement = varargsElement; break;
4231-
case TYPECAST: setVarargsIfNeeded(((JCTypeCast) tree).expr, varargsElement); break;
4232-
default: throw new AssertionError();
4233-
}
4234-
}
4235-
}
4236-
42373902
public void visitSwitch(JCSwitch tree) {
42383903
List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.patternSwitch,
42393904
tree.wasEnumSelector,

0 commit comments

Comments
 (0)