Also, refuse to evaluate an `[init]` decl in the same module (since we don't know whether the initialization is
backtrackable) and always use native symbol of a `[builtinInit]` decl
The following `do` block
```lean
if c_1 then
action_1
else
if cond_2 then
action_2
action_3
```
was being being parsed as
```lean
if c_1 then
action_1
else if cond_2 then
action_2
action_3
```
cc @Kha
We use `MProd` instead of `Prod` to group values when expanding the
`do` notation. `MProd` is a universe monomorphic product.
The motivation is to generate simpler universe constraints in code
that was not written by the user but generated by the `do` macro.
Note that we are not really restricting the macro power since the
`HasBind.bind` combinator already forces values computed by monadic
actions to be in the same universe.
The new test cannot be compiled without this modication.
@Kha the new test may look exoteric, but it reflects an actual
instance in our code base, and the old frontend supports it.
Not sure whether we should keep it or not.
The compiler frontend implemented in C++ is eagerly inlining local
functions. The new test would take an absurd amount of time without
the new hack.
We remove this hack when we re-implement the compiler frontend in Lean.
@Kha `withReader` is a well-behaved version of `adaptReader`. `adaptReader` is
too general, and it often produces counterintuitive elaboration
errors.
Here are two super annoying issues I hit all the time:
1- `adaptReader` + polymorphic code
```
def ex1 : ReaderT Nat IO Unit :=
adaptReader (fun x => x + 1) $
IO.println "foo" -- 3 Errors here failed to synthesize `Monad ?m` and `MonadIO ?m`, and don't know how to synthesize `Type → Type`
```
2- `adaptReader` and notation that requires the expected type
```
structure Context :=
(x y : Nat)
def ex2 : ReaderT Context IO Nat :=
adaptReader (fun s => { s with x := 10 }) $ -- Error at the structure instance
...
```
In the example above, I have to write `fun (s : Context) => ...` to
fix the problem.
The two problems above happen in the old and new frontends. However,
there is a new problem specific for the new frontend. In the new
frontend, a `do` is only elaborated when the expected type is known.
So, `adaptReader (fun ctx => ...) do ...` seldom works :(
As I said above, the issue is that `adaptReader` is too general. Its
type is
```
{ρ ρ' : Type u_1} → {m m' : Type u_1 → Type u_2} → [MonadReaderAdapter ρ ρ' m m'] → {α : Type u_1} → (ρ' → ρ) → m α → m' α
```
`withReader` is a simpler version of `adaptReader`
```
withReader : {ρ : Type u_1} → {m : Type u_1 → Type u_2} → [MonadWithReader ρ m] → {α : Type u_1} → (ρ → ρ) → m α → m α
```
It doesn't have any of the problems above. Moreover, I managed to replace
every single instance of `adaptReader` with `withReader` at the stdlib
and tests. We don't need the `adaptReader` generality.