+ private static String refStructure(Type t) {
+ StringBuilder b = new StringBuilder();
+ IdentityHashSet<TMetaVar> seenVars = new IdentityHashSet<TMetaVar>();
+ refType(b, t, seenVars);
+ return b.toString();
+ }
+
+ private void refStructure(StringBuilder b, IdentityHashSet<TMetaVar> seenVars) {
+ b.append(System.identityHashCode(this));
+ if(!seenVars.add(this))
+ b.append(" (loop)");
+ else if(ref != null) {
+ b.append(" => ");
+ refType(b, ref, seenVars);
+ }
+ else if(skeletonRef != null) {
+ b.append(" -> ");
+ refType(b, skeletonRef, seenVars);
+ }
+ else
+ b.append(" (canonical)");
+ }
+
+ private static void refType(StringBuilder b, Type t, IdentityHashSet<TMetaVar> seenVars) {
+ if(t instanceof TMetaVar)
+ ((TMetaVar)t).refStructure(b, seenVars);
+ else {
+ b.append('[');
+ t.toString(new TypeUnparsingContext(), b);
+ b.append(']');
+ }
+ }
+
+ private void checkRefLoop(TMetaVar var) {
+ IdentityHashSet<TMetaVar> seenVars = new IdentityHashSet<TMetaVar>();
+ StringBuilder b = new StringBuilder();
+ while(true) {
+ b.append(var);
+ if(!seenVars.add(var))
+ throw new InternalCompilerError("Cyclic meta var references: " + b);
+ if(var.ref != null) {
+ b.append(" => ");
+ if(var.ref instanceof TMetaVar)
+ var = (TMetaVar)var.ref;
+ else
+ return;
+ }
+ else if(var.skeletonRef != null) {
+ b.append(" -> ");
+ if(var.skeletonRef instanceof TMetaVar)
+ var = (TMetaVar)var.skeletonRef;
+ else
+ return;
+ }
+ else
+ return;
+ }
+ }
+