Merge pull request #8646 from gottesmm/small_sema_refactoring

diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 94034e1..14dffb8 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -4823,6 +4823,49 @@
   return false;
 }
 
+static unsigned computeCallLevel(
+    ConstraintSystem &cs, ConcreteDeclRef callee,
+    llvm::PointerUnion<ApplyExpr *, ExprRewriter::LevelTy> applyOrLevel) {
+  using LevelTy = ExprRewriter::LevelTy;
+
+  if (applyOrLevel.is<LevelTy>()) {
+    // Level specified by caller.
+    return applyOrLevel.get<LevelTy>();
+  }
+
+  // If we do not have a callee, return a level of 0.
+  if (!callee) {
+    return 0;
+  }
+
+  // Determine the level based on the application itself.
+  auto *apply = applyOrLevel.get<ApplyExpr *>();
+
+  // Only calls to members of types can have level > 0.
+  auto calleeDecl = callee.getDecl();
+  if (!calleeDecl->getDeclContext()->isTypeContext()) {
+    return 0;
+  }
+
+  // Level 1 if we're not applying "self".
+  if (auto *call = dyn_cast<CallExpr>(apply)) {
+    if (!calleeDecl->isInstanceMember() ||
+        !isReferenceToMetatypeMember(cs, call->getDirectCallee())) {
+      return 1;
+    }
+    return 0;
+  }
+
+  // Level 1 if we have an operator.
+  if (isa<PrefixUnaryExpr>(apply) || isa<PostfixUnaryExpr>(apply) ||
+      isa<BinaryExpr>(apply)) {
+    return 1;
+  }
+
+  // Otherwise, we have a normal application.
+  return 0;
+}
+
 Expr *ExprRewriter::coerceCallArguments(
     Expr *arg, Type paramType,
     llvm::PointerUnion<ApplyExpr *, LevelTy> applyOrLevel,
@@ -4870,29 +4913,7 @@
     findCalleeDeclRef(cs, solution, cs.getConstraintLocator(locator));
 
   // Determine the level,
-  unsigned level = 0;
-  if (applyOrLevel.is<LevelTy>()) {
-    // Level specified by caller.
-    level = applyOrLevel.get<LevelTy>();
-  } else if (callee) {
-    // Determine the level based on the application itself.
-    auto apply = applyOrLevel.get<ApplyExpr *>();
-
-    // Only calls to members of types can have level > 0.
-    auto calleeDecl = callee.getDecl();
-    if (calleeDecl->getDeclContext()->isTypeContext()) {
-      // Level 1 if we're not applying "self".
-      if (auto call = dyn_cast<CallExpr>(apply)) {
-        if (!calleeDecl->isInstanceMember() ||
-            !isReferenceToMetatypeMember(cs, call->getDirectCallee()))
-          level = 1;
-      } else if (isa<PrefixUnaryExpr>(apply) ||
-                 isa<PostfixUnaryExpr>(apply) ||
-                 isa<BinaryExpr>(apply)) {
-        level = 1;
-      }
-    }
-  }
+  unsigned level = computeCallLevel(cs, callee, applyOrLevel);
 
   // Determine the parameter bindings.
   auto params = decomposeParamType(paramType, callee.getDecl(), level);