Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Termination checking doesn't work with local lets #3147

Closed
lukaszcz opened this issue Nov 5, 2024 · 4 comments · Fixed by #3169
Closed

Termination checking doesn't work with local lets #3147

lukaszcz opened this issue Nov 5, 2024 · 4 comments · Fixed by #3169

Comments

@lukaszcz
Copy link
Collaborator

lukaszcz commented Nov 5, 2024

Typechecking

module termRec;

import Stdlib.Prelude open;

type MyList A :=
  | myNil
  | myCons@{
      elem : A;
      next : MyList A;
    };

go {A B} (f : A -> B) : MyList A -> MyList B
  | myNil := myNil
  | myCons@{elem; next} := myCons@{elem := f elem; next := go f next};

gives the error

/Users/heliax/Documents/progs/juvix/termRec.juvix:9-12:7-3: error:
The following functions fail the termination checker:
• next
• go

But the following type-checks:

go {A B} (f : A -> B) : MyList A -> MyList B
  | myNil := myNil
  | myCons@{elem; next} := myCons (f elem) (go f next);

Termination checking needs to be adapted to deal with record creation/update syntax (or whatever it is desugared to in Internal).

@janmasrovira
Copy link
Collaborator

myCons@{elem := f elem; next := go f next};

desugars to

let var1 = f elem
    var2 = go f next
in myCons var1 var2

@lukaszcz
Copy link
Collaborator Author

lukaszcz commented Nov 6, 2024

Yes, termination fails also when explicitly desugared. Typechecking:

go {A B} (f : A -> B) : MyList A -> MyList B
  | myNil := myNil
  | myCons@{elem; next} :=
    let var1 := f elem;
        var2 := go f next;
    in myCons var1 var2;

gives:

The following functions fail the termination checker:
• var2
• go

@paulcadman paulcadman modified the milestones: 0.6.8, 0.6.9 Nov 11, 2024
@lukaszcz
Copy link
Collaborator Author

Even this fails:

go {A B} (f : A -> B) : MyList A -> MyList B
  | myNil := myNil
  | (myCons elem next) :=
    let var1 := f elem;
        var2 := go f next;
    in myCons var1 var2;

So the problem is, weirdly, with the let, not with record syntax as such.

@lukaszcz
Copy link
Collaborator Author

I think this is the problem:

-- NOTE that we forget about the arguments of the hosting function
scanLetClause :: (Members '[State CallMap] r) => LetClause -> Sem r ()

@lukaszcz lukaszcz self-assigned this Nov 12, 2024
@lukaszcz lukaszcz changed the title Record creation syntax confuses termination checking Termination checking doesn't work with local lets Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants