Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

universal type variables: initial prototype #521

Closed
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1950,23 +1950,25 @@ public TypeKind getKind() {
*/
public TypeVar projection = null;

public boolean isReferenceProjection;
protected boolean isReferenceProjection = false;

// redundant for now but helpful for debug reasons
public boolean isUniversal;
private boolean isUniversal;

public TypeVar(Name name, Symbol owner, Type lower) {
this(name, owner, lower, false, false);
this(name, owner, lower, false);
}

public TypeVar(Name name, Symbol owner, Type lower, boolean isUniversal, boolean isReferenceProjection) {
public TypeVar(Name name, Symbol owner, Type lower, boolean isUniversal) {
super(null, TypeMetadata.EMPTY);
Assert.checkNonNull(lower);
tsym = new TypeVariableSymbol(isUniversal ? UNIVERSAL : 0, name, this, owner);
this.setUpperBound(null);
this.lower = lower;
this.isReferenceProjection = isReferenceProjection;
this.isUniversal = isUniversal;
if (isUniversal && !isReferenceProjection) {
referenceProjection();
}
}

public TypeVar(TypeSymbol tsym, Type bound, Type lower) {
@@ -1986,6 +1988,9 @@ public TypeVar(TypeSymbol tsym, Type bound, Type lower,
this.lower = lower;
this.isReferenceProjection = isReferenceProjection;
this.isUniversal = (tsym.flags_field & UNIVERSAL) != 0;
if (isUniversal && !isReferenceProjection) {

This comment has been minimized.

@mcimadamore

mcimadamore Aug 12, 2021
Collaborator

isn't isReferenceProjection always false here (you have just created the class)

This comment has been minimized.

@vicente-romero-oracle

vicente-romero-oracle Aug 12, 2021
Author Contributor

not really, because this constructor is used again to build the reference, so I have to add it to the condition to avoid stackoverflow errors

referenceProjection();
}
}

@Override
@@ -2014,7 +2019,11 @@ public TypeTag getTag() {
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Type getUpperBound() { return _bound; }

public void setUpperBound(Type bound) { this._bound = bound; }
public void setUpperBound(Type bound) {
this._bound = bound;
if (projection != null)
projection.setUpperBound(bound);
}

int rank_field = -1;

@@ -2047,16 +2056,6 @@ public boolean isNullOrReference() {
return v.visitTypeVariable(this, p);
}

@Override
public Type withTypeVar(Type t) {
if (t.hasTag(TYPEVAR) &&
((TypeVar)t).isReferenceProjection() &&
projection != null) {
return projection;
}
return this;
}

@Override
public TypeVar referenceProjection() {
if (projection == null) {
@@ -3607,14 +3607,11 @@ public Type visitTypeVar(TypeVar t, Void ignored) {
for (List<Type> from = this.from, to = this.to;
from.nonEmpty();
from = from.tail, to = to.tail) {
if (t.equalsIgnoreMetadata(from.head)) {
return to.head.withTypeVar(t);
}
if (allowUniversalTVars &&
!t.isValueProjection() &&
from.head.hasTag(TYPEVAR) &&
((TypeVar)from.head).projection != null &&
t.equalsIgnoreMetadata(((TypeVar)from.head).projection)) {
if (t.equalsIgnoreMetadata(from.head) ||
allowUniversalTVars &&
!t.isValueProjection() &&
from.head.hasTag(TYPEVAR) &&
t.equalsIgnoreMetadata(((TypeVar)from.head).referenceProjection())) {
return to.head.withTypeVar(t);
}
}
@@ -2660,7 +2660,7 @@ public void visitApply(JCMethodInvocation tree) {
&& (tree.meth.hasTag(SELECT))
&& ((JCFieldAccess)tree.meth).selected.hasTag(IDENT)
&& TreeInfo.name(((JCFieldAccess)tree.meth).selected) == names._super;
boolean qualifierIsUniversal = allowUniversalTVars && qualifier.hasTag(TYPEVAR) && ((TypeVar)qualifier).isValueProjection();
boolean qualifierIsUniversal = allowUniversalTVars && qualifier.hasTag(TYPEVAR) && ((TypeVar)qualifier).isUniversal();
if (qualifier.tsym.isPrimitiveClass() || qualifierIsUniversal || superCallOnPrimitiveReceiver) {
int argSize = argtypes.size();
Name name = symbol.name;
@@ -4464,8 +4464,7 @@ public void visitSelect(JCFieldAccess tree) {
sym = selectSym(tree, sitesym, site, env, resultInfo);
}
boolean varArgs = env.info.lastResolveVarargs();
tree.sym = (allowUniversalTVars && site.getTag() == TYPEVAR && tree.name == names.ref) ?
sym.type.tsym : sym;
tree.sym = sym;

if (site.hasTag(TYPEVAR) && !isType(sym) && sym.kind != ERR) {
site = types.skipTypeVars(site, true);
@@ -4597,15 +4596,8 @@ private Symbol selectSym(JCFieldAccess tree,
case WILDCARD:
throw new AssertionError(tree);
case TYPEVAR:
if (allowUniversalTVars && name == names.ref && ((TypeVar)site).isValueProjection()) {
TypeVar siteTV = (TypeVar)site;
if (siteTV.projection == null) {
TypeVariableSymbol tmpTVarSym = new TypeVariableSymbol(siteTV.tsym.flags(), siteTV.tsym.name, null, siteTV.tsym.owner);
tmpTVarSym.type = siteTV.referenceProjection();
}
TypeVariableSymbol tmpTVarSym = new TypeVariableSymbol(siteTV.tsym.flags(), siteTV.tsym.name, null, siteTV.tsym.owner);
tmpTVarSym.type = siteTV.referenceProjection();
return tmpTVarSym;
if (allowUniversalTVars && name == names.ref && ((TypeVar)site).isUniversal()) {
return ((TypeVar)site).referenceProjection().tsym;
}
// Normally, site.getUpperBound() shouldn't be null.
// It should only happen during memberEnter/attribBase
@@ -5146,7 +5138,7 @@ public void visitTypeApply(JCTypeApply tree) {
List<Type> argTypes, argTypes2;
argTypes2 = argTypes = attribAnyTypes(args, env);
for (Type t : ((ClassType) clazztype.tsym.type).typarams_field) {
argTypes.head = chk.checkRefType(args.head.pos(), argTypes.head, ((TypeVar) t).isValueProjection());
argTypes.head = chk.checkRefType(args.head.pos(), argTypes.head, ((TypeVar) t).isUniversal());
args = args.tail;
argTypes = argTypes.tail;
}
@@ -565,7 +565,7 @@ protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {
public void visitTypeParameter(JCTypeParameter tree) {
TypeVar a = (tree.type != null)
? (TypeVar)tree.type
: new TypeVar(tree.name, env.info.scope.owner, syms.botType, tree.universal, false);
: new TypeVar(tree.name, env.info.scope.owner, syms.botType, tree.universal);
tree.type = a;
if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) {
env.info.scope.enter(a.tsym);