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

refcount: define macro-constraint HasCallStackIfDebug #495

Merged
merged 1 commit into from
Dec 11, 2024

Conversation

wenkokke
Copy link
Collaborator

@dcoutts This PR defines a HasCallStackIfDebug macro which

#ifdef NO_IGNORE_ASSERTS
#define HasCallStackIfDebug HasCallStack
#else
#define HasCallStackIfDebug ()
#endif

which does not throw a warning when used as

newRef ::
     (RefCounted obj, FinaliserM obj ~ m, PrimMonad m)
  => HasCallStackIfDebug
  => m ()
  -> (RefCounter m -> obj)
  -> m (Ref obj)

but is closer to Haskell syntax than the previous HAS_CALL_STACK macro.

@wenkokke
Copy link
Collaborator Author

Note that all other variants do throw a warning.

The following use of the above macro throws a warning:

newRef ::
     (RefCounted obj, FinaliserM obj ~ m, PrimMonad m, HasCallStackIfDebug) 
  => m ()
  -> (RefCounter m -> obj)
  -> m (Ref obj)

The following definition always throws a warning, regardless of use:

type HasCallStackIfDebug :: Constraint
#ifdef NO_IGNORE_ASSERTS
type HasCallStackIfDebug = HasCallStack
#else
type HasCallStackIfDebug = ()
#endif

Comment on lines 202 to 206
#ifdef NO_IGNORE_ASSERTS
#define HAS_CALL_STACK => HasCallStack
#define HasCallStackIfDebug HasCallStack
#else
#define HAS_CALL_STACK
#define HasCallStackIfDebug ()
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the all-caps macros because it makes it clear that it is not actual haskell syntax

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you feel that with the all-caps name, this is an improvement?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is, of course, the risk that this is highly dependent on what is arguably a GHC bug.

@@ -219,7 +219,7 @@ class RefCounted obj where
--
newRef ::
(RefCounted obj, FinaliserM obj ~ m, PrimMonad m)
HAS_CALL_STACK
=> HasCallStackIfDebug
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason that this does not throw a warning?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the looks of it, GHC combines successive constraint arrows, so by the time it reaches the warning subsystem, (A, B) => () => x has turned into (A, B) => x by concatenation, whereas it does no other normalisation, so (A, B, ()) => x remains unchanged.

@wenkokke
Copy link
Collaborator Author

wenkokke commented Dec 11, 2024

My preferred version would be to use CPP to define a type and simply disable the warning, since we're purposefully creating an empty constraint, so disabling the warning is sensible. That way, the code we're writing actually can follow the general rule that each CPP section should be syntactically valid Haskell.

The current PR achieves that, but only by lying and possibly relying on a bug in the GHC warning system.

Copy link
Collaborator

@dcoutts dcoutts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

I have no problem with using a "normal" name rather than a CPP_ISH name. I did the CPP_ISH name because the thing I did was clearly not valid syntax, so it provided a hint that some evil CPP was at play.

And I don't mind relying on GHC warning quirks here.

Related: we should file a ghc bug/feature request to ask that redundant () constraints not get warned about but just get eliminated.

@dcoutts
Copy link
Collaborator

dcoutts commented Dec 11, 2024

My preferred version would be to use CPP to define a type and simply disable the warning, since we're purposefully creating an empty constraint, so disabling the warning is sensible.

The downside of disabling the warning is we cannot do it selectively only for this constraint. It would disable all redundant constraint checking in the module, which can hide real things (e.g. during later refactoring).

@dcoutts dcoutts added this pull request to the merge queue Dec 11, 2024
Merged via the queue into main with commit 70d0db8 Dec 11, 2024
27 checks passed
@dcoutts dcoutts deleted the wenkokke/rc-hascallstackifdebug branch December 11, 2024 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants