< prev index next > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
Print this page
/*
! * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
/*
! * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
UPWARDS() {
@Override
ProjectionKind complement() {
return DOWNWARDS;
}
+
+ @Override
+ boolean allowIntersectionTypes() {
+ return true;
+ }
+
+ @Override
+ ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
+ return allowIntersectionTypes ? this : UPWARDS_NO_INTERSECTION;
+ }
},
DOWNWARDS() {
@Override
ProjectionKind complement() {
return UPWARDS;
}
+
+ @Override
+ boolean allowIntersectionTypes() {
+ return true;
+ }
+
+ @Override
+ ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
+ return allowIntersectionTypes ? this : DOWNWARDS_NO_INTERSECTION;
+ }
+ },
+ UPWARDS_NO_INTERSECTION() {
+ @Override
+ ProjectionKind complement() {
+ return DOWNWARDS_NO_INTERSECTION;
+ }
+
+ @Override
+ boolean allowIntersectionTypes() {
+ return false;
+ }
+
+ @Override
+ ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
+ return allowIntersectionTypes ? UPWARDS : this;
+ }
+ },
+ DOWNWARDS_NO_INTERSECTION() {
+ @Override
+ ProjectionKind complement() {
+ return UPWARDS_NO_INTERSECTION;
+ }
+
+ @Override
+ boolean allowIntersectionTypes() {
+ return false;
+ }
+
+ @Override
+ ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes) {
+ return allowIntersectionTypes ? DOWNWARDS : this;
+ }
};
abstract ProjectionKind complement();
+ abstract boolean allowIntersectionTypes();
+ abstract ProjectionKind withIntersectionTypes(boolean allowIntersectionTypes);
}
/**
* This visitor performs upwards and downwards projections on types.
*
this.vars = vars;
}
@Override
public Type visitClassType(ClassType t, ProjectionKind pkind) {
! if (t.isCompound()) {
! List<Type> components = directSupertypes(t);
! List<Type> components1 = components.map(c -> c.map(this, pkind));
! if (components == components1) return t;
! else return makeIntersectionType(components1);
} else {
Type outer = t.getEnclosingType();
Type outer1 = visit(outer, pkind);
List<Type> typarams = t.getTypeArguments();
List<Type> formals = t.tsym.type.getTypeArguments();
this.vars = vars;
}
@Override
public Type visitClassType(ClassType t, ProjectionKind pkind) {
! if (t.isUnion() || t.isIntersection()) {
! if (pkind.allowIntersectionTypes()) {
! List<Type> components = directSupertypes(t);
! List<Type> components1 = components.map(c -> c.map(this, pkind));
! if (components == components1) return t;
+ else return makeIntersectionType(components1);
+ } else if (t.isIntersection()) {
+ return visit(((IntersectionClassType)t).getExplicitComponents().head, pkind);
+ } else {
+ Assert.check(t.isUnion());
+ return visit(((UnionClassType)t).getLub(), pkind);
+ }
} else {
Type outer = t.getEnclosingType();
Type outer1 = visit(outer, pkind);
List<Type> typarams = t.getTypeArguments();
List<Type> formals = t.tsym.type.getTypeArguments();
if (seen.add(t)) {
try {
final Type bound;
switch (pkind) {
case UPWARDS:
+ case UPWARDS_NO_INTERSECTION:
bound = t.getUpperBound();
break;
case DOWNWARDS:
+ case DOWNWARDS_NO_INTERSECTION:
bound = (t.getLowerBound() == null) ?
syms.botType :
t.getLowerBound();
break;
default:
} finally {
seen.remove(t);
}
} else {
//cycle
! return pkind == ProjectionKind.UPWARDS ?
syms.objectType : syms.botType;
}
} else {
return t;
}
}
private Type mapTypeArgument(Type site, Type declaredBound, Type t, ProjectionKind pkind) {
! return t.containsAny(vars) ?
t.map(new TypeArgumentProjection(site, declaredBound), pkind) :
t;
}
class TypeArgumentProjection extends TypeMapping<ProjectionKind> {
} finally {
seen.remove(t);
}
} else {
//cycle
! return (pkind == ProjectionKind.UPWARDS || pkind == ProjectionKind.UPWARDS_NO_INTERSECTION) ?
syms.objectType : syms.botType;
}
} else {
return t;
}
}
private Type mapTypeArgument(Type site, Type declaredBound, Type t, ProjectionKind pkind) {
! return (t.containsAny(vars) || (!pkind.allowIntersectionTypes() && !chk.checkDenotable(t))) ?
t.map(new TypeArgumentProjection(site, declaredBound), pkind) :
t;
}
class TypeArgumentProjection extends TypeMapping<ProjectionKind> {
}
@Override
public Type visitType(Type t, ProjectionKind pkind) {
//type argument is some type containing restricted vars
! if (pkind == ProjectionKind.DOWNWARDS) {
//not defined
return syms.botType;
}
! Type upper = t.map(TypeProjection.this, ProjectionKind.UPWARDS);
Type lower = t.map(TypeProjection.this, ProjectionKind.DOWNWARDS);
List<Type> formals = site.tsym.type.getTypeArguments();
BoundKind bk;
Type bound;
if (!isSameType(upper, syms.objectType) &&
(declaredBound.containsAny(formals) ||
!isSubtype(declaredBound, upper))) {
bound = upper;
bk = EXTENDS;
! } else if (!lower.hasTag(BOT)) {
bound = lower;
bk = SUPER;
} else {
bound = syms.objectType;
bk = UNBOUND;
}
@Override
public Type visitType(Type t, ProjectionKind pkind) {
//type argument is some type containing restricted vars
! if (pkind == ProjectionKind.DOWNWARDS || pkind == ProjectionKind.DOWNWARDS_NO_INTERSECTION) {
//not defined
return syms.botType;
}
! Type upper = t.map(TypeProjection.this, ProjectionKind.UPWARDS.withIntersectionTypes(pkind.allowIntersectionTypes()));
Type lower = t.map(TypeProjection.this, ProjectionKind.DOWNWARDS);
List<Type> formals = site.tsym.type.getTypeArguments();
BoundKind bk;
Type bound;
if (!isSameType(upper, syms.objectType) &&
(declaredBound.containsAny(formals) ||
!isSubtype(declaredBound, upper))) {
bound = upper;
bk = EXTENDS;
! } else if (!lower.hasTag(BOT) && (!lower.isIntersection() || pkind.allowIntersectionTypes())) {
bound = lower;
bk = SUPER;
} else {
bound = syms.objectType;
bk = UNBOUND;
if (bound.hasTag(BOT)) {
return syms.botType;
}
break;
case SUPER:
! bound = wt.type.map(TypeProjection.this, pkind.complement());
! if (bound.hasTag(BOT)) {
bound = syms.objectType;
bk = UNBOUND;
}
break;
}
if (bound.hasTag(BOT)) {
return syms.botType;
}
break;
case SUPER:
! bound = wt.type.map(TypeProjection.this, pkind.withIntersectionTypes(true).complement());
! if (bound.hasTag(BOT) || (bound.isIntersection() && !pkind.allowIntersectionTypes())) {
bound = syms.objectType;
bk = UNBOUND;
}
break;
}
* @param t the type to be projected
* @param vars the set of type variables to be mapped
* @return the type obtained as result of the projection
*/
public Type upward(Type t, List<Type> vars) {
! return t.map(new TypeProjection(vars), ProjectionKind.UPWARDS);
}
/**
* Computes the set of captured variables mentioned in a given type. See {@link CaptureScanner}.
* This routine is typically used to computed the input set of variables to be used during
* @param t the type to be projected
* @param vars the set of type variables to be mapped
* @return the type obtained as result of the projection
*/
public Type upward(Type t, List<Type> vars) {
! return upward(t, true, vars);
+ }
+
+ /**
+ * Computes an upward projection of given type, and vars. See {@link TypeProjection}.
+ *
+ * @param t the type to be projected
+ * @param allowIntersection whether intersection types should be allowed in the projection
+ * @param vars the set of type variables to be mapped
+ * @return the type obtained as result of the projection
+ */
+ public Type upward(Type t, boolean allowIntersection, List<Type> vars) {
+ return t.map(new TypeProjection(vars),
+ allowIntersection ? ProjectionKind.UPWARDS : ProjectionKind.UPWARDS_NO_INTERSECTION);
}
/**
* Computes the set of captured variables mentioned in a given type. See {@link CaptureScanner}.
* This routine is typically used to computed the input set of variables to be used during
isDerivedRawCache.clear();
implCache._map.clear();
membersCache._map.clear();
closureCache.clear();
}
+
+ // code reflection
+
+ public boolean isQuoted(Type type) {
+ return type.tsym == syms.quotedType.tsym;
+ }
}
< prev index next >