Fix (and test) for SourceForge bug 1161624: erroneous rejection of
foo = proc x -> arr (\y -> y-1) -< x
Now open a new level for the left side of -<, so that variables bound
in the proc are illegal, but variables bound in the expression are OK.
Note that the levels gimmick doesn't really implement holes in the
scope: it rules out nasty obfuscations like
foo x = proc x -> arr (\y -> x-1) -< x
Also added the same treatment to the head of a `form', where it was
missing.
(for STABLE)
-----------------------------------------------------------------
-----------------------------------------------------------------
--- Arrow ``forms'' (| e |) c1 .. cn
+-- Arrow ``forms'' (| e c1 .. cn |)
--
-- G |-b c : [s1 .. sm] s
-- pop(G) |- e : forall w. b ((w,s1) .. sm) s
-- -> a ((w,t1) .. tn) t
-- e \not\in (s, s1..sm, t, t1..tn)
-- ----------------------------------------------
--
-- G |-b c : [s1 .. sm] s
-- pop(G) |- e : forall w. b ((w,s1) .. sm) s
-- -> a ((w,t1) .. tn) t
-- e \not\in (s, s1..sm, t, t1..tn)
-- ----------------------------------------------
--- G |-a (| e |) c : [t1 .. tn] t
+-- G |-a (| e c |) : [t1 .. tn] t
tc_cmd env cmd@(HsArrForm expr fixity cmd_args) (cmd_stk, res_ty)
= addErrCtxt (cmdCtxt cmd) $
tc_cmd env cmd@(HsArrForm expr fixity cmd_args) (cmd_stk, res_ty)
= addErrCtxt (cmdCtxt cmd) $
- ; (expr', lie) <- getLIE (tcCheckRho expr e_ty)
+ ; (expr', lie) <- popArrowBinders (getLIE (tcCheckRho expr e_ty))
; inst_binds <- tcSimplifyCheck sig_msg [w_tv] [] lie
-- Check that the polymorphic variable hasn't been unified with anything
; inst_binds <- tcSimplifyCheck sig_msg [w_tv] [] lie
-- Check that the polymorphic variable hasn't been unified with anything
where
pop (ArrCtxt {proc_level = curr_lvl, proc_banned = banned})
= ASSERT( not (curr_lvl `elem` banned) )
where
pop (ArrCtxt {proc_level = curr_lvl, proc_banned = banned})
= ASSERT( not (curr_lvl `elem` banned) )
- ArrCtxt {proc_level = curr_lvl, proc_banned = curr_lvl : banned}
+ ArrCtxt {proc_level = curr_lvl + 1, proc_banned = curr_lvl : banned}
getBannedProcLevels :: TcM [ProcLevel]
= do { env <- getLclEnv; return (proc_banned (tcl_arrow_ctxt env)) }
getBannedProcLevels :: TcM [ProcLevel]
= do { env <- getLclEnv; return (proc_banned (tcl_arrow_ctxt env)) }
---------------------------
-- In arrow notation, a variable bound by a proc (or enclosed let/kappa)
---------------------------
-- In arrow notation, a variable bound by a proc (or enclosed let/kappa)
--- is not in scope to the left of an arrow tail (-<). For example
+-- is not in scope to the left of an arrow tail (-<) or the head of (|..|).
+-- For example
--
-- proc x -> (e1 -< e2)
--
--
-- proc x -> (e1 -< e2)
--
-- a bit complicated:
--
-- let x = 3 in
-- a bit complicated:
--
-- let x = 3 in
--- prox y -> (proc z -> e1) -< e2
+-- proc y -> (proc z -> e1) -< e2
--
-- Here, x and z are in scope in e1, but y is not. Here's how we track this:
-- a) Assign an "proc level" to each proc, being the number of
--
-- Here, x and z are in scope in e1, but y is not. Here's how we track this:
-- a) Assign an "proc level" to each proc, being the number of
-- enclosing proc.
-- c) Keep a list of out-of-scope procs. When moving to the left of
-- an arrow-tail, add the proc-level of the immediately enclosing
-- enclosing proc.
-- c) Keep a list of out-of-scope procs. When moving to the left of
-- an arrow-tail, add the proc-level of the immediately enclosing
+-- proc to the list, and increment the proc-level so that variables
+-- bound inside the expression are in scope.
-- d) When looking up a variable, complain if its proc-level is in
-- the banned list
-- d) When looking up a variable, complain if its proc-level is in
-- the banned list