freshVarsIn :: (?globals :: Globals) => Span -> [Id] -> (Ctxt Assumption)
            -> Checker (Ctxt Assumption, Ctxt Kind)
freshVarsIn s vars ctxt = do
    newCtxtAndTyVars <- mapM toFreshVar (relevantSubCtxt vars ctxt)
    let (newCtxt, tyVars) = unzip newCtxtAndTyVars
    return (newCtxt, catMaybes tyVars)
  where
    toFreshVar :: (Id, Assumption) -> Checker ((Id, Assumption), Maybe (Id, Kind))
    toFreshVar (var, Discharged t c) = do
      ctype <- inferCoeffectType s c
      -- Create a fresh variable
      freshName <- freshIdentifierBase (internalName var)
      let cvar = mkId freshName
      -- Update the coeffect kind context
      modify (\s -> s { tyVarContext = (cvar, (promoteTypeToKind ctype, InstanceQ)) : tyVarContext s })

      -- Return the freshened var-type mapping
      -- and the new type variable
      return ((var, Discharged t (CVar cvar)), Just (cvar, promoteTypeToKind ctype))

    toFreshVar (var, Linear t) = return ((var, Linear t), Nothing)


-- Combine two contexts
freshVarsIn :: (?globals :: Globals) => Span -> [Id] -> (Ctxt Assumption)
            -> Checker (Ctxt Assumption, Ctxt Kind)
freshVarsIn s vars ctxt = do
    newCtxtAndTyVars <- mapM toFreshVar (relevantSubCtxt vars ctxt)
    let (newCtxt, tyVars) = unzip newCtxtAndTyVars
    return (newCtxt, catMaybes tyVars)
  where
    toFreshVar :: (Id, Assumption) -> Checker ((Id, Assumption), Maybe (Id, Kind))
    toFreshVar (var, Discharged t c) = do
      ctype <- inferCoeffectType s c
      -- Create a fresh variable
      freshName <- freshIdentifierBase (internalName var)
      let cvar = mkId freshName
      -- Update the coeffect kind context
      modify (\s -> s { tyVarContext = (cvar, (promoteTypeToKind ctype, InstanceQ)) : tyVarContext s })

      -- Return the freshened var-type mapping
      -- and the new type variable
      return ((var, Discharged t (CVar cvar)), Just (cvar, promoteTypeToKind ctype))

    toFreshVar (var, Linear t) = return ((var, Linear t), Nothing)


-- Combine two contexts
freshVarsIn s vars ctxt = do
    newCtxtAndTyVars <- mapM toFreshVar (relevantSubCtxt vars ctxt)
    let (newCtxt, tyVars) = unzip newCtxtAndTyVars
    return (newCtxt, catMaybes tyVars)
  where
    toFreshVar :: (Id, Assumption) -> Checker ((Id, Assumption), Maybe (Id, Kind))
    toFreshVar (var, Discharged t c) = do
      ctype <- inferCoeffectType s c
      -- Create a fresh variable
      freshName <- freshIdentifierBase (internalName var)
      let cvar = mkId freshName
      -- Update the coeffect kind context
      modify (\s -> s { tyVarContext = (cvar, (promoteTypeToKind ctype, InstanceQ)) : tyVarContext s })

      -- Return the freshened var-type mapping
      -- and the new type variable
      return ((var, Discharged t (CVar cvar)), Just (cvar, promoteTypeToKind ctype))

    toFreshVar (var, Linear t) = return ((var, Linear t), Nothing)


-- Combine two contexts