Bug 416938 - [compiler] inferred callouts are not consistently available
in a tsub role
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
index 8a4ea20..4813bb2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
@@ -37,6 +37,7 @@
 import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
+import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
 import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementor;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
@@ -833,9 +834,9 @@
 }
 void computeMethods() {
 //{ObjectTeams: make sure we actually have all methods we can have:
-	// supers (unless from the same enclosing) should have all features:
+	// supers (unless in danger of infinite recursion) should have all features:
 	ReferenceBinding superclass = this.type.superclass;
-	if (superclass != null && superclass.outermostEnclosingType().erasure() != this.type.outermostEnclosingType().erasure())
+	if (StateHelper.isDefinitelyReadyToProcess(superclass, this.type, ITranslationStates.STATE_METHODS_VERIFIED))
 		Dependencies.ensureBindingState(superclass, ITranslationStates.STATE_METHODS_VERIFIED);
 	// role should copy all we can get by now
 	if (this.type.isRole() && !this.type.isInterface())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateHelper.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateHelper.java
index 02be601..f2de85d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateHelper.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/StateHelper.java
@@ -20,6 +20,7 @@
  **********************************************************************/
 package org.eclipse.objectteams.otdt.internal.core.compiler.control;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
@@ -232,6 +233,31 @@
 			return false;
 		return isReadyToProcess(type.model, state);
 	}
+	
+	public static boolean isDefinitelyReadyToProcess(ReferenceBinding type, ReferenceBinding requestingSite, int state) {
+		
+		if (!(type instanceof SourceTypeBinding))
+			return false; // most treatment not needed for binary types
+		SourceTypeBinding sourceType = (SourceTypeBinding) type;
+		
+		if (sourceType.outermostEnclosingType().erasure() == requestingSite.outermostEnclosingType().erasure() 
+				|| CharOperation.equals(type.getFileName(), requestingSite.getFileName()))
+			return false; // could infinitely recurse to the same inclosing of kind
+			
+		if (!StateHelper.isReadyToProcess(sourceType, state))
+			return false;
+			
+		try {
+			StateMemento unitState = sourceType.scope.compilationUnitScope().referenceContext.state;
+			if (unitState.isReadyToProcess(state))
+				return true; // GOAL
+		} catch (NullPointerException npe) {
+			// be shy, if any enclosing thing was missing don't risk infinite recursion.
+		}
+		
+		return false;
+	}
+
 
 	/** Signal that processing for `state' has begun
 	 *  (role- and team-models of type plus enclosing team).