Zulip Chat Archive
Stream: general
Topic: has_coe_to_fun instance search
Sebastien Gouezel (Jul 30 2022 at 16:45):
While investigating the timeouts in #15078, @Frédéric Dupuis noticed that this was due to a weird instance search. Here is a mwe showing the behavior:
import analysis.normed_space.basic
variables {α : Type}
set_option trace.class_instances true
lemma wtf (A : set (set α)) (a : A) : true :=
begin
have : (a : set α) = a := rfl,
have : (a : set α) = a := rfl,
trivial
end
If you put the cursor on the first have
keyword in the proof, you will see that Lean goes on a wild hunt to find a has_coe_to_fun
instance for the subtype ↥A
. And of course fails. The instance search starts with
[class_instances] class-instance resolution trace
[class_instances] (0) ?x_5 : has_coe_to_fun ↥A ?x_4 := @continuous_linear_equiv.has_coe_to_fun ?x_6 ?x_7 ?x_8 ?x_9 ?x_10 ?x_11 ?x_12 ?x_13 ?x_14 ?x_15 ?x_16 ?x_17 ?x_18 ?x_19
?x_20
?x_21
failed is_def_eq
[class_instances] (0) ?x_5 : has_coe_to_fun ↥A ?x_4 := @continuous_linear_map.to_fun ?x_22 ?x_23 ?x_24 ?x_25 ?x_26 ?x_27 ?x_28 ?x_29 ?x_30 ?x_31 ?x_32 ?x_33 ?x_34
failed is_def_eq
There are two things I don't understand here: first, why does the system look for a has_coe_to_fun
instance? And second, why doesn't it cache the failure? (You can look at the instance search trace on the second have
, it is just as long as for the first one). @Gabriel Ebner , do you have some ideas?
In such a short proof, it's not a real problem, but in a longer proof it makes things really really slow!
Kyle Miller (Jul 30 2022 at 17:01):
For type ascriptions, when there's a type mismatch the elaborator will eventually get to this line https://github.com/leanprover-community/lean/blob/master/src/frontends/lean/elaborator.cpp#L675
It checks the weak head normal form of the expected type to see if it's a pi type. And in this case, set α
is a pi type, so it appears to make a go at it!
At least, this is what I think is happening. One test would be to create a version of set
that's a structure to see if it avoids this behavior.
Kyle Miller (Jul 30 2022 at 17:04):
It might seem inconsistent that the typeclass inference starts with has_coe_to_fun ↥A ?x_4
(with a metavariable at the expected type) but mk_coercion_to_fn
doesn't take an expected type and it uses inference to infer the resulting type. Maybe this metavariable is why the instance failure isn't cached? (I don't know how the cache works.)
Sebastien Gouezel (Jul 30 2022 at 17:11):
Thanks for the explanations, they're very convincing. I'm not sure why it doesn't use the expected type, though (and of course set
shouldn't be considered a pi
type to start with...)
Kyle Miller (Jul 30 2022 at 17:23):
A quick hack would be to tell the elaborator to not consider set
to be a pi type when looking for coercions. I'm not sure if that's principled enough of a design...
Kyle Miller (Jul 30 2022 at 17:26):
Sebastien Gouezel said:
I'm not sure why it doesn't use the expected type, though
I think I get why -- when you have (a : X)
you are happy if a
coerces to something that has a type defeq to X
, but if you give typeclass inference X
then it'll force it to find something that's syntactically X
.
Last updated: Dec 20 2023 at 11:08 UTC