       ctx.resetAssignTo()
       ctx.leaveDefinition()
       ctx.closeScope()
+      branchUsedNames = ctx.usedNames()
 
       if ctx.shouldDefer()
         continue
 
-      # TODO: we need to check that
-      # log "unifying in match", result, resultType, result.tea
       unify ctx, resultType, result.tea.type
       constraints.push result.tea.constraints...
       varNames.push (findDeclarables precs)...
 
-      matchBranchTranslate precs, assigns, compiledResult
-    ), "throw new Error('match failed to match#{errorMessage}');" #TODO: what subject?
+      [branchUsedNames, precs, assigns, compiledResult])
+
+    [usedNames] = unzip compiledResults
+    lifting = map (findDeps ctx), usedNames
+    jointlyUsed = intersectSets lifting
+
+    compiledCases = conditional (for [used, precs, assigns, compiledResult], i in compiledResults
+      lifted = lifting[i]
+      [conds, assigns] = matchBranchTranslate precs, assigns, compiledResult
+      [conds, join (findDefinitions ctx, (setToArray (subtractSets lifted, jointlyUsed))),
+        assigns])
+    , "throw new Error('match failed to match#{errorMessage}');" #TODO: what subject?
+
+    ctx.setUsedNames join oldUsed, setToArray jointlyUsed
+
     translationCache = ctx.resetAssignTo()
     call.tea = new Constrained constraints, resultType
     assignCompile ctx, call, iife concat (filter _is, [

        " in #{ctx.definitionName()}"
      else
        ""
    compiledCases = conditional (for [pattern, result] in pairs cases

      ctx.newScope() # for variables defined inside pattern
      ctx.defineNonDeferrablePattern pattern
      {precs, assigns} = patternCompile ctx, pattern, subject, no


  doneConds = termsCompileExpectingType ctx, (markOrigin boolType, call), conds

  # mark all used as used (remember them)
  oldUsed = ctx.usedNames()

  compiledResults = for result in results
