@@ -51,13 +51,17 @@ isType ctxt env tm = isType' (normalise ctxt env tm)
5151 | otherwise = fail (showEnv env tm ++ " is not a Type")
5252
5353recheck :: Context -> Env -> Raw -> Term -> TC (Term, Type, UCs)
54−recheck ctxt env tm orig
54+recheck = recheck_borrowing []
55+
56+recheck_borrowing :: [Name] -> Context -> Env -> Raw -> Term ->
57+ TC (Term, Type, UCs)
58+recheck_borrowing bs ctxt env tm orig
5559 = let v = next_tvar ctxt in
5660 case runStateT (check' False ctxt env tm) (v, []) of -- holes banned
5761 Error (IncompleteTerm _) -> Error $ IncompleteTerm orig
5862 Error e -> Error e
5963 OK ((tm, ty), constraints) ->
60− do checkUnique ctxt env tm
64+ do checkUnique bs ctxt env tm
6165 return (tm, ty, constraints)
6266
6367check :: Context -> Env -> Raw -> TC (Term, Type)
@@ -127,12 +131,14 @@ check' holes ctxt env top = chk env top where
127131 when (not holes) $ put (v+1, ULE su (UVar v):ULE tu (UVar v):cs)
128132 return (Bind n (Pi (uniqueBinders (map fst env) sv))
129133 (pToV n tv), TType (UVar v))
130− (UType u, _) ->
131− return (Bind n (Pi (uniqueBinders (map fst env) sv))
132− (pToV n tv), UType u)
133− (_, UType u) ->
134+ (u, u') ->
134135 return (Bind n (Pi (uniqueBinders (map fst env) sv))
135− (pToV n tv), UType u)
136+ (pToV n tv), smaller u u')
137+
138+ where smaller (UType NullType) _ = UType NullType
139+ smaller _ (UType NullType) = UType NullType
140+ smaller (UType u) _ = UType u
141+ smaller _ (UType u) = UType u
136142 chk env (RBind n b sc)
137143 = do b' <- checkBinder b
138144 (scv, sct) <- chk ((n, b'):env) sc
@@ -217,29 +223,57 @@ check' holes ctxt env top = chk env top where
217223 discharge n (PVTy t) scv sct
218224 = return (Bind n (PVTy t) scv, sct)
219225
226+-- Number of times a name can be used
227+data UniqueUse = Never -- no more times
228+ | Once -- at most once more
229+ | LendOnly -- only under 'lend'
230+ | Many -- unlimited
231+ deriving Eq
232+
220233-- If any binders are of kind 'UniqueType' or 'AllTypes' and the name appears
221234-- in the scope more than once, this is an error.
222−checkUnique :: Context -> Env -> Term -> TC ()
223−checkUnique ctxt env tm = evalStateT (chkBinders env (explicitNames tm)) []
235+checkUnique :: [Name] -> Context -> Env -> Term -> TC ()
236+checkUnique borrowed ctxt env tm
237+ = evalStateT (chkBinders env (explicitNames tm)) []
224238 where
225− chkBinders :: Env -> Term -> StateT [(Name, Bool)] TC ()
239+ isVar (P _ _ _) = True
240+ isVar (V _) = True
241+ isVar _ = False
242+
243+ chkBinders :: Env -> Term -> StateT [(Name, (UniqueUse, Universe))] TC ()
226244 chkBinders env (V i) | length env > i = chkName (fst (env!!i))
227245 chkBinders env (P _ n _) = chkName n
246+ -- 'lending' a unique or nulltype variable doesn't count as a use,
247+ -- but we still can't lend something that's already been used.
248+ chkBinders env (App (App (P _ (NS (UN lend) [owner]) _) t) a)
249+ | isVar a && owner == txt "Ownership" &&
250+ (lend == txt "lend" || lend == txt "Read")
251+ = do chkBinders env t -- Check the type normally
252+ st <- get
253+ -- Remove the 'LendOnly' names from the unusable set
254+ put (filter (\(n, (ok, _)) -> ok /= LendOnly) st)
255+ chkBinders env a
256+ put st -- Reset the old state after checking the argument
228257 chkBinders env (App f a) = do chkBinders env f; chkBinders env a
229258 chkBinders env (Bind n b t)
230259 = do chkBinderName env n b
231260 chkBinders ((n, b) : env) t
232261 chkBinders env t = return ()
233262
234− chkBinderName :: Env -> Name -> Binder Term -> StateT [(Name, Bool)] TC ()
263+ chkBinderName :: Env -> Name -> Binder Term ->
264+ StateT [(Name, (UniqueUse, Universe))] TC ()
235265 chkBinderName env n b
236266 = do let rawty = forgetEnv (map fst env) (binderTy b)
237267 (_, kind) <- lift $ check ctxt env rawty -- FIXME: Cache in binder?
238268 case kind of
239269 UType UniqueType -> do ns <- get
240− put ((n, False) : ns)
270+ if n `elem` borrowed
271+ then put ((n, (LendOnly, NullType)) : ns)
272+ else put ((n, (Once, UniqueType)) : ns)
273+ UType NullType -> do ns <- get
274+ put ((n, (LendOnly, NullType)) : ns)
241275 UType AllTypes -> do ns <- get
242− put ((n, False) : ns)
276+ put ((n, (Once, AllTypes)) : ns)
243277 _ -> return ()
244278 chkBinders env (binderTy b)
245279 case b of
@@ -250,6 +284,9 @@ checkUnique ctxt env tm = evalStateT (chkBinders env (explicitNames tm)) []
250284 = do ns <- get
251285 case lookup n ns of
252286 Nothing -> return ()
253− Just True -> lift $ tfail (UniqueError n)
254− Just False -> put ((n, True) : filter (\x -> fst x /= n) ns)
287+ Just (Many, k) -> return ()
288+ Just (Never, k) -> lift $ tfail (UniqueError k n)
289+ Just (LendOnly, k) -> lift $ tfail (UniqueError k n)
290+ Just (Once, k) -> put ((n, (Never, k)) :
291+ filter (\x -> fst x /= n) ns)
255292