@@ -256,7 +256,7 @@ calcProd i fc topn pats
256256
257257 prodRec :: Name -> [Name] -> ([Name], Term, Term) -> Idris Bool
258258 prodRec n done _ | n `elem` done = return True
259− prodRec n done (_, _, tm) = prod n done False (delazy tm)
259+ prodRec n done (_, _, tm) = prod n done False (delazy' True tm)
260260
261261 prod :: Name -> [Name] -> Bool -> Term -> Idris Bool
262262 prod n done ok ap@(App _ _)
@@ -292,9 +292,12 @@ calcProd i fc topn pats
292292 _ -> False
293293 cotype nt n ty = False
294294
295−calcTotality :: [Name] -> FC -> Name -> [([Name], Term, Term)]
296− -> Idris Totality
297−calcTotality path fc n pats
295+-- Calculate the totality of a function from its patterns.
296+-- Either follow the size change graph (if inductive) or check for
297+-- productivity (if coinductive)
298+
299+calcTotality :: FC -> Name -> [([Name], Term, Term)] -> Idris Totality
300+calcTotality fc n pats
298301 = do i <- getIState
299302 let opts = case lookupCtxt n (idris_flags i) of
300303 [fs] -> fs
@@ -329,7 +332,7 @@ checkTotality path fc n
329332 [CaseOp _ _ _ _ pats _] ->
330333 do t' <- if AssertTotal `elem` opts
331334 then return $ Total []
332− else calcTotality path fc n pats
335+ else calcTotality fc n pats
333336 setTotality n t'
334337 addIBC (IBCTotal n t')
335338 return t'
@@ -401,41 +404,47 @@ buildSCG (_, n) = do
401404 [] -> logLvl 5 $ "Could not build SCG for " ++ show n ++ "\n"
402405 x -> error $ "buildSCG: " ++ show (n, x)
403406
404−delazy t@(App f a)
405− | (P _ (UN l) _, [_, _, arg]) <- unApply t,
406− l == txt "Force" = delazy arg
407+delazy = delazy' False -- not lazy codata
408+delazy' all t@(App f a)
407409 | (P _ (UN l) _, [_, _, arg]) <- unApply t,
408− l == txt "Delay" = delazy arg
410+ l == txt "Force" = delazy' all arg
411+ | (P _ (UN l) _, [P _ (UN lty) _, _, arg]) <- unApply t,
412+ l == txt "Delay" && (all || lty == txt "LazyEval") = delazy arg
409413 | (P _ (UN l) _, [_, arg]) <- unApply t,
410− l == txt "Lazy'" = delazy arg
411−delazy (App f a) = App (delazy f) (delazy a)
412−delazy (Bind n b sc) = Bind n (fmap delazy b) (delazy sc)
413−delazy t = t
414+ l == txt "Lazy'" = delazy' all arg
415+delazy' all (App f a) = App (delazy' all f) (delazy' all a)
416+delazy' all (Bind n b sc) = Bind n (fmap (delazy' all) b) (delazy' all sc)
417+delazy' all t = t
414418
415419buildSCG' :: IState -> [(Term, Term)] -> [Name] -> [SCGEntry]
416420buildSCG' ist pats args = nub $ concatMap scgPat pats where
417421 scgPat (lhs, rhs) = let lhs' = delazy lhs
418422 rhs' = delazy rhs
419423 (f, pargs) = unApply (dePat lhs') in
420− findCalls (dePat rhs') (patvars lhs') pargs
424+ findCalls True (dePat rhs') (patvars lhs') pargs
421425
422− findCalls ap@(App f a) pvs pargs
426+ findCalls guarded ap@(App f a) pvs pargs
423427 -- under a call to "assert_total", don't do any checking, just believe
424428 -- that it is total.
425429 | (P _ (UN at) _, [_, _]) <- unApply ap,
426430 at == txt "assert_total" = []
431+ -- under a call to "Delay LazyCodata", don't do any checking as long
432+ -- as the call is guarded
433+ | (P _ (UN del) _, [_,_,_]) <- unApply ap,
434+ guarded && del == txt "Delay" = []
427435 | (P _ n _, args) <- unApply ap
428− = mkChange n args pargs ++
429− concatMap (\x -> findCalls x pvs pargs) args
430− findCalls (App f a) pvs pargs
431− = findCalls f pvs pargs ++ findCalls a pvs pargs
432− findCalls (Bind n (Let t v) e) pvs pargs
433− = findCalls v pvs pargs ++ findCalls e (n : pvs) pargs
434− findCalls (Bind n _ e) pvs pargs
435− = findCalls e (n : pvs) pargs
436− findCalls (P _ f _ ) pvs pargs
436+ = let nguarded = isConName n (tt_ctxt ist) in
437+ mkChange n args pargs ++
438+ concatMap (\x -> findCalls nguarded x pvs pargs) args
439+ findCalls guarded (App f a) pvs pargs
440+ = findCalls False f pvs pargs ++ findCalls False a pvs pargs
441+ findCalls guarded (Bind n (Let t v) e) pvs pargs
442+ = findCalls False v pvs pargs ++ findCalls guarded e (n : pvs) pargs
443+ findCalls guarded (Bind n _ e) pvs pargs
444+ = findCalls guarded e (n : pvs) pargs
445+ findCalls guarded (P _ f _ ) pvs pargs
437446 | not (f `elem` pvs) = [(f, [])]
438− findCalls _ _ _ = []
447+ findCalls _ _ _ _ = []
439448
440449 expandToArity n args
441450 = case lookupTy n (tt_ctxt ist) of