with-abstraction regression
UlfNorell opened this issue · comments
The following works in agda-2.6.4.3 but fails on master.
open import Agda.Builtin.Nat
open import Agda.Builtin.Bool
open import Agda.Builtin.Equality
postulate
IsPreorder : {A : Set} → (A → A → Set) → (A → A → Set) → Set₁
module NatOrder where
postulate
_≤_ : Nat → Nat → Set
≤-isPreorder : IsPreorder _≡_ _≤_
module BoolOrder where
postulate
_≤_ : Bool → Bool → Set
≤-isPreorder : IsPreorder _≡_ _≤_
record HasPreorder (A : Set) (_≈_ : A → A → Set) : Set₁ where
infix 4 _≤_
field
_≤_ : A → A → Set
≤-isPreorder : IsPreorder _≈_ _≤_
open HasPreorder ⦃...⦄ public
_∋_ : ∀ {a} (A : Set a) → A → A
A ∋ x = x
instance
Nat-hasPreorder = HasPreorder _ _ ∋ record {NatOrder}
Bool-hasPreorder = HasPreorder _ _ ∋ record {BoolOrder}
data Dec (P : Set) : Set where
yes : P → Dec P
no : Dec P
case_of_ : ∀ {A B : Set} → A → (A → B) → B
case x of f = f x
record _⁇ (P : Set) : Set where
constructor ⁇_
field dec : Dec P
open _⁇ ⦃...⦄ public
¿_¿ : ∀ (X : Set) → ⦃ X ⁇ ⦄ → Dec X
¿ _ ¿ = dec
instance
postulate Dec≤ : ∀ {n m : Nat} → (n ≤ m) ⁇
top : Set
top = Nat
where -- only fails in a `where` block
IsGood : (new : Nat) → Set
IsGood new = 1 ≤ new
-- case/with over this works:
-- checkGood : ∀ new → Dec (IsGood new)
-- checkGood new = ¿ IsGood new ¿
foo : ∀ new → Bool
foo new = case ¿ IsGood new ¿ of λ where
(yes _) → true
no → true
bar : ∀ new → foo new ≡ true
bar new with ¿ IsGood new ¿ -- with-abstraction fails
... | yes _ = refl
... | no = refl
Bisection blames 403ee42.
@plt-amy do you have some time to take a look at this?
What's interesting is that it works if you give the type argument to the (unused) Bool instance:
Bool-hasPreorder = HasPreorder Bool _ ∋ record {BoolOrder}
The only difference in this case is that we add the instance to the discrimination tree with the Bool directly:
added value Bool-hasPreorder to discrimination tree with case
case 0 of
HasPreorder² → case 0 of
Bool⁰ → done {Bool-hasPreorder}
instead of first adding it as
added value Bool-hasPreorder to discrimination tree with case
case 0 of
HasPreorder² → done {Bool-hasPreorder}
and only adding the refined version once the meta is solved. I haven't been able to figure out yet why this makes a difference.
Sure, I'll take a look.
@UlfNorell My immediate guess was right: this is a result of my rather silly attempts to avoid repeatedly waking up instances. The intent was to block on the metas that caused the discrimination tree to go off and find multiple instances:
instance candidates from signature for goal:
HasPreorder Nat __≈__52
{Nat-hasPreorder, Bool-hasPreorder} length: 2
blocker:
__≈__52
mutual block:
{}
As you can tell from the amount of Bool
s, this isn't exactly stellar code; turns out many things are sensitive to the order that instance constraints are solved in (like termination checking). Computing the type of a with
isn't one of the situations I accounted for. Fixes I can see:
- I can't tell you whether this code buys us any significant performance (though I'd wager it's an improvement, since it avoids the expensive
checkCandidates
on average), so I'd be okay with getting rid of it. (i.e. delete InstanceArguments.hs lines 212-269) - The alternative is to call
wakeupConstraints_
somewhere between inferring the type of thewith
-scrutinee and computing the abstraction; the postpone-on-overlap doesn't fire when underwakeupConstraints_
. I don't know enough about the LHS checker to know where this would go, but I could have a poke.