Sort of the official policy is that inside proofs (i.e., terms of types in Prop) constructibility doesn't matter, but inside definitions (i.e., terms of types in Type 0 and above) try to be constructive. For example, it is ok to define a function constructively but with a nonconstructive proof of termination.
The axiom of choice is an actual axiom, and it too ends up being used everywhere, but mostly to introduce decidable instances to permit things like double negation elimination inside proofs. An illustration: [1] introduces these instances to the file and [2] implicitly uses the instance.
It is my understanding that functional extensionality in Lean itself follows from the axiom propositional extensionality, so in that sense LEM is still a consequence of an axiom. The core theory of Lean is constructive.
I'm not an expert on the foundations of Lean, but I do know that funext in the source code follows only from the axioms of quotient types and the eliminator for equality. There are a number of axioms that are implicit in the type checker itself, so you might say that proof irrelevance is built-in in that way. Propositional extensionality (propext) is that propositions that imply each other are equal, and that's an axiom in the library, but funext does not depend on propext.
Correcting my non-expert inaccuracies in this thread: I just learned that Diaconescu's theorem depends on the axiom of choice, which I'd missed even though I'd glanced at the code for classical.em a few times. So, LEM definitely depends on the axiom of choice in Lean.
LEM and double-negation elimination is very poor style from a constructive POV, though. If you need to prove something non-constructively, just stick to the negative fragment.
I think your comment illustrates a difference in cultures -- mathematicians generally don't care about whether it's bad style in the constructive POV. Sure, you can 'just' stick to the negative fragment, but that 'just' is sweeping a lot of questions of ergonomics under the rug. One thing that attracted me to Lean was that I could formalize mathematics as I knew it, more or less, and there was a vibrant community with a fairly well developed library of basic classical mathematics.
I'm not saying these concerns about constructibility aren't unimportant. I do appreciate both POVs. I just don't think it's something you have to force mathematicians to worry about if all they're interested in is formalizing their math on a computer.
Something that's interesting about Lean is that double-negation elimination is used in Prop but not generally in Type and above. You have to explicitly reach for the axiom of choice if you want to "construct" a term of a type that isn't empty.
> Sure, you can 'just' stick to the negative fragment, but that 'just' is sweeping a lot of questions of ergonomics under the rug.
With all due respect, that seems a bit vague to me. What are the "questions of ergonomics" you're thinking of here? Choosing the negative form of a goal whenever you have to prove something non-constructively seems even easier ergonomically than, e.g. adding LEM as an axiom. You basically don't have to change your proof methods as long as the statement you're proving is of the appropriate form.
Ergonomics to me means "what is the moment-to-moment experience of a user of the language, in particular frictions between what the user wants to say and how it must be said." For someone who does not care much about constructibility, it is better not having to do anything differently depending on whether or not something is constructive. The workaround for such people could be to always include at least one negation for every statement, but that's a pervasive reminder of questions of constructibility! If practitioners are going to be using this transformation by default, then the language would be more ergonomic if it was just automatic.
I don't think having to think about constructibility all the time is more ergonomic than accepting that the system has a well-accepted axiom. There doesn't need to be a one-true system, of course, and for people interested in foundations, reverse mathematics, constructive mathematics, higher category theory, and homotopy type theory, there are other systems. Most mathematicians don't study these things, and accepting LEM is natural for them.
> For someone who does not care much about constructibility, it is better not having to do anything differently depending on whether or not something is constructive.
Well, there are many possible constructive 'versions' of any non-constructive statement, so 'not having to do anything or be reminde[d] of questions of constructivity', strictly speaking, leads to just sticking to the non-constructive version by default. Since it's easy, even in constructive logic, to derive the non-constructive 'version' of some statement from a constructive one, this transformation (properly understood) is as good as automatic.
Right, that's what I am getting at. If it is as good as automatic, why make a mathematician do the transformation themselves? Why make them look at and manipulate all the transformed statements when they're working out a tactic proof?
Whether or not a proposition is constructive is not something I've ever heard any mathematicians in my department ever worry about. I have only ever heard about, for example, showing a certain bound was "effective" after showing that there was a bound at all. Effective means that there is some procedure to construct the number -- but no one cares about whether the argument that shows this number is an upper bound is itself constructive. Lean with its Prop, Type 0, Type 1, ... universe hierarchy is sort of well suited for this.
I'm sure that there are interesting questions that hinge on constructibility in a proof, but again, mathematicians I talk to have never seriously thought about these things. In my field (topology), we do worry about constructing objects and invariants (and sometimes we even care about the complexity class), but at the proof level everything is classical.
If you're involved in developing proof assistants and you want mathematicians to use it, then I would suggest making it so you can change the "reasoning monad" in a file. If you put it in classical mode, it should look like you're able to use LEM, etc., and the goal window should show only untransformed statements, but then when outside the classical monad a constructivist would see the transformed statements. This would be sufficiently ergonomic.