This commit is contained in:
Leonardo de Moura 2021-05-22 19:07:09 -07:00
parent c426a816a1
commit b91e22af2b
5 changed files with 118 additions and 3 deletions

View file

@ -1150,6 +1150,14 @@ def checkReassignable (xs : Array Name) : M Unit := do
unless ctx.mutableVars.contains x do
throwInvalidReassignment x
def checkNotShadowingMutable (xs : Array Name) : M Unit := do
let throwInvalidShadowing (x : Name) : M Unit :=
throwError "mutable variable '{x.simpMacroScopes}' cannot be shadowed"
let ctx ← read
for x in xs do
if ctx.mutableVars.contains x then
throwInvalidShadowing x
@[inline] def withFor {α} (x : M α) : M α :=
withReader (fun ctx => { ctx with insideFor := true }) x
@ -1265,6 +1273,7 @@ mutual
let decl := doLetArrow[2]
if decl.getKind == `Lean.Parser.Term.doIdDecl then
let y := decl[0].getId
checkNotShadowingMutable #[y]
let doElem := decl[3]
let k ← withNewMutableVars #[y] (isMutableLet doLetArrow) (doSeqToCode doElems)
match isDoExpr? doElem with
@ -1396,6 +1405,7 @@ mutual
doSeqToCode (getDoSeqElems (getDoSeq auxDo) ++ doElems)
else withRef doFor do
let x := doForDecls[0][0]
withRef x <| checkNotShadowingMutable (← getPatternVarsEx x)
let xs := doForDecls[0][2]
let forElems := getDoSeqElems doFor[3]
let forInBodyCodeBlock ← withFor (doSeqToCode forElems)
@ -1432,6 +1442,7 @@ mutual
let alts ← matchAlts.mapM fun matchAlt => do
let patterns := matchAlt[1]
let vars ← getPatternsVarsEx patterns.getSepArgs
withRef patterns <| checkNotShadowingMutable vars
let rhs := matchAlt[3]
let rhs ← doSeqToCode (getDoSeqElems rhs)
pure { ref := matchAlt, vars := vars, patterns := patterns, rhs := rhs : Alt CodeBlock }
@ -1454,6 +1465,8 @@ mutual
let catches ← doTry[2].getArgs.mapM fun catchStx => do
if catchStx.getKind == `Lean.Parser.Term.doCatch then
let x := catchStx[1]
if x.isIdent then
withRef x <| checkNotShadowingMutable #[x.getId]
let optType := catchStx[2]
let c ← doSeqToCode (getDoSeqElems catchStx[4])
pure { x := x, optType := optType, codeBlock := c : Catch }
@ -1518,12 +1531,15 @@ mutual
let k := doElem.getKind
if k == `Lean.Parser.Term.doLet then
let vars ← getDoLetVars doElem
checkNotShadowingMutable vars
mkVarDeclCore vars doElem <$> withNewMutableVars vars (isMutableLet doElem) (doSeqToCode doElems)
else if k == `Lean.Parser.Term.doHave then
let var := getDoHaveVar doElem
checkNotShadowingMutable #[var]
mkVarDeclCore #[var] doElem <$> (doSeqToCode doElems)
else if k == `Lean.Parser.Term.doLetRec then
let vars ← getDoLetRecVars doElem
checkNotShadowingMutable vars
mkVarDeclCore vars doElem <$> (doSeqToCode doElems)
else if k == `Lean.Parser.Term.doReassign then
let vars ← getDoReassignVars doElem

View file

@ -63,7 +63,7 @@ do IO.setRandSeed seed
m := m.erase k
i := i + 1
check (sz m == a.size / 2)
let i := 0
i := 0
for (k, v) in a do
if i % 2 == 1 then
check (m.find? k == some v)

86
tests/lean/241.lean Normal file
View file

@ -0,0 +1,86 @@
def ex1 : IO Unit := do
let mut xs : Array Nat := #[]
let xs := xs -- Error
xs := xs.push 0
IO.println xs
def ex2 : IO Unit := do
let mut xs : Array Nat := #[]
let (xs, _) := (xs, 4) -- Error
xs := xs.push 0
IO.println xs
def ex3 : IO Unit := do
let mut xs : Array Nat := #[]
match (1, 2) with
| (xs, ys) => -- Error
xs := xs.push 0
IO.println xs
def ex4 : IO Unit := do
let mut xs : Array Nat := #[]
let (xs, _) ← pure (xs, 4) -- Error
xs := xs.push 0
IO.println xs
def ex5 : IO Unit := do
let mut xs : Array Nat := #[]
let xs ← pure xs -- Error
xs := xs.push 0
IO.println xs
def ex6 : IO Unit := do
let mut xs : Array Nat := #[]
if let some xs ← pure (some 4) then -- Error
IO.println xs
else
pure ()
def ex7 : IO Unit := do
let mut xs : Array Nat := #[]
if let some xs := some 4 then -- Error
IO.println xs
else
pure ()
def ex8 : IO Unit := do
let mut xs : Array Nat := #[]
if let some xs ← pure (some 4) then -- Error
IO.println xs
else
pure ()
def ex9 : IO Unit := do
let mut xs : Array Nat := #[]
try
IO.println xs
catch
| IO.Error.userError xs => -- Error
pure ()
| _ =>
pure ()
def ex10 : IO Unit := do
let mut xs : Array Nat := #[]
try
IO.println xs
catch xs => -- Error
pure ()
def ex11 : IO Unit := do
let mut xs : Array (Nat × Nat) := #[(1,2)]
for (xs, y) in xs do -- Error
xs := xs.push (0, 0)
IO.println xs
def ex12 : IO Unit := do
let mut xs : Array Nat := #[1,2,3]
for xs in xs do -- Error
xs := xs.push 0
IO.println xs
def ex13 : IO Unit := do
let mut xs : Array Nat := #[1,2,3]
for a in [:10], xs in [1,2,3] do -- Error
xs := xs.push 0
IO.println xs

View file

@ -0,0 +1,13 @@
241.lean:3:2-3:14: error: mutable variable 'xs' cannot be shadowed
241.lean:9:2-9:24: error: mutable variable 'xs' cannot be shadowed
241.lean:16:4-16:12: error: mutable variable 'xs' cannot be shadowed
241.lean:22:2-22:28: error: mutable variable 'xs' cannot be shadowed
241.lean:28:2-28:18: error: mutable variable 'xs' cannot be shadowed
241.lean:34:9-34:16: error: mutable variable 'xs' cannot be shadowed
241.lean:41:9-41:16: error: mutable variable 'xs' cannot be shadowed
241.lean:48:9-48:16: error: mutable variable 'xs' cannot be shadowed
241.lean:58:6-58:27: error: mutable variable 'xs' cannot be shadowed
241.lean:67:8-67:10: error: mutable variable 'xs' cannot be shadowed
241.lean:72:6-72:13: error: mutable variable 'xs' cannot be shadowed
241.lean:78:6-78:8: error: mutable variable 'xs' cannot be shadowed
241.lean:84:2-86:17: error: mutable variable 'xs' cannot be shadowed

View file

@ -34,8 +34,8 @@ def h (x : Nat) (y : Nat) : Nat := do
let mut x := x
let mut y := y
if x > 0 then
let y := x + 1 -- this is a new `y` that shadows the one above
x := y
let y' := x + 1
x := y'
else
y := y + 1
return x + y