Zulip Chat Archive

Stream: PR reviews

Topic: lean#703 noncomputable!


Kyle Miller (Mar 17 2022 at 04:18):

This is a PR to add the ability to completely turn off the noncomputability checker and the VM compiler. There are two user-visible features: the noncomputable! modifier for definitions and the noncomputable! theory command (for when you really mean it).

The current noncomputable theory is sort of misleading in that it actually just causes Lean to ignore whether you applied noncomputable correctly. It still VM compiles things it thinks are computable. To avoid this, you can do noncomputable! theory at the top of your file and never see another noncomputability checker or VM compilation error ever again.

I'm posting this message as an RFC, and there are some more details in the PR message at lean#703. I believe this is a completely reverse-compatible change.

Mario Carneiro (Mar 17 2022 at 04:19):

I don't think it would be a good idea to use this in mathlib, I think it will increase the number of VM error messages

Mario Carneiro (Mar 17 2022 at 04:20):

plus this will be another thing to support in mathport, I'm not sure lean 4 has what we need

Kyle Miller (Mar 17 2022 at 04:22):

Why do you think it would increase the number of VM error messages? This causes declarations to be marked noncomputable in the environment, so nothing VM compiled could ever use them.

Mario Carneiro (Mar 17 2022 at 04:23):

until you try to use anything from the file in the next file down

Kyle Miller (Mar 17 2022 at 04:23):

Regarding Lean 4, isn't noncomputable! equivalent to its noncomputable?

Mario Carneiro (Mar 17 2022 at 04:23):

we need to support all three settings with this version

Kyle Miller (Mar 17 2022 at 04:24):

Mario Carneiro said:

until you try to use anything from the file in the next file down

How so?

Kyle Miller (Mar 17 2022 at 04:25):

For mathport, you can replace noncomputable theory with explicit noncomputables, and all the information you need is in the noncomputability marking in the environment, I'm pretty sure.

Mario Carneiro (Mar 17 2022 at 04:26):

synport does syntax porting, it does not do syntactic transformations like that unless they reflect the user's intent

Kyle Miller (Mar 17 2022 at 04:26):

What are you porting noncomputable theory to then?

Mario Carneiro (Mar 17 2022 at 04:26):

noncomputable section I believe

Kyle Miller (Mar 17 2022 at 04:27):

That means it's all completely not compiled, right? So if that behavior remains the same in Lean 4, both noncomputable theory and noncomputable! theory can become noncomputable section

Mario Carneiro (Mar 17 2022 at 04:28):

no, this works

noncomputable section

def foo := 1
#eval foo

Mario Carneiro (Mar 17 2022 at 04:28):

only the noncomputable modifier on defs forces noncomputable

Mario Carneiro (Mar 17 2022 at 04:29):

I think that "don't compile anything in this section" is dangerous because tactics might want to create and compile auxiliary defs in a section

Mario Carneiro (Mar 17 2022 at 04:31):

noncomputable is also incompatible with partial/unsafe

Kyle Miller (Mar 17 2022 at 04:31):

I'm still not sure what you're referring to about VM error messages

-- mod1.lean
noncomputable! def n :  := 37

-- mod2.lean
import mod1

#print n
/-
noncomputable def n : ℕ :=
37
-/

def m := n
/- definition 'm' is noncomputable, it depends on 'n' -/

Mario Carneiro (Mar 17 2022 at 04:32):

I have occasionally hit issues with noncomputable lemma foo := 1 definitions in old lean 3 (which is also essentially "force noncomputable")

Mario Carneiro (Mar 17 2022 at 04:33):

luckily this pattern is used very rarely so it hasn't been a problem but I guess this will make it more common

Mario Carneiro (Mar 17 2022 at 04:33):

The issue being that a thing that really should be computable has accidentally been marked noncomputable

Mario Carneiro (Mar 17 2022 at 04:34):

it's very annoying to fix this when the thing is an auxiliary def

Mario Carneiro (Mar 17 2022 at 04:35):

in fact I'm pretty sure all current issues with noncomputable theory not just working are of this form

Kyle Miller (Mar 17 2022 at 04:35):

What kinds of things happen when you have noncomputable lemmas?

Mario Carneiro (Mar 17 2022 at 04:35):

Note that it's a noncomputable lemma which has a type which is data

Mario Carneiro (Mar 17 2022 at 04:35):

i.e. the thing that you get linter warnings about

Mario Carneiro (Mar 17 2022 at 04:36):

unfortunately I can't remember the details, but it is something along the lines of the VM not finding a definition it is supposed to

Mario Carneiro (Mar 17 2022 at 04:38):

Can you give an example where noncomputable! is the right thing to do?

Mario Carneiro (Mar 17 2022 at 04:40):

as far as I see it noncomputable theory is the correct option if you never want to think about computability

Kyle Miller (Mar 17 2022 at 04:41):

This is for people like @Kevin Buzzard where they don't care if the VM compiler runs, and he's been reporting examples with timeout errors that as far as I can tell all come from exponential blowups in VM compiler preprocessing steps

Mario Carneiro (Mar 17 2022 at 04:41):

maybe there are bugs in the implementation but spec-wise it has exactly the right semantics

Kyle Miller (Mar 17 2022 at 04:41):

They've been using force_noncomputable as a stop-gap

Kyle Miller (Mar 17 2022 at 04:41):

These are also things that they're never going to evaluate, so why waste cycles VM compiling them?

Kyle Miller (Mar 17 2022 at 04:41):

or checking whether they could be VM compiled?

Mario Carneiro (Mar 17 2022 at 04:43):

Okay, that works for noncomputable! on an individual def but not a whole section

Mario Carneiro (Mar 17 2022 at 04:43):

I would use it only when there is a definite gain

Mario Carneiro (Mar 17 2022 at 04:43):

and also fix the noncomputable checker to not be slow if that's the issue

Mario Carneiro (Mar 17 2022 at 04:44):

You will also need a computable! modifier for when you want a computable def in a noncomputable! theory file, no?

Kyle Miller (Mar 17 2022 at 04:45):

Yeah, that's fair, and I'm not suggesting noncomputable! theory should be used in mathlib. The main feature here is the noncomputable! modifier, and I added the command since I was touching all this code anyway.

Mario Carneiro (Mar 17 2022 at 04:45):

(flashbacks to CSS !important)

Kyle Miller (Mar 17 2022 at 04:51):

I still don't see why we care about finding opportunities to VM compile theoretical definitions. Where would these ever be used?

Lean 4's noncomputability system seems to be much more robust, and it very likely noncomputable! and noncomputable could be translated to the same thing.

Kyle Miller (Mar 17 2022 at 04:51):

Mario Carneiro said:

and also fix the noncomputable checker to not be slow if that's the issue

The issue is that the definitions Kevin's shared are all computable, but the VM compiler is horrendously slow -- I poked around a bit, but it doesn't seem to be a good use of time trying to fix that.

Mario Carneiro (Mar 17 2022 at 04:53):

If this is being used to better express intent in the code than I have no issues with adding these things. But I would not recommend noncomputable! theory to people who don't know the tradeoffs

Kyle Miller (Mar 17 2022 at 04:53):

As far as I can tell, neither noncomputable! nor noncomputable! theory affects auxiliary definitions. This is either a bug or a feature, I suppose.

Mario Carneiro (Mar 17 2022 at 04:54):

that can be bad if an auxiliary definition refers to a user definition and everything in sight is noncomputable except the auxiliary

Kyle Miller (Mar 17 2022 at 04:55):

If it refers to the user definition, I think it will be marked noncomputable, too. They seem to be processed as if they were under noncomputable theory.

Kyle Miller (Mar 17 2022 at 04:56):

What might be a bug is that noncomputable! theory causes all lemmas to be marked noncomputable. Does that have any affect on anything?

Mario Carneiro (Mar 17 2022 at 04:56):

lemmas are always noncomputable

Mario Carneiro (Mar 17 2022 at 04:56):

like I said, noncomputable lemma is a way to get the effect of noncomputable! def in old lean 3

Kyle Miller (Mar 17 2022 at 04:56):

They're not marked noncomputable

Kyle Miller (Mar 17 2022 at 04:57):

noncomputable!
lemma foo1 : true := trivial

lemma foo2 : true := trivial

#print foo1
/-
noncomputable theorem foo1 : true :=
trivial
-/

#print foo2
/-
theorem foo2 : true :=
trivial
-/

Mario Carneiro (Mar 17 2022 at 04:57):

well, it might put the modifier on but it doesn't have code

Mario Carneiro (Mar 17 2022 at 04:59):

noncomputable lemma foo1 : nat := 1 -- incorrectly marked as noncomputable, but proceeds anyway
lemma foo2 : nat := 1
def foo3 : nat := 1

#eval foo1 -- no code
#eval foo2 -- no code
#eval foo3 -- 1

Kyle Miller (Mar 17 2022 at 05:00):

I'm not talking about a modifier here, but the noncomputable mark in the environment. That's what the #print command checks when deciding to write noncomputable, and it's also what things like the noncomputability checker use, or the VM compiler when deciding when to compile something

Mario Carneiro (Mar 17 2022 at 05:01):

This is the problem that occurs when the modifier does not match the presence of code:

lemma foo2 : nat := 1
def foo3 : nat := foo2
-- failed to generate bytecode for 'foo3'
-- code generation failed, VM does not have code for 'test.foo2'

Mario Carneiro (Mar 17 2022 at 05:02):

I see no good reason for these to ever differ

Mario Carneiro (Mar 17 2022 at 05:03):

i.e. all lemmas which produce data should be marked noncomputable

Kyle Miller (Mar 17 2022 at 05:10):

That seems like it's a bug in the noncomputability checker -- it should be able to tell when a declaration has no value

Mario Carneiro (Mar 17 2022 at 05:22):

well, currently you can't actually put noncomputable on a lemma, it just ignores it. With your version you can, so we should probably be consistent about what it means

Kyle Miller (Mar 17 2022 at 19:07):

For what it's worth, you can put noncomputable on a lemma, and it's not ignored:

import data.nat.lattice

noncomputable lemma foo :  := Sup set.univ

This then correctly causes definitions that use it to need to be noncomputable as well:

def foo' := foo
-- definition 'foo'' is noncomputable, it depends on 'foo'

Kyle Miller (Mar 17 2022 at 19:12):

I guess what should happen is that get_noncomputable_reason should check whether it's a theorem with data. It already lets through definitions/theorems whose type is a Prop, so it might just need to require it if it's a theorem

Kyle Miller (Mar 18 2022 at 00:06):

@Mario Carneiro lean#704 addresses the "code generation failed" error when you use a theorem that produces data by having non-Prop theorems be marked as noncomputable. It's more restrictive than necessary and could also allow other computationally irrelevant types, but this was easiest and mathlib's linters don't allow them anyway.

Kyle Miller (Mar 18 2022 at 00:08):

Somewhere along the way I saw a commit message by Leo from many years ago, when the noncomputability checker was mostly built, saying that we should refactor things to use the VM compiler to determine noncomputability, otherwise it will be this endless task of trying to keep the checker and the compiler in sync. That's what Lean 4 does now, right?


Last updated: Dec 20 2023 at 11:08 UTC