Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,260
    • Issues 4,260
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 398
    • Merge Requests 398
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #16760

Closed
Open
Opened Jun 06, 2019 by Luo Chen@luochen1990

Proposal: add HasCallStack for all partial functions in base

Motivation

Partial functions in base (especially Prelude) often cause runtime errors and is hard to locate. My current workaround is define my own wrapper functions with HasCallStack constraint for some mostly used partial functions.

e.g.

head' :: HasCallStack => [a] -> a
head' = head

fromJust' :: HasCallStack => Maybe a -> a
fromJust' = fromJust

I have been thinking about how should we use the HasCallStack mechanism to gain a better debugging experience. i.e. How HasCallStack is supposed to be used by the programmers. And through my programming practice I think add HasCallStack for partial (non-total) functions could be a good balance for better debugging experience and less runtime overhead.

Proposal

  1. add HasCallStack constraint for all partial functions in base package
  2. suggest all programmers to add HasCallStack constraint for their exported partial functions when they release a package
  3. provide a compiler option to toggle off the effect of HasCallStack constraint in case somebody need best performance

Other Considerations

There is an issue talking about inferring HasCallStack, and it says:

The downside is that even with -finfer-hascallstack you would not get full call-stacks for functions in an imported module that was compiled normally. So this would not help with e.g. partial functions in base.

And the downside no more exists when working with this proposal.

With these two proposal work together, we finally get an almost perfect solution for call stack in Haskell: When developing a package, we can use the -finfer-hascallstack to get very detailed call stack information, and the printed call stack will just end up properly at the importing boundary, so we can know the path how we reach an improper call to a partial function provided by some other imported package, and the detailed call stack inside the imported package will not be printed, which is disturbing (this is much better than other languages' call stack solution). And when the package is released, it will be compiled without -finfer-hascallstack and only the exported partial functions (which is expected to be marked with the HasCallStack constraint) will appears in the call stack.

Assignee
Assign to
⊥
Milestone
⊥
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#16760