<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=Lean_theorem_prover%2FSystem%2FThe_Lean_kernel</id>
	<title>Lean theorem prover/System/The Lean kernel - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=Lean_theorem_prover%2FSystem%2FThe_Lean_kernel"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/System/The_Lean_kernel&amp;action=history"/>
	<updated>2026-10-21T06:34:12Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://invarians.org/index.php?title=Lean_theorem_prover/System/The_Lean_kernel&amp;diff=6787&amp;oldid=prev</id>
		<title>PMA Publisher: Published from the Principia Machina source</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/System/The_Lean_kernel&amp;diff=6787&amp;oldid=prev"/>
		<updated>2026-10-15T19:35:06Z</updated>

		<summary type="html">&lt;p&gt;Published from the Principia Machina source&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 19:35, 15 October 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{DISPLAYTITLE:The Lean kernel}}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{DISPLAYTITLE:The Lean kernel}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Plebeian|Lean theorem prover/Explainers/The small trusted core|Lean theorem prover/Explainers/What a proof assistant does}}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;{{Plebeian|Lean theorem prover/Explainers/The small trusted core|Lean theorem prover/Explainers/What a proof assistant does}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;{{Lean theorem prover map}}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The &amp;#039;&amp;#039;&amp;#039;Lean kernel&amp;#039;&amp;#039;&amp;#039; is the type checker that decides whether a definition, theorem, axiom or inductive type may enter Lean&amp;#039;s environment, its table of definitions and theorems. Everything else in Lean, from the parser to the most elaborate tactic, produces candidates; the Lean kernel accepts or refuses them. This page describes what it checks, what it never sees, how it is written, and where its trust ends, for Lean 4.34.1.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The &amp;#039;&amp;#039;&amp;#039;Lean kernel&amp;#039;&amp;#039;&amp;#039; is the type checker that decides whether a definition, theorem, axiom or inductive type may enter Lean&amp;#039;s environment, its table of definitions and theorems. Everything else in Lean, from the parser to the most elaborate tactic, produces candidates; the Lean kernel accepts or refuses them. This page describes what it checks, what it never sees, how it is written, and where its trust ends, for Lean 4.34.1.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>PMA Publisher</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=Lean_theorem_prover/System/The_Lean_kernel&amp;diff=6580&amp;oldid=prev</id>
		<title>PMA Publisher: Published from the Principia Machina source</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=Lean_theorem_prover/System/The_Lean_kernel&amp;diff=6580&amp;oldid=prev"/>
		<updated>2026-10-14T18:01:05Z</updated>

		<summary type="html">&lt;p&gt;Published from the Principia Machina source&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{DISPLAYTITLE:The Lean kernel}}&lt;br /&gt;
{{Plebeian|Lean theorem prover/Explainers/The small trusted core|Lean theorem prover/Explainers/What a proof assistant does}}&lt;br /&gt;
&lt;br /&gt;
The &amp;#039;&amp;#039;&amp;#039;Lean kernel&amp;#039;&amp;#039;&amp;#039; is the type checker that decides whether a definition, theorem, axiom or inductive type may enter Lean&amp;#039;s environment, its table of definitions and theorems. Everything else in Lean, from the parser to the most elaborate tactic, produces candidates; the Lean kernel accepts or refuses them. This page describes what it checks, what it never sees, how it is written, and where its trust ends, for Lean 4.34.1.&lt;br /&gt;
&lt;br /&gt;
== What reaches it ==&lt;br /&gt;
&lt;br /&gt;
The Lean kernel receives fully explicit terms of one data type, &amp;lt;code&amp;gt;Expr&amp;lt;/code&amp;gt;. With &amp;lt;code&amp;gt;import Lean&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;#print Lean.Expr&amp;lt;/code&amp;gt; lists its twelve constructors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
import Lean&lt;br /&gt;
#print Lean.Expr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean-output&amp;quot; style=&amp;quot;background: #ffffff; border: 1px dashed #a2a9b1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
inductive Lean.Expr : Type&lt;br /&gt;
number of parameters: 0&lt;br /&gt;
constructors:&lt;br /&gt;
Lean.Expr.bvar : Nat → Lean.Expr&lt;br /&gt;
Lean.Expr.fvar : Lean.FVarId → Lean.Expr&lt;br /&gt;
Lean.Expr.mvar : Lean.MVarId → Lean.Expr&lt;br /&gt;
Lean.Expr.sort : Lean.Level → Lean.Expr&lt;br /&gt;
Lean.Expr.const : Lean.Name → List Lean.Level → Lean.Expr&lt;br /&gt;
Lean.Expr.app : Lean.Expr → Lean.Expr → Lean.Expr&lt;br /&gt;
Lean.Expr.lam : Lean.Name → Lean.Expr → Lean.Expr → Lean.BinderInfo → Lean.Expr&lt;br /&gt;
Lean.Expr.forallE : Lean.Name → Lean.Expr → Lean.Expr → Lean.BinderInfo → Lean.Expr&lt;br /&gt;
Lean.Expr.letE : Lean.Name → Lean.Expr → Lean.Expr → Lean.Expr → Bool → Lean.Expr&lt;br /&gt;
Lean.Expr.lit : Lean.Literal → Lean.Expr&lt;br /&gt;
Lean.Expr.mdata : Lean.MData → Lean.Expr → Lean.Expr&lt;br /&gt;
Lean.Expr.proj : Lean.Name → Nat → Lean.Expr → Lean.Expr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These are bound variables, free variables, metavariables, sorts, constants with universe levels, applications, functions, dependent function types, local definitions, numeric and string literals, annotations, and structure projections. The type theory they encode is described in [[Lean theorem prover/Foundations/Terms, types and judgments|terms, types and judgments]]. A term handed to the Lean kernel for addition may contain neither metavariables nor free variables: the elaborator must have solved every hole and closed every term.&amp;lt;ref name=&amp;quot;src-env-cpp&amp;quot;&amp;gt;Lean 4 source code, version 4.34.1 (2026), file &amp;lt;code&amp;gt;src/kernel/environment.cpp&amp;lt;/code&amp;gt;: the functions &amp;lt;code&amp;gt;add_axiom&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;add_definition&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;add_theorem&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;add_opaque&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;add_mutual&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;check_constant_val&amp;lt;/code&amp;gt;. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/kernel/environment.cpp&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requests themselves form a second data type, &amp;lt;code&amp;gt;Lean.Declaration&amp;lt;/code&amp;gt;, with seven constructors: an axiom, a definition, a theorem, an opaque constant, a block of mutually recursive definitions, the quotient primitives, and a block of inductive types. What the table stores, &amp;lt;code&amp;gt;Lean.ConstantInfo&amp;lt;/code&amp;gt;, has eight: the same kinds, minus the mutual block, plus the constructors and recursors that the Lean kernel itself generates for each inductive type. Both are printed by &amp;lt;code&amp;gt;#print&amp;lt;/code&amp;gt; in the same way as &amp;lt;code&amp;gt;Expr&amp;lt;/code&amp;gt; above.&lt;br /&gt;
&lt;br /&gt;
== What it checks ==&lt;br /&gt;
&lt;br /&gt;
For every constant, whatever its kind, the Lean kernel checks that the name is not already taken, that no universe parameter is listed twice, that the stated type contains no metavariables or free variables, and that the type is itself well typed with a sort as its type.&amp;lt;ref name=&amp;quot;src-env-cpp&amp;quot; /&amp;gt; Then it checks by kind.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;An axiom&amp;#039;&amp;#039;&amp;#039; is accepted once its type passes. Nothing else is checked, which is why axioms are listed by &amp;lt;code&amp;gt;#print axioms&amp;lt;/code&amp;gt; and why the edition treats them on their own page, [[Lean theorem prover/Foundations/The three axioms|the three axioms]].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;A definition, a theorem or an opaque constant&amp;#039;&amp;#039;&amp;#039; has a value. The Lean kernel infers the value&amp;#039;s type and asks whether it is definitionally equal to the stated type. For a theorem it also checks that the stated type is a proposition.&amp;lt;ref name=&amp;quot;src-env-cpp&amp;quot; /&amp;gt; In the notation of the foundations pages, a definition &amp;lt;math&amp;gt;c : T := v&amp;lt;/math&amp;gt; is accepted when&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{\vdash T : \mathrm{Sort}\ u \qquad \vdash v : T&amp;#039; \qquad T&amp;#039; \equiv T}{c : T := v\ \ \mathrm{accepted}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;math&amp;gt;\equiv&amp;lt;/math&amp;gt; is definitional equality, the subject of [[Lean theorem prover/Foundations/Definitional equality|definitional equality]]. Much of the Lean kernel&amp;#039;s work is in that last premise. Its implementation in 4.34.1 tries, in order: quick structural checks; full evaluation when the second term is the Boolean &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and the first has no free variables, a path its source comment ties to the &amp;lt;code&amp;gt;decide&amp;lt;/code&amp;gt; tactic; reduction to weak head normal form; proof irrelevance; lazy unfolding of definitions, the side with the greater definitional height first; then comparison of arguments, eta for functions, eta for structures, string literals and unit-like types.&amp;lt;ref name=&amp;quot;src-tc&amp;quot;&amp;gt;Lean 4 source code, version 4.34.1 (2026), file &amp;lt;code&amp;gt;src/kernel/type_checker.cpp&amp;lt;/code&amp;gt;: the functions &amp;lt;code&amp;gt;is_def_eq_core&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;lazy_delta_reduction_step&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;reduce_nat&amp;lt;/code&amp;gt;; with the function &amp;lt;code&amp;gt;compare&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;src/kernel/declaration.cpp&amp;lt;/code&amp;gt;, which orders unfolding by definitional height. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/kernel/type_checker.cpp&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A block of mutually recursive definitions is accepted only when it is marked &amp;lt;code&amp;gt;partial&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt;.&amp;lt;ref name=&amp;quot;src-env-cpp&amp;quot; /&amp;gt; Ordinary recursive functions reach the Lean kernel already compiled into recursors, as [[Lean theorem prover/Foundations/Structural and well-founded recursion|structural and well-founded recursion]] explains, so the Lean kernel has no termination checker to trust.&amp;lt;ref name=&amp;quot;manual-elab&amp;quot;&amp;gt;Lean Developers, &amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version 4.34.0, chapter &amp;quot;Elaboration and Compilation&amp;quot;. https://lean-lang.org/doc/reference/4.34.0/Elaboration-and-Compilation/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;An inductive type&amp;#039;&amp;#039;&amp;#039; is checked hardest, because its constructors and its recursor become axiom-like rules. For each constructor the Lean kernel checks that its type is well typed, that its parameters match the type&amp;#039;s parameters, that each field lives in a universe no larger than the type&amp;#039;s own (unless the type is a proposition), that the type being defined occurs only strictly positively, and that the constructor returns the type being defined. It then generates the recursor and its computation rules.&amp;lt;ref name=&amp;quot;src-ind&amp;quot;&amp;gt;Lean 4 source code, version 4.34.1 (2026), file &amp;lt;code&amp;gt;src/kernel/inductive.cpp&amp;lt;/code&amp;gt;: the functions &amp;lt;code&amp;gt;check_constructors&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;check_positivity&amp;lt;/code&amp;gt;. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/kernel/inductive.cpp&amp;lt;/ref&amp;gt; [[Lean theorem prover/Foundations/Inductive types and recursors|Inductive types and recursors]] gives the rules; here is the positivity check refusing a type that would make the logic inconsistent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean lean-fails&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
inductive Bad where&lt;br /&gt;
  | mk : (Bad → Nat) → Bad&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean-output&amp;quot; style=&amp;quot;background: #ffffff; border: 1px dashed #a2a9b1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
error: (kernel) arg #1 of &amp;#039;Bad.mk&amp;#039; has a non positive occurrence of the datatypes being declared&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The prefix &amp;lt;code&amp;gt;(kernel)&amp;lt;/code&amp;gt; marks a message that comes from the Lean kernel and not from the elaborator.&amp;lt;ref name=&amp;quot;src-message&amp;quot;&amp;gt;Lean 4 source code, version 4.34.1 (2026), file &amp;lt;code&amp;gt;src/Lean/Message.lean&amp;lt;/code&amp;gt;: the messages for &amp;lt;code&amp;gt;Kernel.Exception&amp;lt;/code&amp;gt;. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/Lean/Message.lean&amp;lt;/ref&amp;gt; Some checks are made twice. A constructor field in too large a universe, such as &amp;lt;code&amp;gt;mk : Type → Big&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;Big : Type&amp;lt;/code&amp;gt;, is caught first by the elaborator, which gives a fuller message; the Lean kernel would refuse it too.&amp;lt;ref name=&amp;quot;src-ind&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What it does not see ==&lt;br /&gt;
&lt;br /&gt;
The Lean kernel sees no syntax, no notation, no macro, no tactic, no instance search and no coercion. It performs no unification and no termination checking.&amp;lt;ref name=&amp;quot;manual-elab&amp;quot; /&amp;gt; A proof written with fifty tactic steps and the same proof written as a term reach it as the same kind of object, an &amp;lt;code&amp;gt;Expr&amp;lt;/code&amp;gt;, and it cannot tell how either was found. This is the point of the design: the elaborator ([[Lean theorem prover/System/Elaboration|elaboration]]) and the tactic framework may be as clever, as large and as buggy as they like, because what they produce is checked again.&lt;br /&gt;
&lt;br /&gt;
The arrangement can be tested by going around the elaborator. The following metaprogram hands the Lean kernel a theorem whose stated type is &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt; and whose proof is &amp;lt;code&amp;gt;True.intro&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean lean-fails&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
import Lean&lt;br /&gt;
open Lean Elab Command&lt;br /&gt;
&lt;br /&gt;
#eval show CommandElabM Unit from do&lt;br /&gt;
  let decl := Declaration.thmDecl {&lt;br /&gt;
    name := `bogus, levelParams := [], type := mkConst ``False,&lt;br /&gt;
    value := mkConst ``True.intro }&lt;br /&gt;
  liftCoreM (addDecl decl)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean-output&amp;quot; style=&amp;quot;background: #ffffff; border: 1px dashed #a2a9b1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
error: (kernel) declaration type mismatch, &amp;#039;bogus&amp;#039; has type&lt;br /&gt;
  True&lt;br /&gt;
but it is expected to have type&lt;br /&gt;
  False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Computation inside the check ==&lt;br /&gt;
&lt;br /&gt;
Deciding definitional equality means running programs, so the Lean kernel contains an evaluator. Pure unfolding would make arithmetic on numerals hopeless, since &amp;lt;code&amp;gt;Nat&amp;lt;/code&amp;gt; is unary in its definition. The Lean kernel therefore computes &amp;lt;code&amp;gt;Nat.add&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.sub&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.mul&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.div&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.mod&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.gcd&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.pow&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.beq&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Nat.ble&amp;lt;/code&amp;gt;, the bitwise operations and the shifts directly on literals, with the arbitrary-precision numbers of Lean&amp;#039;s runtime.&amp;lt;ref name=&amp;quot;src-tc&amp;quot; /&amp;gt; Their size is capped all the same: the Lean kernel refuses a natural-number literal, whether written in the source or produced by this arithmetic, that takes more than 128 MB, a default that the operating-system variable &amp;lt;code&amp;gt;LEAN_NAT_MAX_SIZE&amp;lt;/code&amp;gt; can change.&amp;lt;ref name=&amp;quot;src-natmax&amp;quot;&amp;gt;Lean 4 source code, version 4.34.1 (2026), file &amp;lt;code&amp;gt;src/kernel/type_checker.cpp&amp;lt;/code&amp;gt;: the constant &amp;lt;code&amp;gt;LEAN_NAT_MAX_SIZE_DEFAULT&amp;lt;/code&amp;gt; (128 × 1024 × 1024 bytes), the functions &amp;lt;code&amp;gt;check_nat_size&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;infer_lit&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;reduce_nat&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;initialize_type_checker&amp;lt;/code&amp;gt;. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/kernel/type_checker.cpp&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;lean&amp;quot; style=&amp;quot;background: #f8f9fa; border: 1px solid #c8ccd1; padding: 0.6em; margin: 0.3em 0; font-size: 0.85em; line-height: 1.35; overflow-x: auto; white-space: pre;&amp;quot;&amp;gt;&lt;br /&gt;
theorem big : 2 ^ 64 * 2 ^ 64 = 2 ^ 128 := rfl&lt;br /&gt;
#print axioms big&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This prints &amp;lt;code&amp;gt;&amp;#039;big&amp;#039; does not depend on any axioms&amp;lt;/code&amp;gt;. The cost is that this arithmetic, and the runtime code behind it, is part of what must be trusted.&lt;br /&gt;
&lt;br /&gt;
== Its implementation ==&lt;br /&gt;
&lt;br /&gt;
The reference manual states that the Lean kernel is written in C++, and that independent reimplementations exist in Rust and in Lean, the aim being to have as many implementations as possible so that they can be cross-checked against each other.&amp;lt;ref name=&amp;quot;manual-elab&amp;quot; /&amp;gt; In version 4.34.1 the directory &amp;lt;code&amp;gt;src/kernel&amp;lt;/code&amp;gt; of the Lean source holds 36 C++ source and header files totalling 8,071 lines, blank lines and comments included; this count was made for this page by running &amp;lt;code&amp;gt;wc -l&amp;lt;/code&amp;gt; over those files as they stand at that version.&amp;lt;ref name=&amp;quot;src-kernel-dir&amp;quot;&amp;gt;Lean 4 source code, version 4.34.1 (2026), directory &amp;lt;code&amp;gt;src/kernel&amp;lt;/code&amp;gt; (36 files &amp;lt;code&amp;gt;*.cpp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;*.h&amp;lt;/code&amp;gt;, plus &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;). Apache License 2.0. https://github.com/leanprover/lean4/tree/v4.34.1/src/kernel&amp;lt;/ref&amp;gt; The count is a lower bound on what is trusted, not a measure of it: those files include headers from Lean&amp;#039;s runtime and utility libraries, for numbers, names and memory management, which the count leaves out. The largest files are the type checker (1,373 lines) and the checker for inductive types (1,417 lines). The paper that introduced Lean 4 describes the Lean kernel as relatively small.&amp;lt;ref name=&amp;quot;lean4-paper&amp;quot;&amp;gt;Leonardo de Moura and Sebastian Ullrich, &amp;quot;The Lean 4 Theorem Prover and Programming Language (System Description)&amp;quot;, in &amp;#039;&amp;#039;Automated Deduction – CADE 28&amp;#039;&amp;#039;, Lecture Notes in Computer Science 12699, Springer, 2021, pp. 625–635. doi:10.1007/978-3-030-79876-5_37&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Lean&amp;#039;s environment ==&lt;br /&gt;
&lt;br /&gt;
Lean&amp;#039;s environment, its table of definitions and theorems, is the Lean kernel&amp;#039;s state. In 4.34.1 the Lean structure &amp;lt;code&amp;gt;Lean.Kernel.Environment&amp;lt;/code&amp;gt; maps each constant&amp;#039;s name to its &amp;lt;code&amp;gt;ConstantInfo&amp;lt;/code&amp;gt;, and its documentation says that this table contains every constant that has already been type checked by the Lean kernel, that it is never destructively updated, and that its constructor is private to protect against changes that bypass the Lean kernel.&amp;lt;ref name=&amp;quot;src-env-lean&amp;quot;&amp;gt;Lean 4 source code, version 4.34.1 (2026), file &amp;lt;code&amp;gt;src/Lean/Environment.lean&amp;lt;/code&amp;gt;: the structure &amp;lt;code&amp;gt;Lean.Kernel.Environment&amp;lt;/code&amp;gt;, the option &amp;lt;code&amp;gt;debug.skipKernelTC&amp;lt;/code&amp;gt; and the function &amp;lt;code&amp;gt;addDeclWithoutChecking&amp;lt;/code&amp;gt;. Apache License 2.0. https://github.com/leanprover/lean4/blob/v4.34.1/src/Lean/Environment.lean&amp;lt;/ref&amp;gt; The same structure carries &amp;#039;&amp;#039;&amp;#039;extensions&amp;#039;&amp;#039;&amp;#039;, further tables for data the Lean kernel ignores, such as simp lemmas, custom pretty printers and the compiler&amp;#039;s intermediate code.&amp;lt;ref name=&amp;quot;src-env-lean&amp;quot; /&amp;gt;&amp;lt;ref name=&amp;quot;manual-elab&amp;quot; /&amp;gt; Adding a constant returns a new table; nothing already accepted is changed.&lt;br /&gt;
&lt;br /&gt;
== Where the trust ends ==&lt;br /&gt;
&lt;br /&gt;
The checked table is only as good as the path into it. Lean 4.34.1 has an option, &amp;lt;code&amp;gt;debug.skipKernelTC&amp;lt;/code&amp;gt;, whose own description warns that setting it &amp;quot;may compromise soundness&amp;quot; because proofs are then not checked by the Lean kernel, and a matching function, &amp;lt;code&amp;gt;addDeclWithoutChecking&amp;lt;/code&amp;gt;.&amp;lt;ref name=&amp;quot;src-env-lean&amp;quot; /&amp;gt; A Lean source file can also run arbitrary code while it is processed. The reference manual&amp;#039;s guidance on validating proofs therefore recommends replaying the compiled files through the Lean kernel with a separate checker, and, for adversarial settings, building the proofs in a sandbox, exporting them and replaying them with the Lean kernel or an independent checker.&amp;lt;ref name=&amp;quot;manual-validating&amp;quot;&amp;gt;Lean Developers, &amp;#039;&amp;#039;The Lean Language Reference&amp;#039;&amp;#039;, version 4.34.0, &amp;quot;Validating a Lean Proof&amp;quot;. https://lean-lang.org/doc/reference/4.34.0/ValidatingProofs/&amp;lt;/ref&amp;gt; [[Lean theorem prover/System/Proof export and independent checkers|Proof export and independent checkers]] takes this up. The soundness of the type theory itself, which no checker can establish from inside, is the subject of [[Lean theorem prover/Foundations/Consistency and the metatheory|consistency and the metatheory]].&lt;br /&gt;
&lt;br /&gt;
== Next ==&lt;br /&gt;
&lt;br /&gt;
[[Lean theorem prover/System/Metavariables and unification|Metavariables and unification]] describes the holes the elaborator must fill before a term may reach the Lean kernel.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>PMA Publisher</name></author>
	</entry>
</feed>