Skip to content

Catch Block Fails When Inner Functional Dependency not in Function Signature #1719

@Jason94

Description

@Jason94

This is possibly caused by #1717. But I'm actually not sure because the workaround is different.

You have a class with a functional dependency:

  (define-class (MyClass :a :b (:a -> :b))
    (to-zero (:a -> :b))
    (to-zero-prx (Proxy :a -> :b))
    )

  (define-instance (MyClass String Integer)
    (define (to-zero _) 0)
    (define (to-zero-prx _) 0)
    )

Using the functional dependency works fine:

  (declare works (MyClass :a :t => Proxy :a -> String))
  (define (works x)
    (to-zero-prx x)
    "Runs")

However, if you wrap that in a catch block, it doesn't compile:

  (declare breaks (MyClass :a :t => Proxy :a -> String))
  (define (breaks x)
    (catch (progn
             (to-zero-prx x)
             "Runs")
      (_ "Fails")))
==>
  read-error: 
    COMMON-LISP:READ error during COMMON-LISP:COMPILE-FILE:
    
      Unknown instance for predicate MYCLASS #T448 #T446
    
      (in form starting at line: 17, column: 0, position: 284)

Compilation failed.

This is definitely a bug because you can hack it by wrapping in an anonymous function, which compiles:

  (declare workaround (MyClass :a :t => Proxy :a -> String))
  (define (workaround x)
    (let f = (fn ()
               (to-zero-prx x)
               "Runs"))
    (catch (inline (f))
      (_ "Fails")))

And it also works if the functional dependency appears in the declare, which is why I think this is possibly a duplicate of #1717, deep down:

  (declare also-works (MyClass :a Integer => Proxy :a -> Integer))
  (define (also-works x)
    (catch (progn
             (to-zero-prx x))
      (_ -1000)))

Also, the bug I actually ran into in my code was a little different. I couldn't recreate it. But I had this function which I think should be the same relevant shape as breaks above:

  (inline)
  (declare unmask-and-await-safely% (Runtime :rt :t => Proxy :rt -> cv:ConditionVariable -> lk:Lock -> Unit))
  (define (unmask-and-await-safely% rt-prx cv lock)
    (catch
        (progn
          (unmask! rt-prx (current-thread! rt-prx))
          (cv:await cv lock)
          (mask-current! rt-prx))
      ((InterruptCurrentThread _)
       (lk:release lock)
       Unit)))

and I got this very strange error, that I wasn't able to recreate in a simpler context:

; caught COMMON-LISP:ERROR:
;   COMMON-LISP:READ error during COMMON-LISP:COMPILE-FILE:
;   
;     Undefined key RUNTIME
;   
;     (in form starting at line: 47, column: 0, position: 919)

and the same workaround fixed it:

  (inline)
  (declare unmask-and-await-safely% (Runtime :rt :t => Proxy :rt -> cv:ConditionVariable -> lk:Lock -> Unit))
  (define (unmask-and-await-safely% rt-prx cv lock)
    (let f =
      (fn ()
        (unmask! rt-prx (current-thread! rt-prx))
        (cv:await cv lock)
        (mask-current! rt-prx)))
    (catch (inline (f))
      ((InterruptCurrentThread _)
       (lk:release lock)
       Unit)))

Full test file:

(cl:in-package :cl-user)
(defpackage :test
  (:use
   #:coalton
   #:coalton-prelude
   #:coalton-library/types
   )
  )

(in-package :test)

(named-readtables:in-readtable coalton:coalton)

(coalton-toplevel

  (define-class (MyClass :a :b (:a -> :b))
    (to-zero (:a -> :b))
    (to-zero-prx (Proxy :a -> :b))
    )

  (define-instance (MyClass String Integer)
    (define (to-zero _) 0)
    (define (to-zero-prx _) 0)
    )

  (declare works (MyClass :a :t => Proxy :a -> String))
  (define (works x)
    (to-zero-prx x)
    "Runs")

  ;; (declare breaks (MyClass :a :t => Proxy :a -> String))
  ;; (define (breaks x)
  ;;   (catch (progn
  ;;            (to-zero-prx x)
  ;;            "Runs")
  ;;     (_ "Fails")))

  (declare workaround (MyClass :a :t => Proxy :a -> String))
  (define (workaround x)
    (let f = (fn ()
               (to-zero-prx x)
               "Runs"))
    (catch (inline (f))
      (_ "Fails")))

  (declare also-works (MyClass :a Integer => Proxy :a -> Integer))
  (define (also-works x)
    (catch (progn
             (to-zero-prx x))
      (_ -1000)))
  )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions