@@ -377,7 +377,7 @@ topLevelComponent = TopLevelComponent . fmap (over _2 removeSyntheticTypeVars)
377
377
-- generalize types stored in the notes.
378
378
substituteSolved ::
379
379
(Var v , Ord loc ) =>
380
- [ Element v loc ] ->
380
+ Map v ( Monotype v loc ) ->
381
381
InfoNote v loc ->
382
382
InfoNote v loc
383
383
substituteSolved ctx (SolvedBlank b v t) =
@@ -473,7 +473,7 @@ scope' p (ErrorNote cause path) = ErrorNote cause (path `mappend` pure p)
473
473
scope :: PathElement v loc -> M v loc a -> M v loc a
474
474
scope p (MT m) = MT \ ppe pmcSwitch datas effects env -> mapErrors (scope' p) (m ppe pmcSwitch datas effects env)
475
475
476
- newtype Context v loc = Context [(Element v loc , Info v loc )]
476
+ data Context v loc = Context [(Element v loc , Info v loc )] ( Map v ( Monotype v loc ))
477
477
478
478
data Info v loc = Info
479
479
{ existentialVars :: Set v , -- set of existentials seen so far
@@ -484,14 +484,25 @@ data Info v loc = Info
484
484
}
485
485
486
486
-- | The empty context
487
- context0 :: Context v loc
488
- context0 = Context []
487
+ context0 :: Ord v => Context v loc
488
+ context0 = Context [] mempty
489
+
490
+ context :: Ord v => [(Element v loc , Info v loc )] -> Context v loc
491
+ context elems = Context elems (computeSolvedExistentials (fst <$> elems))
492
+
493
+ computeSolvedExistentials :: Ord a => [Element a loc ] -> Map a (Monotype a loc )
494
+ computeSolvedExistentials elems =
495
+ elems & mapMaybe (\ case
496
+ Solved _ v t -> Just (v, t)
497
+ _ -> Nothing
498
+ )
499
+ & Map. fromList
489
500
490
501
occursAnn :: (Var v ) => (Ord loc ) => TypeVar v loc -> Context v loc -> Bool
491
- occursAnn v (Context eis) = any p es
502
+ occursAnn v (Context eis solved ) = any p es
492
503
where
493
504
es = fst <$> eis
494
- p (Ann _ ty) = v `Set.member` ABT. freeVars (applyCtx es ty)
505
+ p (Ann _ ty) = v `Set.member` ABT. freeVars (applyCtx solved ty)
495
506
p _ = False
496
507
497
508
-- | Focuses on the first element in the list that satisfies the predicate.
@@ -505,38 +516,38 @@ focusAt p xs = go [] xs
505
516
-- | Delete from the end of this context up to and including
506
517
-- the given `Element`. Returns `Nothing` if the element is not found.
507
518
retract0 :: (Var v , Ord loc ) => Element v loc -> Context v loc -> Maybe (Context v loc , [Element v loc ])
508
- retract0 e (Context ctx) = case focusAt (\ (e', _) -> e' == e) ctx of
519
+ retract0 e (Context ctx _ ) = case focusAt (\ (e', _) -> e' == e) ctx of
509
520
Just (discarded, _, remaining) ->
510
521
-- note: no need to recompute used variables; any suffix of the
511
522
-- context snoc list is also a valid context
512
- Just (Context remaining, map fst discarded)
523
+ Just (context remaining, map fst discarded)
513
524
Nothing -> Nothing
514
525
515
526
-- | Adds a marker to the end of the context, runs the `body` and then discards
516
527
-- from the end of the context up to and including the marker. Returns the result
517
528
-- of `body` and the discarded context (not including the marker), respectively.
518
529
-- Freshened `markerHint` is used to create the marker.
519
- markThenRetract :: (Var v , Ord loc ) => v -> M v loc a -> M v loc (a , [Element v loc ])
530
+ markThenRetract :: (Var v , Ord loc ) => v -> M v loc a -> M v loc (a , [Element v loc ], Map v ( Monotype v loc ) )
520
531
markThenRetract hint body =
521
532
markThenCallWithRetract hint \ retract -> adjustNotes do
522
533
r <- body
523
- ctx <- retract
524
- pure ((r, ctx), substituteSolved ctx )
534
+ ( ctx, solved) <- retract
535
+ pure ((r, ctx, solved ), substituteSolved solved )
525
536
526
537
markThenRetract0 :: (Var v , Ord loc ) => v -> M v loc a -> M v loc ()
527
538
markThenRetract0 markerHint body = () <$ markThenRetract markerHint body
528
539
529
540
markThenCallWithRetract ::
530
541
(Var v , Ord loc ) =>
531
542
v ->
532
- (M v loc [Element v loc ] -> M v loc a ) ->
543
+ (M v loc ( [Element v loc ], Map v ( Monotype v loc )) -> M v loc a ) ->
533
544
M v loc a
534
545
markThenCallWithRetract hint k = do
535
546
v <- freshenVar hint
536
547
extendContext (Marker v)
537
548
k (doRetract (Marker v))
538
549
where
539
- doRetract :: (Var v , Ord loc ) => Element v loc -> M v loc [Element v loc ]
550
+ doRetract :: (Var v , Ord loc ) => Element v loc -> M v loc ( [Element v loc ], Map v ( Monotype v loc ))
540
551
doRetract e = do
541
552
ctx <- getContext
542
553
case retract0 e ctx of
@@ -554,7 +565,7 @@ markThenCallWithRetract hint k = do
554
565
inst = apply ctx
555
566
Foldable. traverse_ go (solved ++ unsolved)
556
567
setContext t
557
- pure discarded
568
+ pure ( discarded, computeSolvedExistentials discarded)
558
569
559
570
-- unsolved' :: Context v loc -> [(B.Blank loc, v)]
560
571
-- unsolved' (Context ctx) = [(b,v) | (Existential b v, _) <- ctx]
@@ -570,11 +581,11 @@ breakAt ::
570
581
Element v loc ->
571
582
Context v loc ->
572
583
Maybe (Context v loc , Element v loc , [Element v loc ])
573
- breakAt m (Context xs) =
584
+ breakAt m (Context xs _ ) =
574
585
case focusAt (\ (e, _) -> e === m) xs of
575
586
Just (r, m, l) ->
576
587
-- l is a suffix of xs and is already a valid context
577
- Just (Context l, fst m, map fst r)
588
+ Just (context l, fst m, map fst r)
578
589
Nothing -> Nothing
579
590
where
580
591
Existential _ v === Existential _ v2 | v == v2 = True
@@ -649,7 +660,7 @@ appendContext = traverse_ extendContext
649
660
markRetained :: (Var v , Ord loc ) => Set v -> M v loc ()
650
661
markRetained keep = setContext . marks =<< getContext
651
662
where
652
- marks (Context eis) = Context (fmap mark eis)
663
+ marks (Context eis _ ) = context (fmap mark eis)
653
664
mark (Existential B. Blank v, i)
654
665
| v `Set.member` keep = (Var (TypeVar. Existential B. Retain v), i)
655
666
mark (Solved B. Blank v t, i)
@@ -747,14 +758,14 @@ wellformedType c t = case t of
747
758
748
759
-- | Return the `Info` associated with the last element of the context, or the zero `Info`.
749
760
info :: (Ord v ) => Context v loc -> Info v loc
750
- info (Context [] ) = Info mempty mempty mempty mempty mempty
751
- info (Context ((_, i) : _)) = i
761
+ info (Context [] _ ) = Info mempty mempty mempty mempty mempty
762
+ info (Context ((_, i) : _) _ ) = i
752
763
753
764
-- | Add an element onto the end of this `Context`. Takes `O(log N)` time,
754
765
-- including updates to the accumulated `Info` value.
755
766
-- Fail if the new context is not well formed (see Figure 7 of paper).
756
767
extend' :: (Var v ) => Element v loc -> Context v loc -> Either (CompilerBug v loc ) (Context v loc )
757
- extend' e c@ (Context ctx) = Context . (: ctx) . (e,) <$> i'
768
+ extend' e c@ (Context ctx _ ) = context . (: ctx) . (e,) <$> i'
758
769
where
759
770
Info es ses us uas vs = info c
760
771
-- see figure 7
@@ -946,8 +957,8 @@ apply :: (Var v, Ord loc) => Context v loc -> Type v loc -> Type v loc
946
957
apply ctx = apply' (solvedExistentials . info $ ctx)
947
958
948
959
-- | Replace any existentials with their solution in the context (given as a list of elements)
949
- applyCtx :: (Var v , Ord loc ) => [ Element v loc ] -> Type v loc -> Type v loc
950
- applyCtx elems = apply' $ Map. fromList [(v, sa) | Solved _ v sa <- elems]
960
+ applyCtx :: (Var v , Ord loc ) => Map v ( Monotype v loc ) -> Type v loc -> Type v loc
961
+ applyCtx = apply'
951
962
952
963
apply' :: (Var v , Ord loc ) => Map v (Monotype v loc ) -> Type v loc -> Type v loc
953
964
apply' _ t | Set. null (Type. freeVars t) = t
@@ -1107,16 +1118,14 @@ synthesizeTop ::
1107
1118
M v loc (Type v loc )
1108
1119
synthesizeTop tm = do
1109
1120
(ty, want) <- synthesize tm
1110
- ctx <- getContext
1111
- want <- substAndDefaultWanted want (out ctx)
1121
+ ctx@ ( Context es solved) <- getContext
1122
+ want <- substAndDefaultWanted want (fst <$> es) solved
1112
1123
when (not $ null want) . failWith $ do
1113
1124
AbilityCheckFailure
1114
1125
[]
1115
1126
(Type. flattenEffects . snd =<< want)
1116
1127
ctx
1117
1128
applyM ty
1118
- where
1119
- out (Context es) = fmap fst es
1120
1129
1121
1130
-- | Synthesize the type of the given term, updating the context in
1122
1131
-- the process. Also collect wanted abilities.
@@ -1222,11 +1231,11 @@ synthesizeWanted (Term.Let1Top' top binding e) = do
1222
1231
pure (t, want)
1223
1232
synthesizeWanted (Term. LetRecNamed' [] body) = synthesizeWanted body
1224
1233
synthesizeWanted (Term. LetRecTop' isTop letrec) = do
1225
- ((t, want), ctx2) <- markThenRetract (Var. named " let-rec-marker" ) $ do
1234
+ ((t, want), ctx2, solved2 ) <- markThenRetract (Var. named " let-rec-marker" ) $ do
1226
1235
e <- annotateLetRecBindings isTop letrec
1227
1236
synthesize e
1228
- want <- substAndDefaultWanted want ctx2
1229
- pure (generalizeExistentials ctx2 t, want)
1237
+ want <- substAndDefaultWanted want ctx2 solved2
1238
+ pure (generalizeExistentials ctx2 solved2 t, want)
1230
1239
synthesizeWanted (Term. Handle' h body) = do
1231
1240
-- To synthesize a handle block, we first synthesize the handler h,
1232
1241
-- then push its allowed abilities onto the current ambient set when
@@ -1403,10 +1412,10 @@ synthesizeBinding top binding = do
1403
1412
else
1404
1413
if top
1405
1414
then do
1406
- ctx <- retract
1407
- pure ((generalizeExistentials ctx tb, [] ), substituteSolved ctx )
1415
+ ( ctx, solved) <- retract
1416
+ pure ((generalizeExistentials ctx solved tb, [] ), substituteSolved solved )
1408
1417
else do
1409
- ctx <- retract
1418
+ ( ctx, solved) <- retract
1410
1419
-- Note: this is conservative about what we avoid
1411
1420
-- generalizing. Right now only TDNR causes variables to be
1412
1421
-- retained. It might be possible to make this happen for any
@@ -1423,7 +1432,7 @@ synthesizeBinding top binding = do
1423
1432
| Solved b _ sa <- ctx,
1424
1433
retain b,
1425
1434
TypeVar. Existential _ v <-
1426
- Set. toList . ABT. freeVars . applyCtx ctx $ Type. getPolytype sa
1435
+ Set. toList . ABT. freeVars . applyCtx solved $ Type. getPolytype sa
1427
1436
]
1428
1437
keep = Set. fromList (erecs ++ srecs)
1429
1438
p (Existential _ v)
@@ -1433,8 +1442,8 @@ synthesizeBinding top binding = do
1433
1442
(repush, discard) = partitionEithers $ fmap p ctx
1434
1443
appendContext repush
1435
1444
markRetained keep
1436
- let tf = generalizeExistentials discard (applyCtx ctx tb)
1437
- pure ((tf, [] ), substituteSolved ctx )
1445
+ let tf = generalizeExistentials discard (computeSolvedExistentials discard) ( applyCtx solved tb)
1446
+ pure ((tf, [] ), substituteSolved solved )
1438
1447
1439
1448
getDataConstructorsAtType :: forall v loc . (Ord loc , Var v ) => Type v loc -> M v loc (EnumeratedConstructors (TypeVar v loc ) v loc )
1440
1449
getDataConstructorsAtType t0 = do
@@ -1856,7 +1865,7 @@ annotateLetRecBindings isTop letrec =
1856
1865
annotateLetRecBindings' useUserAnnotations = do
1857
1866
(bindings, body) <- letrec freshenVar
1858
1867
let vs = map fst bindings
1859
- ((bindings, bindingTypes), ctx2) <- markThenRetract Var. inferOther $ do
1868
+ ((bindings, bindingTypes), ctx2, solved2 ) <- markThenRetract Var. inferOther $ do
1860
1869
let f (v, binding) = case binding of
1861
1870
-- If user has provided an annotation, we use that
1862
1871
Term. Ann' e t | useUserAnnotations -> do
@@ -1891,7 +1900,7 @@ annotateLetRecBindings isTop letrec =
1891
1900
-- compute generalized types `gt1, gt2 ...` for each binding `b1, b2...`;
1892
1901
-- add annotations `v1 : gt1, v2 : gt2 ...` to the context
1893
1902
let bindingArities = Term. arity <$> bindings
1894
- gen bindingType _arity = generalizeExistentials ctx2 bindingType
1903
+ gen bindingType _arity = generalizeExistentials ctx2 solved2 bindingType
1895
1904
bindingTypesGeneralized = zipWith gen bindingTypes bindingArities
1896
1905
annotations = zipWith Ann vs bindingTypesGeneralized
1897
1906
appendContext annotations
@@ -2067,12 +2076,12 @@ forcedData ty = Type.freeVars ty
2067
2076
2068
2077
-- | Apply the context to the input type, then convert any unsolved existentials
2069
2078
-- to universals.
2070
- generalizeExistentials :: (Var v , Ord loc ) => [Element v loc ] -> Type v loc -> Type v loc
2071
- generalizeExistentials ctx ty0 = generalizeP pred ctx ty
2079
+ generalizeExistentials :: (Var v , Ord loc ) => [Element v loc ] -> Map v ( Monotype v loc ) -> Type v loc -> Type v loc
2080
+ generalizeExistentials ctx solved ty0 = generalizeP pred ctx solved ty
2072
2081
where
2073
2082
gens = Set. fromList $ mapMaybe (fmap snd . existentialP) ctx
2074
2083
2075
- ty = discardCovariant gens $ applyCtx ctx ty0
2084
+ ty = discardCovariant gens $ applyCtx solved ty0
2076
2085
fvs = Type. freeVars ty
2077
2086
2078
2087
pred e
@@ -2086,9 +2095,10 @@ generalizeP ::
2086
2095
(Ord loc ) =>
2087
2096
(Element v loc -> Maybe (TypeVar v loc , v )) ->
2088
2097
[Element v loc ] ->
2098
+ Map v (Monotype v loc ) ->
2089
2099
Type v loc ->
2090
2100
Type v loc
2091
- generalizeP p ctx0 ty = foldr gen (applyCtx ctx0 ty) ctx
2101
+ generalizeP p ctx0 solved ty = foldr gen (applyCtx solved ty) ctx
2092
2102
where
2093
2103
ctx = mapMaybe p ctx0
2094
2104
@@ -2127,12 +2137,12 @@ checkScoped ::
2127
2137
M v loc (Type v loc , Wanted v loc )
2128
2138
checkScoped e (Type. Forall' body) = do
2129
2139
v <- ABT. freshen body freshenTypeVar
2130
- ((ty, want), pop) <- markThenRetract v $ do
2140
+ ((ty, want), pop, popSolved ) <- markThenRetract v $ do
2131
2141
x <- extendUniversal v
2132
2142
let e' = Term. substTypeVar (ABT. variable body) (universal' () x) e
2133
2143
checkScoped e' (ABT. bindInheritAnnotation body (universal' () x))
2134
- want <- substAndDefaultWanted want pop
2135
- pure (generalizeP variableP pop ty, want)
2144
+ want <- substAndDefaultWanted want pop popSolved
2145
+ pure (generalizeP variableP pop popSolved ty, want)
2136
2146
checkScoped e t = do
2137
2147
t <- existentializeArrows t
2138
2148
(t,) <$> check e t
@@ -2154,8 +2164,9 @@ markThenRetractWanted ::
2154
2164
v ->
2155
2165
M v loc (Wanted v loc ) ->
2156
2166
M v loc (Wanted v loc )
2157
- markThenRetractWanted v m =
2158
- markThenRetract v m >>= uncurry substAndDefaultWanted
2167
+ markThenRetractWanted v m = do
2168
+ (a, es, solved) <- markThenRetract v m
2169
+ substAndDefaultWanted a es solved
2159
2170
2160
2171
-- This function handles merging two sets of wanted abilities, along
2161
2172
-- with some pruning of the set. This means that coalescing a list
@@ -2261,9 +2272,10 @@ substAndDefaultWanted ::
2261
2272
(Ord loc ) =>
2262
2273
Wanted v loc ->
2263
2274
[Element v loc ] ->
2275
+ Map v (Monotype v loc ) ->
2264
2276
M v loc (Wanted v loc )
2265
- substAndDefaultWanted want ctx
2266
- | want <- (fmap . fmap ) (applyCtx ctx ) want,
2277
+ substAndDefaultWanted want ctx solved
2278
+ | want <- (fmap . fmap ) (applyCtx solved ) want,
2267
2279
want <- filter q want,
2268
2280
repush <- filter keep ctx =
2269
2281
appendContext repush *> coalesceWanted want []
@@ -3292,14 +3304,14 @@ synthesizeClosed' abilities term = do
3292
3304
-- save current context, for restoration when done
3293
3305
ctx0 <- getContext
3294
3306
setContext context0
3295
- (t, ctx) <- markThenRetract (Var. named " start" ) $ do
3307
+ (t, ctx, solved ) <- markThenRetract (Var. named " start" ) $ do
3296
3308
-- retract will cause notes to be written out for
3297
3309
-- any `Blank`-tagged existentials passing out of scope
3298
3310
(t, want) <- synthesize term
3299
3311
scope (InSynthesize term) $
3300
3312
t <$ subAbilities want abilities
3301
3313
setContext ctx0 -- restore the initial context
3302
- pure $ generalizeExistentials ctx t
3314
+ pure $ generalizeExistentials ctx solved t
3303
3315
3304
3316
-- Check if the given typechecking action succeeds.
3305
3317
succeeds :: M v loc a -> TotalM v loc Bool
@@ -3380,7 +3392,7 @@ instance (Var v) => Show (Element v loc) where
3380
3392
show (Marker v) = " |" ++ Text. unpack (Var. name v) ++ " |"
3381
3393
3382
3394
instance (Ord loc , Var v ) => Show (Context v loc ) where
3383
- show ctx@ (Context es) = " Γ\n " ++ (intercalate " \n " . map (showElem ctx . fst )) (reverse es)
3395
+ show ctx@ (Context es _ ) = " Γ\n " ++ (intercalate " \n " . map (showElem ctx . fst )) (reverse es)
3384
3396
where
3385
3397
showElem _ctx (Var v) = case v of
3386
3398
TypeVar. Universal x -> " @" <> show x
0 commit comments