Skip to content

Commit 8e2cd28

Browse files
Jason Walkerstylewarning
authored andcommitted
Fix a bug with nested fundep instances
Previously, when one type would contain an instance of a class and it used that contained instance's instance to supply its own instance of the class, then it would fail to compile. The issue was that define-instance removes the class constraints before checking the types of the instance methods. Normally that's not a problem because they're entailed. But fundep-entail% checks for structural similarity, not entailment. To fix it, fundep-entail now skips fundep-entail% for any predicate that was entailed by the environment. The tests pass, and the commit includes a regression test that failed with the fix removed and passes now.
1 parent 5ecce30 commit 8e2cd28

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/typechecker/context-reduction.lisp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
;; Context reduction
3232
;;
3333

34-
3534
(defun true (x)
3635
(if x
3736
t
@@ -294,7 +293,10 @@ the type variables of the class D.
294293
:with preds := (expand preds)
295294
:with subs := nil
296295
:for pred :in preds
297-
:for new-subs := (fundep-entail% env expr-preds pred known-tyvars)
296+
:for new-subs :=
297+
(if (entail env expr-preds pred)
298+
'()
299+
(fundep-entail% env expr-preds pred known-tyvars))
298300
:do (setf subs (compose-substitution-lists subs new-subs))
299301
:finally (return subs))))
300302

tests/fundep-tests.lisp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,31 @@
258258
(declare foo (MonadChain :h :h => :h String))
259259
(define foo
260260
bar)"))
261+
262+
(deftest fundep-nested-fundep-instances ()
263+
;; See https://github.com/coalton-lang/coalton/pull/1743
264+
(check-coalton-types
265+
"
266+
(define-class (FundepClass :a :b (:a -> :b))
267+
(use-a (:a -> Unit)))
268+
269+
(define-type (BaseType :a :b)
270+
(BaseType :a))
271+
272+
(declare unwrap% (BaseType :a :b -> :a))
273+
(define (unwrap% (BaseType val))
274+
val)
275+
276+
(define-instance (FundepClass :a :b => FundepClass (BaseType :a :b) (List :b))
277+
(inline)
278+
(define (use-a grouped)
279+
(use-a (unwrap% grouped))))
280+
281+
(define-struct (WrapperType :a)
282+
(inner-base-type (BaseType :a Unit)))
283+
284+
(define-instance (FundepClass (BaseType :a Unit) (List Unit)
285+
=> FundepClass (WrapperType :a) Unit)
286+
(inline)
287+
(define (use-a wrapper)
288+
(use-a (.inner-base-type wrapper))))"))

0 commit comments

Comments
 (0)