This PR upstreams the `ToLevel` typeclass from mathlib and uses it to fix the existing `ToExpr` instances so that they are truly universe polymorphic (previously it generated malformed expressions when the universe level was nonzero). We improve on the mathlib definition of `ToLevel` to ensure the class always lives in `Type`, irrespective of the universe parameter. This implements part one of the plan to upstream a derive handler for `ToExpr`, as discussed in #5906 and #5909. --------- Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: Tobias Grosser <tobias@grosser.es>
132 lines
4.3 KiB
Text
132 lines
4.3 KiB
Text
import Lean.Elab.Command
|
||
import Lean.Elab.Open
|
||
/-!
|
||
Issue #2291
|
||
|
||
The following example would cause the pretty printer to panic.
|
||
-/
|
||
|
||
set_option trace.compiler.simp true in
|
||
/--
|
||
info: [compiler.simp] >> _eval
|
||
let _x_21 := `Nat;
|
||
let _x_22 := [];
|
||
let _x_23 := Lean.Expr.const _x_21 _x_22;
|
||
let _x_24 := `List.nil;
|
||
let _x_25 := Lean.Level.zero :: _x_22;
|
||
let _x_26 := Lean.Expr.const _x_24 _x_25;
|
||
let _x_27 := _x_26.app _x_23;
|
||
let _x_28 := `List.cons;
|
||
let _x_29 := Lean.Expr.const _x_28 _x_25;
|
||
let _x_30 := _x_29.app _x_23;
|
||
let _x_31 := [];
|
||
let _x_32 := 0 :: _x_31;
|
||
let _x_33 := Lean.List.toExprAux✝ _x_27 _x_30 _x_32;
|
||
Lean.MessageData.ofExpr _x_33
|
||
[compiler.simp] >> _private.Lean.ToExpr.0.Lean.List.toExprAux._at._eval._spec_1
|
||
fun nilFn consFn x =>
|
||
List.casesOn fun head tail =>
|
||
let _x_1 := Lean.mkNatLit head;
|
||
let _x_2 := Lean.List.toExprAux._at._eval._spec_1✝ nilFn consFn tail;
|
||
Lean.mkAppB consFn _x_1 _x_2
|
||
>> _eval
|
||
let _x_14 := Lean.Name.str._override Lean.Name.anonymous._impl "Nat";
|
||
let _x_15 := List.nil _neutral;
|
||
let _x_16 := Lean.Expr.const._override _x_14 _x_15;
|
||
let _x_17 := `List.nil;
|
||
let _x_18 := List.cons _neutral Lean.Level.zero._impl _x_15;
|
||
let _x_19 := Lean.Expr.const._override _x_17 _x_18;
|
||
let _x_20 := Lean.Expr.app._override _x_19 _x_16;
|
||
let _x_21 := `List.cons;
|
||
let _x_22 := Lean.Expr.const._override _x_21 _x_18;
|
||
let _x_23 := Lean.Expr.app._override _x_22 _x_16;
|
||
let _x_24 := List.cons _neutral 0 _x_15;
|
||
let _x_25 := Lean.List.toExprAux._at._eval._spec_1✝ _x_20 _x_23 _x_24;
|
||
Lean.MessageData.ofExpr _x_25
|
||
[compiler.simp] >> _private.Lean.ToExpr.0.Lean.List.toExprAux._at._eval._spec_1
|
||
fun nilFn consFn x =>
|
||
List.casesOn fun head tail =>
|
||
let _x_1 := Lean.mkNatLit head;
|
||
let _x_2 := Lean.List.toExprAux._at._eval._spec_1✝ nilFn consFn tail;
|
||
Lean.mkAppB consFn _x_1 _x_2
|
||
>> _eval
|
||
let _x_1 := Lean.Name.str._override Lean.Name.anonymous._impl "Nat";
|
||
let _x_2 := List.nil _neutral;
|
||
let _x_3 := Lean.Expr.const._override _x_1 _x_2;
|
||
let _x_4 := `List.nil;
|
||
let _x_5 := List.cons _neutral Lean.Level.zero._impl _x_2;
|
||
let _x_6 := Lean.Expr.const._override _x_4 _x_5;
|
||
let _x_7 := Lean.Expr.app._override _x_6 _x_3;
|
||
let _x_8 := `List.cons;
|
||
let _x_9 := Lean.Expr.const._override _x_8 _x_5;
|
||
let _x_10 := Lean.Expr.app._override _x_9 _x_3;
|
||
let _x_11 := List.cons _neutral 0 _x_2;
|
||
let _x_12 := Lean.List.toExprAux._at._eval._spec_1✝ _x_7 _x_10 _x_11;
|
||
Lean.MessageData.ofExpr _x_12
|
||
[compiler.simp] >> _private.Lean.ToExpr.0.Lean.List.toExprAux._at._eval._spec_1
|
||
fun nilFn consFn x =>
|
||
List.casesOn fun head tail =>
|
||
let _x_1 := Lean.mkNatLit head;
|
||
let _x_2 := Lean.List.toExprAux._at._eval._spec_1✝ nilFn consFn tail;
|
||
Lean.mkAppB consFn _x_1 _x_2
|
||
>> _eval._closed_1
|
||
"Nat"
|
||
>> _eval._closed_2
|
||
Lean.Name.str._override Lean.Name.anonymous._impl _eval._closed_1
|
||
>> _eval._closed_3
|
||
let _x_1 := List.nil _neutral;
|
||
Lean.Expr.const._override _eval._closed_2 _x_1
|
||
>> _eval._closed_4
|
||
"List"
|
||
>> _eval._closed_5
|
||
"nil"
|
||
>> _eval._closed_6
|
||
Lean.Name.mkStr2 _eval._closed_4 _eval._closed_5
|
||
>> _eval._closed_7
|
||
let _x_1 := List.nil _neutral;
|
||
List.cons _neutral Lean.Level.zero._impl _x_1
|
||
>> _eval._closed_8
|
||
Lean.Expr.const._override _eval._closed_6 _eval._closed_7
|
||
>> _eval._closed_9
|
||
Lean.Expr.app._override _eval._closed_8 _eval._closed_3
|
||
>> _eval._closed_10
|
||
"cons"
|
||
>> _eval._closed_11
|
||
Lean.Name.mkStr2 _eval._closed_4 _eval._closed_10
|
||
>> _eval._closed_12
|
||
Lean.Expr.const._override _eval._closed_11 _eval._closed_7
|
||
>> _eval._closed_13
|
||
Lean.Expr.app._override _eval._closed_12 _eval._closed_3
|
||
>> _eval._closed_14
|
||
let _x_1 := List.nil _neutral;
|
||
List.cons _neutral 0 _x_1
|
||
>> _eval
|
||
let _x_1 :=
|
||
Lean.List.toExprAux._at._eval._spec_1✝ _eval._closed_9 _eval._closed_13
|
||
_eval._closed_14;
|
||
Lean.MessageData.ofExpr _x_1
|
||
---
|
||
info: [0]
|
||
-/
|
||
#guard_msgs in
|
||
#eval [0]
|
||
|
||
|
||
/-!
|
||
Fixing the above involved changing `Lean.unresolveNameGlobal`.
|
||
Here, we also verify that we do not pretty print using any aliases that have macro scopes.
|
||
-/
|
||
|
||
open Lean in
|
||
elab "add_bad_alias " n:ident : command => withFreshMacroScope do
|
||
let declName ← Elab.OpenDecl.resolveNameUsingNamespaces [← getCurrNamespace] n
|
||
let badName ← MonadQuotation.addMacroScope `bad
|
||
modify fun s => { s with env := addAlias s.env badName declName }
|
||
|
||
def f := 1
|
||
|
||
add_bad_alias f
|
||
|
||
-- Formerly was info: bad✝ : ℕ
|
||
/-- info: f : Nat -/
|
||
#guard_msgs in #check (f)
|