Skip to content

Commit fb06b74

Browse files
committed
Revive top-level var bindings
1 parent 24c3751 commit fb06b74

File tree

3 files changed

+44
-64
lines changed

3 files changed

+44
-64
lines changed

parser-typechecker/src/Unison/Typechecker/Context.hs

+38-51
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,6 @@ scope :: PathElement v loc -> M v loc a -> M v loc a
480480
scope p (MT m) = MT \ppe pmcSwitch datas effects env -> mapErrors (scope' p) (m ppe pmcSwitch datas effects env)
481481

482482
newtype Context v loc = Context [(Element v loc, Info v loc)]
483-
deriving stock (Show)
484483

485484
data Info v loc = Info
486485
{ existentialVars :: Set v, -- set of existentials seen so far
@@ -489,7 +488,6 @@ data Info v loc = Info
489488
termVarAnnotations :: Map v (Type v loc),
490489
allVars :: Set v -- all variables seen so far
491490
}
492-
deriving stock (Show)
493491

494492
-- | The empty context
495493
context0 :: Context v loc
@@ -1083,43 +1081,35 @@ generalizeExistentials' t =
10831081
isExistential TypeVar.Existential {} = True
10841082
isExistential _ = False
10851083

1086-
noteBindingType ::
1087-
forall v loc.
1084+
noteTopLevelType ::
10881085
(Ord loc, Var v) =>
1089-
Term.IsTop ->
1090-
loc ->
1091-
v ->
1086+
ABT.Subst f v a ->
10921087
Term v loc ->
10931088
Type v loc ->
10941089
M v loc ()
1095-
noteBindingType top _span v binding typ = case binding of
1090+
noteTopLevelType e binding typ = case binding of
10961091
Term.Ann' strippedBinding _ -> do
10971092
inferred <- (Just <$> synthesizeTop strippedBinding) `orElse` pure Nothing
10981093
case inferred of
10991094
Nothing -> do
1100-
let v = Var.reset v
1101-
let t = generalizeAndUnTypeVar typ
1102-
let redundant = False
1103-
note [(v, t, redundant)]
1095+
btw $
1096+
topLevelComponent
1097+
[(Var.reset (ABT.variable e), generalizeAndUnTypeVar typ, False)]
11041098
Just inferred -> do
11051099
redundant <- isRedundant typ inferred
1106-
note [(Var.reset v, generalizeAndUnTypeVar typ, redundant)]
1100+
btw $
1101+
topLevelComponent
1102+
[(Var.reset (ABT.variable e), generalizeAndUnTypeVar typ, redundant)]
11071103
-- The signature didn't exist, so was definitely redundant
1108-
_ ->
1109-
note
1110-
[(Var.reset v, generalizeAndUnTypeVar typ, True)]
1111-
where
1112-
note :: (Var v) => [(v, Type.Type v loc, RedundantTypeAnnotation)] -> M v loc ()
1113-
note comps = do
1114-
-- Also note top-level components as standard let bindings for the LSP
1115-
-- for_ comps \(v, t, _r) -> noteVarBinding v span t
1116-
when top (btw $ topLevelComponent comps)
1117-
1104+
_ -> do
1105+
btw $
1106+
topLevelComponent
1107+
[(Var.reset (ABT.variable e), generalizeAndUnTypeVar typ, True)]
11181108
-- | Take note of the types and locations of all bindings, including let bindings, letrec
11191109
-- bindings, lambda argument bindings and top-level bindings.
11201110
-- This information is used to provide information to the LSP after typechecking.
1121-
_noteVarBinding :: (Var v) => v -> loc -> Type.Type v loc -> M v loc ()
1122-
_noteVarBinding _v _span _t = pure () -- btw $ VarBinding v span t
1111+
noteVarBinding :: (Var v) => v -> loc -> Type.Type v loc -> M v loc ()
1112+
noteVarBinding v span t = btw $ VarBinding v span t
11231113

11241114
synthesizeTop ::
11251115
(Var v) =>
@@ -1237,7 +1227,8 @@ synthesizeWanted abt@(Term.Let1Top' top binding e) = do
12371227
appendContext [Ann v' tbinding]
12381228
(t, w) <- synthesize (ABT.bindInheritAnnotation e (Term.var () v'))
12391229
t <- applyM t
1240-
noteBindingType top (ABT.annotation abt) (ABT.variable e) binding tbinding
1230+
when top $ noteTopLevelType e binding tbinding
1231+
noteVarBinding (ABT.variable e) (ABT.annotation abt) (TypeVar.lowerType tbinding)
12411232
want <- coalesceWanted w wb
12421233
-- doRetract $ Ann v' tbinding
12431234
pure (t, want)
@@ -1334,7 +1325,6 @@ synthesizeWanted e
13341325
let it = existential' l B.Blank i
13351326
ot = existential' l B.Blank o
13361327
et = existential' l B.Blank e
1337-
13381328
appendContext $
13391329
[existential i, existential e, existential o, Ann arg it]
13401330
when (Var.typeOf i == Var.Delay) $ do
@@ -1348,9 +1338,8 @@ synthesizeWanted e
13481338
ctx <- getContext
13491339
let t = apply ctx $ Type.arrow l it (Type.effect l [et] ot)
13501340

1351-
-- TODO revive
1352-
-- let solvedInputType = fromMaybe it . fmap Type.getPolytype $ Map.lookup i . solvedExistentials . info $ ctx
1353-
-- noteVarBinding i l (TypeVar.lowerType $ solvedInputType)
1341+
let solvedInputType = fromMaybe it . fmap Type.getPolytype $ Map.lookup i . solvedExistentials . info $ ctx
1342+
noteVarBinding i l (TypeVar.lowerType $ solvedInputType)
13541343
pure (t, [])
13551344
| Term.If' cond t f <- e = do
13561345
cwant <- scope InIfCond $ check cond (Type.boolean l)
@@ -1853,7 +1842,7 @@ annotateLetRecBindings ::
18531842
Term.IsTop ->
18541843
((v -> M v loc v) -> M v loc ([(v, Term v loc)], Term v loc)) ->
18551844
M v loc (Term v loc)
1856-
annotateLetRecBindings _span isTop letrec =
1845+
annotateLetRecBindings span isTop letrec =
18571846
-- If this is a top-level letrec, then emit a TopLevelComponent note,
18581847
-- which asks if the user-provided type annotations were needed.
18591848
if isTop
@@ -1878,9 +1867,8 @@ annotateLetRecBindings _span isTop letrec =
18781867
topLevelComponent ((\(v, b) -> (Var.reset v, b, False)) . unTypeVar <$> vts)
18791868
pure body
18801869
else do -- If this isn't a top-level letrec, then we don't have to do anything special
1881-
(body, _vts) <- annotateLetRecBindings' True
1882-
-- TODO revive
1883-
-- for_ vts \(v, t) -> noteVarBinding v span (TypeVar.lowerType t)
1870+
(body, vts) <- annotateLetRecBindings' True
1871+
for_ vts \(v, t) -> noteVarBinding v span (TypeVar.lowerType t)
18841872
pure body
18851873
where
18861874
annotateLetRecBindings' useUserAnnotations = do
@@ -1906,8 +1894,7 @@ annotateLetRecBindings _span isTop letrec =
19061894
-- Anything else, just make up a fresh existential
19071895
-- which will be refined during typechecking of the binding
19081896
vt <- extendExistential v
1909-
let typ = existential' (loc binding) B.Blank vt
1910-
pure $ (e, typ)
1897+
pure $ (e, existential' (loc binding) B.Blank vt)
19111898
(bindings, bindingTypes) <- unzip <$> traverse f bindings
19121899
appendContext (zipWith Ann vs bindingTypes)
19131900
-- check each `bi` against its type
@@ -1925,8 +1912,9 @@ annotateLetRecBindings _span isTop letrec =
19251912
gen bindingType _arity = generalizeExistentials ctx2 bindingType
19261913
bindingTypesGeneralized = zipWith gen bindingTypes bindingArities
19271914
annotations = zipWith Ann vs bindingTypesGeneralized
1928-
-- for_ (zip3 vs bindings bindingTypesGeneralized) \(v, b, t) -> do
1929-
-- noteVarBinding v (loc b) (TypeVar.lowerType t)
1915+
-- TODO: is this right?
1916+
for_ (zip3 vs bindings bindingTypesGeneralized) \(v, b, t) -> do
1917+
noteVarBinding v (loc b) (TypeVar.lowerType t)
19301918
appendContext annotations
19311919
pure (body, vs `zip` bindingTypesGeneralized)
19321920

@@ -2230,7 +2218,7 @@ coalesceWanted' keep ((loc, n) : new) old
22302218
if keep u
22312219
then pure (new, (loc, n) : old)
22322220
else do
2233-
defaultAbility n
2221+
_ <- defaultAbility n
22342222
pure (new, old)
22352223
coalesceWanted new old
22362224
| otherwise = coalesceWanted' keep new ((loc, n) : old)
@@ -2465,7 +2453,7 @@ checkWanted want (Term.Lam' body) (Type.Arrow'' i es o) = do
24652453
body <- pure $ ABT.bindInheritAnnotation body (Term.var () x)
24662454
checkWithAbilities es body o
24672455
pure want
2468-
checkWanted want _abt@(Term.Let1Top' top binding m) t = do
2456+
checkWanted want abt@(Term.Let1Top' top binding m) t = do
24692457
(tbinding, wbinding) <- synthesizeBinding top binding
24702458
want <- coalesceWanted wbinding want
24712459
v <- ABT.freshen m freshenVar
@@ -2474,8 +2462,7 @@ checkWanted want _abt@(Term.Let1Top' top binding m) t = do
24742462
-- enforce that actions in a block have type ()
24752463
subtype tbinding (DDB.unitType (ABT.annotation binding))
24762464
extendContext (Ann v tbinding)
2477-
-- TODO revive
2478-
-- noteVarBinding v (ABT.annotation abt) (TypeVar.lowerType tbinding)
2465+
noteVarBinding v (ABT.annotation abt) (TypeVar.lowerType tbinding)
24792466
checkWanted want (ABT.bindInheritAnnotation m (Term.var () v)) t
24802467
checkWanted want (Term.LetRecNamed' [] m) t =
24812468
checkWanted want m t
@@ -3414,15 +3401,15 @@ instance (Var v) => Show (Element v loc) where
34143401
++ TP.prettyStr Nothing PPE.empty t
34153402
show (Marker v) = "|" ++ Text.unpack (Var.name v) ++ "|"
34163403

3417-
-- instance (Ord loc, Var v) => Show (Context v loc) where
3418-
-- show ctx@(Context es) = "Γ\n " ++ (intercalate "\n " . map (showElem ctx . fst)) (reverse es)
3419-
-- where
3420-
-- showElem _ctx (Var v) = case v of
3421-
-- TypeVar.Universal x -> "@" <> show x
3422-
-- e -> show e
3423-
-- showElem ctx (Solved _ v (Type.Monotype t)) = "'" ++ Text.unpack (Var.name v) ++ " = " ++ TP.prettyStr Nothing PPE.empty (apply ctx t)
3424-
-- showElem ctx (Ann v t) = Text.unpack (Var.name v) ++ " : " ++ TP.prettyStr Nothing PPE.empty (apply ctx t)
3425-
-- showElem _ (Marker v) = "|" ++ Text.unpack (Var.name v) ++ "|"
3404+
instance (Ord loc, Var v) => Show (Context v loc) where
3405+
show ctx@(Context es) = "Γ\n " ++ (intercalate "\n " . map (showElem ctx . fst)) (reverse es)
3406+
where
3407+
showElem _ctx (Var v) = case v of
3408+
TypeVar.Universal x -> "@" <> show x
3409+
e -> show e
3410+
showElem ctx (Solved _ v (Type.Monotype t)) = "'" ++ Text.unpack (Var.name v) ++ " = " ++ TP.prettyStr Nothing PPE.empty (apply ctx t)
3411+
showElem ctx (Ann v t) = Text.unpack (Var.name v) ++ " : " ++ TP.prettyStr Nothing PPE.empty (apply ctx t)
3412+
showElem _ (Marker v) = "|" ++ Text.unpack (Var.name v) ++ "|"
34263413

34273414
instance (Monad f) => Monad (MT v loc f) where
34283415
return = pure

unison-cli/src/Unison/LSP/FileAnalysis.hs

+3-11
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,7 @@ checkFile doc = runMaybeT do
106106
Result.Result _ (Just parsedFile) -> do
107107
typecheckingEnv <- computeTypecheckingEnvironment (ShouldUseTndr'Yes parsingEnv) cb ambientAbilities parsedFile
108108
let Result.Result typecheckingNotes maybeTypecheckedFile = FileParsers.synthesizeFile typecheckingEnv parsedFile
109-
-- This is silly, but after applying TDNR we can just re-typecheck the already substituted file to get the correct types of
110-
-- local bindings from after TDNR.
111-
_localBindings <-
112-
-- maybeTypecheckedFile & foldMapM \tf -> do
113-
-- let parsedFile = UF.discardTypes tf
114-
-- typecheckingEnv' <- computeTypecheckingEnvironment ShouldUseTndr'No cb ambientAbilities parsedFile
115-
-- let Result.Result afterTDNRTypecheckingNotes' _maybeTypecheckedFile' = FileParsers.synthesizeFile typecheckingEnv' parsedFile
116-
-- Debug.debugM Debug.Temp "After typechecking notes" afterTDNRTypecheckingNotes'
117-
-- afterTDNRTypecheckingNotes'
109+
localBindings <-
118110
typecheckingNotes
119111
& Foldable.toList
120112
& reverse -- Type notes that come later in typechecking have more information filled in.
@@ -123,10 +115,10 @@ checkFile doc = runMaybeT do
123115
Cv.annToRange loc & foldMap (\(LSP.Range start end) -> (keyedSingleton v (start, end) typ))
124116
_ -> mempty
125117
& pure
126-
pure (mempty, typecheckingNotes, Just parsedFile, maybeTypecheckedFile)
118+
pure (localBindings, typecheckingNotes, Just parsedFile, maybeTypecheckedFile)
127119

128120
Debug.debugM Debug.Temp "BEFORE Local Bindings" ()
129-
-- Debug.debugM Debug.Temp "My Local Bindings" localBindingTypes
121+
Debug.debugM Debug.Temp "My Local Bindings" localBindingTypes
130122
Debug.debugM Debug.Temp "AFTER Local Bindings" ()
131123
filePPED <- lift $ ppedForFileHelper parsedFile typecheckedFile
132124
(errDiagnostics, codeActions) <- lift $ analyseFile fileUri srcText filePPED notes

unison-cli/src/Unison/Main.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import Unison.CommandLine.Main qualified as CommandLine
7979
import Unison.CommandLine.Types qualified as CommandLine
8080
import Unison.CommandLine.Welcome (CodebaseInitStatus (..))
8181
import Unison.CommandLine.Welcome qualified as Welcome
82+
import Unison.LSP qualified as LSP
8283
import Unison.Parser.Ann (Ann)
8384
import Unison.Prelude
8485
import Unison.PrettyTerminal qualified as PT
@@ -136,7 +137,7 @@ main version = do
136137
-- hSetBuffering stdout NoBuffering -- cool
137138
(renderUsageInfo, globalOptions, command) <- parseCLIArgs progName (Text.unpack (Version.gitDescribeWithDate version))
138139
nrtp <- fixNativeRuntimePath (nativeRuntimePath globalOptions)
139-
let GlobalOptions {codebasePathOption = mCodePathOption, exitOption} = globalOptions
140+
let GlobalOptions {codebasePathOption = mCodePathOption, exitOption, lspFormattingConfig} = globalOptions
140141
withConfig mCodePathOption \config -> do
141142
currentDir <- getCurrentDirectory
142143
case command of
@@ -311,7 +312,7 @@ main version = do
311312
-- prevent UCM from shutting down properly. Hopefully we can re-enable LSP on
312313
-- Windows when we move to GHC 9.*
313314
-- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/1224
314-
-- void . Ki.fork scope $ LSP.spawnLsp lspFormattingConfig theCodebase runtime (readTVar rootCausalHashVar) (readTVar pathVar)
315+
void . Ki.fork scope $ LSP.spawnLsp lspFormattingConfig theCodebase runtime (readTVar rootCausalHashVar) (readTVar pathVar)
315316
Server.startServer (Backend.BackendEnv {Backend.useNamesIndex = False}) codebaseServerOpts sbRuntime theCodebase $ \baseUrl -> do
316317
case exitOption of
317318
DoNotExit -> do

0 commit comments

Comments
 (0)