/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2006-2010. */ package x10.visit; import java.util.ArrayList; import java.util.List; import polyglot.ast.Assign; import polyglot.ast.Block; import polyglot.ast.ClassDecl; import polyglot.ast.ClassMember; import polyglot.ast.ConstructorCall; import polyglot.ast.ConstructorDecl; import polyglot.ast.Eval; import polyglot.ast.Expr; import polyglot.ast.FieldAssign; import polyglot.ast.Formal; import polyglot.ast.New; import polyglot.ast.Node; import polyglot.ast.NodeFactory; import polyglot.ast.Stmt; import polyglot.ast.TypeNode; import polyglot.frontend.Job; import polyglot.types.ClassType; import polyglot.types.CodeInstance; import polyglot.types.ConstructorDef; import polyglot.types.FieldDef; import polyglot.types.Flags; import polyglot.types.LocalDef; import polyglot.types.LocalInstance; import polyglot.types.Name; import polyglot.types.Ref; import polyglot.types.SemanticException; import polyglot.types.ContainerType; import polyglot.types.Type; import polyglot.types.TypeSystem; import polyglot.types.TypeSystem_c; import polyglot.types.Types; import polyglot.util.Position; import polyglot.visit.ContextVisitor; import polyglot.visit.InnerClassRemover; import polyglot.visit.NodeVisitor; import x10.ast.DepParameterExpr; import x10.ast.TypeParamNode; import x10.ast.X10Call; import x10.ast.X10ClassDecl; import x10.ast.X10ConstructorDecl; import x10.ast.X10FieldDecl; import x10.ast.X10MethodDecl; import x10.ast.X10New; import x10.types.ClosureInstance; import x10.types.ConstrainedType; import x10.types.ParameterType; import x10.types.X10ClassDef; import x10.types.X10ClassType; import x10.types.X10ConstructorDef; import x10.types.X10ConstructorInstance; import x10.types.X10FieldDef; import x10.types.X10FieldInstance; import x10.types.X10LocalInstance; import x10.types.X10MethodDef; import x10.types.MethodInstance; import x10.types.X10ParsedClassType; import x10.types.X10ProcedureDef; import x10.types.constraints.CConstraint; import x10.types.constraints.SubtypeConstraint; import x10.types.constraints.TypeConstraint; /** * This class rewrites inner classes to static nested classes. * As part of the rewrite, it first transforms local classes * (including anonymous classes) to inner/nested classes using * an instance of {@link X10LocalClassRemover}. * * The transformation of an inner class I is as follows: * <pre> * class X[A,B]{g} { * class Y[C,D]{h} { * class I[E,F]{c} extends S[A,B,C,D,E,F] { * def this(a:Z) { * cons * } * body * } * } * ... * val v = qual.new I[P,Q](e); // qual is of type X[K,L].Y[M,N] * val w: X[K,L].Y[M.N].I[P.Q] = v; * } * </pre> * to * <pre> * class X[A,B]{g} { * static class Y[C,D,A',B']{h[A'/A,B'/B]&&g[A'/A,B'/B]} { * ...val out$: X[A',B'];... * static class I[E,F,C',D',A',B']{c[A'/A,B'/B,C'/C,D'/D]&&h[A'/A,B'/B,C'/C,D'/D]&&g[A'/A,B'/B]} extends S[A',B',C',D',E,F] { * val out$: Y[C',D',A',B']; * def this(a:Z, o: Y[C',D',A',B']) { * out$ = o; * cons[A'/A,B'/B,C'/C,D'/D,out$/Y.this,out$.out$/X.this] * } * body[A'/A,B'/B,C'/C,D'/D] * } * } * ... * val v = new X.Y.I[K,L,M,N,P,Q](e, qual); * val w: X.Y.I[K,L,M,N,P,Q] = v; * } * </pre> */ public class X10InnerClassRemover extends InnerClassRemover { public X10InnerClassRemover(Job job, TypeSystem ts, NodeFactory nf) { super(job, ts, nf); } @Override protected ContextVisitor localClassRemover() { return new X10LocalClassRemover(this); } @Override protected Node leaveCall(Node old, Node n, NodeVisitor v) { Node res = super.leaveCall(old, n, v); return xform.transform(res, old, (ContextVisitor) v); } private InnerClassTypeExpander xform = new InnerClassTypeExpander(); // FIXME: factor out common functionality with TypeParamSubst! private final class InnerClassTypeExpander extends TypeTransformer { @Override protected X10MethodDecl transform(X10MethodDecl d, X10MethodDecl old) { return fixMethodDecl(d); } @Override protected X10ConstructorDecl transform(X10ConstructorDecl d, X10ConstructorDecl old) { return fixConstructorDecl(d); } @Override protected X10FieldDecl transform(X10FieldDecl d, X10FieldDecl old) { return fixFieldDecl(d); } protected CConstraint transformConstraint(CConstraint c) { return super.transformConstraint(c); } protected TypeConstraint transformTypeConstraint(TypeConstraint c) { if (c == null) return null; boolean changed = false; List<SubtypeConstraint> newTerms = new ArrayList<SubtypeConstraint>(); List<SubtypeConstraint> terms = c.terms(); for (SubtypeConstraint t : terms) { Type sub = t.subtype(); Type sup = t.supertype(); Type nsub = transformType(sub); Type nsup = transformType(sup); if (nsub != sub || nsup != sup) { newTerms.add(new SubtypeConstraint(nsub, nsup, t.kind())); changed = true; } else { newTerms.add(t); } } if (!changed) return c; TypeConstraint nc = new TypeConstraint(); nc.addTerms(newTerms); return nc; } @Override protected X10ConstructorInstance transformConstructorInstance(X10ConstructorInstance ci) { Type returnType = ci.returnType(); Type newReturnType = transformType(returnType); if (newReturnType != returnType) { ci = (X10ConstructorInstance) ci.returnType(newReturnType); } List<Type> formalTypes = ci.formalTypes(); List<Type> newFormalTypes = transformTypeList(formalTypes); if (newFormalTypes != formalTypes) { ci = (X10ConstructorInstance) ci.formalTypes(newFormalTypes); } List<LocalInstance> newFormalNames = new ArrayList<LocalInstance>(); boolean changed = false; for (LocalInstance li : ci.formalNames()) { LocalInstance newLI = transformLocalInstance((X10LocalInstance) li); if (newLI != li) changed = true; newFormalNames.add(newLI); } if (changed) { ci = (X10ConstructorInstance) ci.formalNames(newFormalNames); } ContainerType container = ci.container(); ContainerType newContainer = (ContainerType) transformType(container); if (newContainer != container) { ci = (X10ConstructorInstance) ci.container(newContainer); } CConstraint guard = ci.guard(); CConstraint newGuard = transformConstraint(guard); if (newGuard != guard) { ci = (X10ConstructorInstance) ci.guard(newGuard); } TypeConstraint typeGuard = ci.typeGuard(); TypeConstraint newTypeGuard = transformTypeConstraint(typeGuard); if (newTypeGuard != typeGuard) { ci = (X10ConstructorInstance) ci.typeGuard(newTypeGuard); } return ci; } @Override protected MethodInstance transformMethodInstance(MethodInstance mi) { Type returnType = mi.returnType(); Type newReturnType = transformType(returnType); if (newReturnType != returnType) { mi = (MethodInstance) mi.returnType(newReturnType); } List<Type> formalTypes = mi.formalTypes(); List<Type> newFormalTypes = transformTypeList(formalTypes); if (newFormalTypes != formalTypes) { mi = (MethodInstance) mi.formalTypes(newFormalTypes); } List<LocalInstance> newFormalNames = new ArrayList<LocalInstance>(); boolean changed = false; for (LocalInstance li : mi.formalNames()) { LocalInstance newLI = transformLocalInstance((X10LocalInstance) li); if (newLI != li) changed = true; newFormalNames.add(newLI); TypeSystem_c.internalConsistencyCheck(newLI.type()); } if (changed) { mi = (MethodInstance) mi.formalNames(newFormalNames); } ContainerType container = mi.container(); ContainerType newContainer = (ContainerType) transformType(container); if (newContainer != container) { mi = (MethodInstance) mi.container(newContainer); } CConstraint guard = mi.guard(); CConstraint newGuard = transformConstraint(guard); if (newGuard != guard) { mi = (MethodInstance) mi.guard(newGuard); } TypeConstraint typeGuard = mi.typeGuard(); TypeConstraint newTypeGuard = transformTypeConstraint(typeGuard); if (newTypeGuard != typeGuard) { mi = (MethodInstance) mi.typeGuard(newTypeGuard); } TypeSystem_c.internalConsistencyCheck(mi); return mi; } @Override protected X10FieldInstance transformFieldInstance(X10FieldInstance fi) { Type type = fi.type(); Type newType = transformType(type); if (newType != type) { fi = (X10FieldInstance) fi.type(newType); } ContainerType container = fi.container(); ContainerType newContainer = (ContainerType) transformType(container); if (newContainer != container) { fi = (X10FieldInstance) fi.container(newContainer); } return fi; } @Override protected X10LocalInstance transformLocalInstance(X10LocalInstance li) { Type type = li.type(); Type newType = transformType(type); if (newType != type) { li = (X10LocalInstance) li.type(newType); } return li; } @Override protected ClosureInstance transformClosureInstance(ClosureInstance ci) { Type returnType = ci.returnType(); Type newReturnType = transformType(returnType); if (newReturnType != returnType) { ci = (ClosureInstance) ci.returnType(newReturnType); } List<Type> formalTypes = ci.formalTypes(); List<Type> newFormalTypes = transformTypeList(formalTypes); if (newFormalTypes != formalTypes) { ci = (ClosureInstance) ci.formalTypes(newFormalTypes); } List<LocalInstance> newFormalNames = new ArrayList<LocalInstance>(); boolean changed = false; for (LocalInstance li : ci.formalNames()) { LocalInstance newLI = transformLocalInstance((X10LocalInstance) li); if (newLI != li) changed = true; newFormalNames.add(newLI); } if (changed) { ci = (ClosureInstance) ci.formalNames(newFormalNames); } ClassType container = ci.typeContainer(); ClassType newContainer = (ClassType) transformType(container); if (newContainer != container) { ci = (ClosureInstance) ci.typeContainer(newContainer); } CodeInstance<?> methodContainer = ci.methodContainer(); CodeInstance<?> newMethodContainer = transformCodeInstance(methodContainer); if (newMethodContainer != methodContainer) { ci = (ClosureInstance) ci.methodContainer(newMethodContainer); } CConstraint guard = ci.guard(); CConstraint newGuard = transformConstraint(guard); if (newGuard != guard) { ci = (ClosureInstance) ci.guard(newGuard); } TypeConstraint typeGuard = ci.typeGuard(); TypeConstraint newTypeGuard = transformTypeConstraint(typeGuard); if (newTypeGuard != typeGuard) { ci = (ClosureInstance) ci.typeGuard(newTypeGuard); } return ci; } @Override protected Type transformType(Type t) { Type nt = fixType(t); nt = super.transformType(nt); return nt; } } @SuppressWarnings("unchecked") public static <T> void updateRefUnsafe(Ref<? extends T> ref, T value) { ((Ref<T>)ref).update(value); } private X10MethodDecl fixMethodDecl(X10MethodDecl md) { X10MethodDef def = md.methodDef(); // Adjust various types in the def. Ref<? extends Type> dtr = def.returnType(); Ref<? extends Type> tr = md.returnType().typeRef(); if (dtr != tr && !ts.typeEquals(Types.get(tr), Types.get(dtr), context)) { updateRefUnsafe(dtr, Types.get(tr)); } List<Formal> formals = md.formals(); List<Ref<? extends Type>> formalTypes = def.formalTypes(); List<LocalDef> formalNames = def.formalNames(); for (int i = 0; i < formalTypes.size(); i++) { Ref<? extends Type> dftr = formalTypes.get(i); LocalDef fn = formalNames.get(i); assert (ts.typeEquals(Types.get(fn.type()), Types.get(dftr), context)); Ref<? extends Type> ftr = formals.get(i).type().typeRef(); if (!ts.typeEquals(Types.get(ftr), Types.get(dftr), context)) { if (dftr != ftr) updateRefUnsafe(dftr, Types.get(ftr)); if (fn.type() != ftr) { updateRefUnsafe(fn.type(), Types.get(ftr)); } } } if (md.guard() != null) { DepParameterExpr g = md.guard(); if (def.guard() != g.valueConstraint()) { def.guard().update(Types.get(g.valueConstraint())); } if (def.typeGuard() != g.typeConstraint()) { def.typeGuard().update(Types.get(g.typeConstraint())); } } if (md.offerType() != null) { Ref<? extends Type> dotr = def.offerType(); Ref<? extends Type> otr = md.offerType().typeRef(); if (dotr != otr && !ts.typeEquals(Types.get(otr), Types.get(dotr), context)) { updateRefUnsafe(dotr, Types.get(otr)); } } ContainerType container = def.container().get(); Ref<? extends ContainerType> newContainer = Types.ref((ContainerType)fixType(container)); if (newContainer != container) { def.setContainer(newContainer); } return md; } private X10ConstructorDecl fixConstructorDecl(X10ConstructorDecl cd) { X10ConstructorDef def = cd.constructorDef(); // Adjust various types in the def. if (cd.returnType() != null) { Ref<? extends Type> dtr = def.returnType(); Ref<? extends Type> tr = cd.returnType().typeRef(); if (dtr != tr && !ts.typeEquals(Types.get(tr), Types.get(dtr), context)) { updateRefUnsafe(dtr, Types.get(tr)); } } List<Formal> formals = cd.formals(); List<Ref<? extends Type>> formalTypes = def.formalTypes(); List<LocalDef> formalNames = def.formalNames(); assert formalNames.size() == formals.size(); assert formalNames.size() == formalTypes.size(); for (int i = 0; i < formalTypes.size(); i++) { Ref<? extends Type> dftr = formalTypes.get(i); LocalDef fn = formalNames.get(i); assert (ts.typeEquals(Types.get(fn.type()), Types.get(dftr), context)); Ref<? extends Type> ftr = formals.get(i).type().typeRef(); if (!ts.typeEquals(Types.get(ftr), Types.get(dftr), context)) { if (dftr != ftr) updateRefUnsafe(dftr, Types.get(ftr)); if (fn.type() != ftr) { updateRefUnsafe(fn.type(), Types.get(ftr)); } } } if (cd.guard() != null) { DepParameterExpr g = cd.guard(); if (def.guard() != g.valueConstraint()) { def.guard().update(Types.get(g.valueConstraint())); } if (def.typeGuard() != g.typeConstraint()) { def.typeGuard().update(Types.get(g.typeConstraint())); } } if (cd.offerType() != null) { Ref<? extends Type> dotr = def.offerType(); Ref<? extends Type> otr = cd.offerType().typeRef(); if (dotr != otr && !ts.typeEquals(Types.get(otr), Types.get(dotr), context)) { updateRefUnsafe(dotr, Types.get(otr)); } } ContainerType container = def.container().get(); Ref<? extends ContainerType> newContainer = Types.ref((ContainerType)fixType(container)); if (newContainer != container) { def.setContainer(newContainer); } return cd; } private X10FieldDecl fixFieldDecl(X10FieldDecl fd) { X10FieldDef def = fd.fieldDef(); // Adjust field type. Ref<? extends Type> dtr = def.type(); Ref<? extends Type> tr = fd.type().typeRef(); if (dtr != tr && !ts.typeEquals(Types.get(tr), Types.get(dtr), context)) { updateRefUnsafe(dtr, Types.get(tr)); } return fd; } protected ClassDecl fixClassDecl(ClassDecl n) { // FIX:XTENLANG-215 X10ClassDecl cd = (X10ClassDecl) n; Flags flags = cd.flags().flags(); X10ClassDef def = cd.classDef(); if (def.isMember() && !cd.flags().flags().isStatic()) { def.flags(def.flags().clearStatic()); // temporarily turn off the "static" flag // The def should already have all of the necessary type parameters List<ParameterType> typeParameters = def.typeParameters(); List<ParameterType.Variance> variances = def.variances(); assert (typeParameters.size() == variances.size()); List<TypeParamNode> typeParamNodes = new ArrayList<TypeParamNode>(cd.typeParameters()); for (int p = 0; p < typeParameters.size(); p++) { ParameterType tp = typeParameters.get(p); if (p < typeParamNodes.size()) { TypeParamNode tpn = typeParamNodes.get(p); assert (tpn.type().typeEquals(tp, context())); continue; } NodeFactory xnf = (NodeFactory) nf; Position genPos = tp.position().markCompilerGenerated(); typeParamNodes.add(xnf.TypeParamNode(genPos, xnf.Id(genPos, tp.name()), variances.get(p)).type(tp)); } if (typeParameters.size() > cd.typeParameters().size()) { cd = cd.typeParameters(typeParamNodes); } List<ClassMember> newMember = new ArrayList<ClassMember>(); List<X10FieldDecl> fieldDs = new ArrayList<X10FieldDecl>(); List<ClassMember> members = cd.body().members(); // remove initializers of final variables; // final int bar = foo(define outer class val) -> final int bar; for (ClassMember classMember : members) { if (classMember instanceof X10FieldDecl) { X10FieldDecl fieldD = (X10FieldDecl) classMember; if (fieldD.fieldDef().flags().isFinal() && !fieldD.fieldDef().flags().isStatic() && fieldD.init() != null) { fieldDs.add(fieldD); newMember.add(fieldD.init(null)); continue; } } newMember.add(classMember); } // add code to initialize final variables after super() for (int i = 0; i < members.size(); i++) { ClassMember classMember = members.get(i); if (classMember instanceof ConstructorDecl) { ArrayList<Stmt> statements = new ArrayList<Stmt>(); for (X10FieldDecl fieldD : fieldDs) { Position pos = fieldD.position().markCompilerGenerated(); FieldDef fi = fieldD.fieldDef(); FieldAssign a = nf.FieldAssign(pos, nf.This(pos).type(fi.asInstance().container()), nf.Id(pos, fi.name()), Assign.ASSIGN, fieldD.init()); a = (FieldAssign) a.type(fi.asInstance().type()); a = a.fieldInstance(fi.asInstance()); a = a.targetImplicit(false); Eval e = nf.Eval(pos, a); statements.add(e); } ConstructorDecl decl = (ConstructorDecl) classMember; Block block = decl.body(); if (block.statements().size() > 0) { Stmt stmt = block.statements().get(0); if (stmt instanceof ConstructorCall) { statements.add(0, stmt); } else { statements.add(stmt); } statements.addAll(block.statements().subList(1, block.statements().size())); } newMember.set(i,(ClassMember) decl.body(block.statements(statements))); } } cd = cd.body(cd.body().members(newMember)); def.setWasInner(true); Ref<? extends Type> st = def.superType(); if (st != null) { ((Ref<Type>) st).update(Types.instantiateTypeParametersExplicitly(Types.get(st))); } for (Ref<? extends Type> it : def.interfaces()) { ((Ref<Type>) it).update(Types.instantiateTypeParametersExplicitly(Types.get(it))); } def.flags(def.flags().Static()); // set the "static" flag back on } cd = (X10ClassDecl) super.fixClassDecl(cd); if (def.isMember() && !cd.flags().flags().isStatic()) { cd = cd.flags(cd.flags().flags(flags.Static())); } return cd; } protected void adjustConstructorFormals(ConstructorDef ci, List<Formal> newFormals) { super.adjustConstructorFormals(ci, newFormals); assert (ci instanceof X10ConstructorDef); List<LocalDef> newFormalNames = new ArrayList<LocalDef>(); for (Formal f : newFormals) { newFormalNames.add(f.localDef()); } ((X10ConstructorDef) ci).setFormalNames(newFormalNames); } protected CConstraint fixConstraint(CConstraint constraint) { return constraint; } protected Type fixTypeArguments(Type t) { if (t instanceof ConstrainedType) { ConstrainedType ct = (ConstrainedType) t; Type bt = Types.get(ct.baseType()); Type ibt = fixType(bt); if (ibt != bt) ct = ct.baseType(Types.ref(ibt)); return ct; } else if (t instanceof X10ParsedClassType) { X10ParsedClassType pct = (X10ParsedClassType) t; List<Type> typeArguments = pct.typeArguments(); List<Type> newTypeArguments = typeArguments; if (typeArguments != null) { List<Type> res = new ArrayList<Type>(); for (Type a : typeArguments) { Type ia = fixType(a); if (ia != a) newTypeArguments = res; res.add(ia); } } pct = pct.typeArguments(newTypeArguments); return pct; } else { return t; } } protected Type fixType(Type t) { if (t == null) return null; if (!t.isClass()) return t; X10ParsedClassType qt = (X10ParsedClassType) t.toClass(); X10ClassDef def = qt.x10Def(); if (def.isMember() && !def.flags().isStatic()) { List<ParameterType> typeParameters = new ArrayList<ParameterType>(); List<ParameterType.Variance> variances = new ArrayList<ParameterType.Variance>(); gatherOuterTypeParameters(def, typeParameters, variances); assert (typeParameters.size() == variances.size()); for (int p = 0; p < typeParameters.size(); p++) { ParameterType tp = typeParameters.get(p); // FIXME: [IP] this is a hack. We should really rename type parameters. // rename it here, see what breaks... //tp = new ParameterType(ts, Position.COMPILER_GENERATED, Position.COMPILER_GENERATED, Name.makeFresh("_T"), Types.ref(def)); def.addTypeParameter(tp, variances.get(p)); } def.setWasInner(true); def.flags(def.flags().Static()); } t = Types.instantiateTypeParametersExplicitly(t); t = fixTypeArguments(t); t = propagateTypeArgumentsToInnermostType(t); CConstraint constraint = t instanceof ConstrainedType ? ((ConstrainedType) t).getRealXClause() : null; if (constraint != null) { CConstraint newConstraint = fixConstraint(constraint); if (newConstraint != constraint) t = Types.xclause(Types.baseType(t), newConstraint); } return t; } @Override public TypeNode fixTypeNode(TypeNode tn) { return super.fixTypeNode(tn); } @Override public New fixNew(New neu) { Expr q = neu.qualifier(); X10New xneu = (X10New) super.fixNew(neu); if (q == null) return xneu; X10ConstructorInstance ci = xneu.constructorInstance(); // Fix the ci (again). ArrayList<LocalInstance> formals = new ArrayList<LocalInstance>(); formals.add(typeSystem().localDef(q.position().markCompilerGenerated(), Flags.FINAL, Types.ref(q.type()), Name.makeFresh()).asInstance()); formals.addAll(ci.formalNames()); ci = (X10ConstructorInstance) ci.formalNames(formals); xneu = xneu.constructorInstance(ci); assert (q.type().isClass()); X10ParsedClassType qt = (X10ParsedClassType) q.type().toClass(); List<TypeNode> typeArguments = new ArrayList<TypeNode>(xneu.typeArguments()); List<Type> tArgs = qt.typeArguments(); if (tArgs != null && !tArgs.isEmpty()) { for (Type ta : tArgs) { typeArguments.add(nf.CanonicalTypeNode(q.position().markCompilerGenerated(), ta)); } xneu = xneu.typeArguments(typeArguments); // Object type has already been transformed by the visitor. } return xneu; } @Override protected Node fixConstructorCall(ConstructorCall cc) { Expr q = cc.qualifier(); cc = (ConstructorCall) super.fixConstructorCall(cc); X10ConstructorInstance ci = (X10ConstructorInstance) cc.constructorInstance(); boolean fixCI = ci.formalTypes().size() != ci.formalNames().size(); // Fix the ci if a copy; otherwise, let the ci be modified at the declaration node. if (fixCI) { List<LocalInstance> args = new ArrayList<LocalInstance>(); args.add(typeSystem().localDef(q.position().markCompilerGenerated(), Flags.FINAL, Types.ref(q.type()), Name.makeFresh()).asInstance()); args.addAll(ci.formalNames()); ci = (X10ConstructorInstance) ci.formalNames(args); cc = cc.constructorInstance(ci); } return cc; } private static Type propagateTypeArgumentsToInnermostType(Type t) { if (t instanceof X10ParsedClassType) { X10ParsedClassType ct = (X10ParsedClassType) t; if (ct.isMember()) { ct = ct.container(resetTypeArguments((X10ParsedClassType) ct.container())); } List<Type> typeArguments = ct.typeArguments(); List<Type> newTypeArguments = typeArguments; if (typeArguments != null) { List<Type> res = new ArrayList<Type>(); for (Type a : typeArguments) { Type ia = propagateTypeArgumentsToInnermostType(a); if (ia != a) newTypeArguments = res; res.add(ia); } } ct = ct.typeArguments(newTypeArguments); return ct; } else if (t instanceof ConstrainedType) { ConstrainedType ct = (ConstrainedType) t; Type baseType = Types.get(ct.baseType()); Type newBaseType = propagateTypeArgumentsToInnermostType(baseType); if (newBaseType != baseType) t = ct.baseType(Types.ref(newBaseType)); }/* else if (t instanceof AnnotatedType) { AnnotatedType at = (AnnotatedType) t; Type baseType = at.baseType(); Type newBaseType = propagateTypeArgumentsToInnermostType(baseType); if (newBaseType != baseType) t = at.baseType(newBaseType); }*/ return t; } private static X10ParsedClassType resetTypeArguments(X10ParsedClassType t) { if (t.isMember()) { t = t.container(resetTypeArguments((X10ParsedClassType) t.container())); } return t.typeArguments(null); } private void gatherOuterTypeParameters(X10ClassDef def, List<ParameterType> typeParameters, List<ParameterType.Variance> variances) { if (!isInner(def)) return; def = (X10ClassDef) Types.get(def.outer()); List<ParameterType> tps = def.typeParameters(); List<ParameterType.Variance> vs = def.variances(); for (int i = 0; i < tps.size(); i++) { ParameterType tp = tps.get(i); ParameterType.Variance v = vs.get(i); if (!typeParameters.contains(tp)) { typeParameters.add(tp); variances.add(v); } } gatherOuterTypeParameters(def, typeParameters, variances); } @Override protected FieldDef boxThis(ClassType currClass, ClassType outerClass) { outerClass = (ClassType) fixType(outerClass); FieldDef fi = super.boxThis(currClass, outerClass); //if (!(fi.flags() instanceof X10Flags)) // fi.setFlags(X10Flags.toX10Flags(fi.flags())); return fi; } }