@Override
 @Nullable
 public PsiType fun(final GrReferenceExpressionImpl refExpr) {
   final Pair key = Pair.create(TypeInferenceHelper.getCurrentContext(), refExpr);
   return RecursionManager.doPreventingRecursion(
       key,
       true,
       new Computable<PsiType>() {
         @Override
         public PsiType compute() {
           return doFun(refExpr);
         }
       });
 }
 @NotNull
 private GroovyResolveResult[] doPolyResolveWithCaching(
     final boolean incompleteCode, final boolean genericsMatter) {
   final InferenceContext context = TypeInferenceHelper.getCurrentContext();
   final Trinity<?, ?, ?> key =
       Trinity.create(this, context, Pair.create(incompleteCode, genericsMatter));
   final GroovyResolveResult[] value =
       RecursionManager.doPreventingRecursion(
           key,
           true,
           new Computable<GroovyResolveResult[]>() {
             @Override
             public GroovyResolveResult[] compute() {
               return doPolyResolve(incompleteCode, genericsMatter);
             }
           });
   return value == null ? GroovyResolveResult.EMPTY_ARRAY : value;
 }
 @NotNull
 private Pair<Boolean, GroovyResolveResult[]> resolveByShape(
     final boolean allVariants, @Nullable final GrExpression upToArgument) {
   LOG.assertTrue(allVariants || upToArgument == null);
   final Trinity key =
       Trinity.create(
           TypeInferenceHelper.getCurrentContext(), this, Pair.create(allVariants, upToArgument));
   final Pair<Boolean, GroovyResolveResult[]> result =
       RecursionManager.doPreventingRecursion(
           key,
           true,
           new Computable<Pair<Boolean, GroovyResolveResult[]>>() {
             @Override
             public Pair<Boolean, GroovyResolveResult[]> compute() {
               return doResolveByShape(allVariants, upToArgument);
             }
           });
   return result == null ? Pair.create(false, GroovyResolveResult.EMPTY_ARRAY) : result;
 }