{-# OPTIONS_GHC -Wunused-imports #-}

{-|

This module implements the type checking part of generalisable variables. When we get here we have
a type checking problem for a type (or telescope) containing a known set of generalisable variables
and we need to produce a well typed type (or telescope) with the correct generalisations. For instance,
given

@
variable
  A  : Set
  n  : Nat
  xs : Vec A n

foo : SomeType xs
@

generalisation should produce @{A : Set} {n : Nat} {xs : Vec A n} → SomeType xs@ for the type of
@foo@.

The functions `generalizeType` and `generalizeTelescope` don't have access to the abstract syntax to
be type checked (@SomeType xs@ in the example). Instead they are provided a type checking action
that delivers a `Type` or a `Telescope`. The challenge is setting up a context in which @SomeType
xs@ can be type checked successfully by this action, without knowing what the telescope of
generalised variables will be. Once we have computed this telescope the result needs to be
transformed into a well typed type abstracted over it.

__At no point are we allowed to cheat!__ Any transformation between well typed terms needs to be done
by well typed substitutions.

The key idea is to run the type checking action in the context of a single variable of an unknown
type. Once we know what variables to generalise over this type is instantiated to a fresh record
type with a field for each generalised variable. Turning the result of action into something valid
in the context of the generalised variables is then a simple substitution unpacking the record
variable.

In more detail, generalisation proceeds as follows:

- Add a variable @genTel@ of an unknown type to the context (`withGenRecVar`).

@
  (genTel : _GenTel)
@

- Create metavariables for the generalisable variables appearing in the problem and their
  dependencies (`createGenValues`). In the example this would be

@
  (genTel : _GenTel) ⊢
    _A  : Set
    _n  : Nat
    _xs : Vec _A _n
@

- Run the type checking action (`createMetasAndTypeCheck`), binding the mentioned generalisable
  variables to the corresponding newly created metavariables. This binding is stored in
  `eGeneralizedVars` and picked up in `Agda.TypeChecking.Rules.Application.inferDef`

@
  (genTel : _GenTel) ⊢ SomeType (_xs genTel)
@

- Compute the telescope of generalised variables (`computeGeneralization`). This is done by taking
  the unconstrained metavariables created by `createGenValues` or created during the type checking
  action and sorting them into a well formed telescope.

@
  {A : Set} {n : Nat} {xs : Vec A n}
@

- Create a record type @GeneralizeTel@ whose fields are the generalised variables and instantiate
  the type of @genTel@ to it (`createGenRecordType`).

@
  record GeneralizeTel : Set₁ where
    constructor mkGeneralizeTel
    field
      A  : Set
      n  : Nat
      xs : Vec A n
@

- Solve the metavariables with their corresponding projections from @genTel@.

@
  _A  := λ genTel → genTel .A
  _n  := λ genTel → genTel .n
  _xs := λ genTel → genTel .xs
@

- Build the unpacking substitution (`unpackSub`) that maps terms in @(genTel : GeneralizeTel)@ to
  terms in the context of the generalised variables by substituting a record value for @genTel@.

@
  {A : Set} {n : Nat} {xs : Vec A n} ⊢ [mkGeneralizeTel A n xs / genTel] : (genTel : GeneralizeTel)
@

- Build the final result by applying the unpacking substitution to the result of the type checking
  action and abstracting over the generalised telescope.

@
  {A : Set} {n : Nat} {xs : Vec A n} → SomeType (_xs (mkGeneralizeTel A n xs)) ==
  {A : Set} {n : Nat} {xs : Vec A n} → SomeType xs
@

- In case of `generalizeType` return the resulting pi type.
- In case of `generalizeTelescope` enter the resulting context, applying the unpacking substitution
  to let bindings (TODO #6916: and also module applications!) created in the telescope, and call the
  continuation.

-}

module Agda.TypeChecking.Generalize
  ( generalizeType
  , generalizeType'
  , generalizeTelescope ) where

import Prelude hiding (null)

import Control.Arrow ((&&&), first)
import Control.Monad
import Control.Monad.Except

import qualified Data.IntSet as IntSet
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Data.Map.Strict as MapS
import Data.List (partition, sortBy)
import Data.Monoid
import Data.Function (on)

import Agda.Interaction.Options.Base

import Agda.Syntax.Common
import Agda.Syntax.Common.Pretty (prettyShow, singPlural)
import Agda.Syntax.Concrete.Name (LensInScope(..))
import Agda.Syntax.Position
import Agda.Syntax.Info          (MetaNameSuggestion)
import Agda.Syntax.Internal
import Agda.Syntax.Internal.Generic
import Agda.Syntax.Internal.MetaVars
import Agda.Syntax.Scope.Monad (bindVariable, outsideLocalVars)
import Agda.Syntax.Scope.Base (BindingSource(..))
import Agda.TypeChecking.Monad
import Agda.TypeChecking.Constraints
import Agda.TypeChecking.Conversion
import Agda.TypeChecking.Free
import Agda.TypeChecking.InstanceArguments (postponeInstanceConstraints)
import Agda.TypeChecking.MetaVars
import Agda.TypeChecking.Pretty
import Agda.TypeChecking.Reduce
import Agda.TypeChecking.Substitute
import Agda.TypeChecking.Telescope
import Agda.TypeChecking.Warnings

import Agda.Benchmarking (Phase(Typing, Generalize))
import Agda.Utils.Benchmark
import qualified Agda.Utils.BiMap as BiMap
import Agda.Utils.Functor
import Agda.Utils.Impossible
import Agda.Utils.Lens
import Agda.Utils.List (downFrom, hasElem)
import Agda.Utils.Maybe
import Agda.Utils.Monad
import Agda.Utils.Null
import Agda.Utils.Size
import Agda.Utils.Permutation

-- | Generalize a telescope over a set of generalizable variables.
generalizeTelescope :: Map QName Name -> (forall a. (Telescope -> TCM a) -> TCM a) -> ([Maybe Name] -> Telescope -> TCM a) -> TCM a
generalizeTelescope :: forall a.
Map QName Name
-> (forall a. (Telescope -> TCM a) -> TCM a)
-> ([Maybe Name] -> Telescope -> TCM a)
-> TCM a
generalizeTelescope Map QName Name
vars forall a. (Telescope -> TCM a) -> TCM a
typecheckAction [Maybe Name] -> Telescope -> TCM a
ret | Map QName Name -> Bool
forall k a. Map k a -> Bool
Map.null Map QName Name
vars = (Telescope -> TCM a) -> TCM a
forall a. (Telescope -> TCM a) -> TCM a
typecheckAction ([Maybe Name] -> Telescope -> TCM a
ret [])
generalizeTelescope Map QName Name
vars forall a. (Telescope -> TCM a) -> TCM a
typecheckAction [Maybe Name] -> Telescope -> TCM a
ret = Account (BenchPhase (TCMT IO)) -> TCM a -> TCM a
forall (m :: * -> *) c.
MonadBench m =>
Account (BenchPhase m) -> m c -> m c
billTo [BenchPhase (TCMT IO)
Phase
Typing, BenchPhase (TCMT IO)
Phase
Generalize] (TCM a -> TCM a) -> TCM a -> TCM a
forall a b. (a -> b) -> a -> b
$ (Type -> TCM a) -> TCM a
forall a. (Type -> TCM a) -> TCM a
withGenRecVar ((Type -> TCM a) -> TCM a) -> (Type -> TCM a) -> TCM a
forall a b. (a -> b) -> a -> b
$ \ Type
genRecMeta -> do
  let s :: Set QName
s = Map QName Name -> Set QName
forall k a. Map k a -> Set k
Map.keysSet Map QName Name
vars
  (([Name]
cxtNames, Telescope
tel, [(Name, LetBinding)]
letbinds), Map MetaId QName
namedMetas, LocalMetaStores
allmetas) <-
    Set QName
-> TCM ([Name], Telescope, [(Name, LetBinding)])
-> TCM
     (([Name], Telescope, [(Name, LetBinding)]), Map MetaId QName,
      LocalMetaStores)
forall a.
Set QName -> TCM a -> TCM (a, Map MetaId QName, LocalMetaStores)
createMetasAndTypeCheck Set QName
s (TCM ([Name], Telescope, [(Name, LetBinding)])
 -> TCM
      (([Name], Telescope, [(Name, LetBinding)]), Map MetaId QName,
       LocalMetaStores))
-> TCM ([Name], Telescope, [(Name, LetBinding)])
-> TCM
     (([Name], Telescope, [(Name, LetBinding)]), Map MetaId QName,
      LocalMetaStores)
forall a b. (a -> b) -> a -> b
$ (Telescope -> TCM ([Name], Telescope, [(Name, LetBinding)]))
-> TCM ([Name], Telescope, [(Name, LetBinding)])
forall a. (Telescope -> TCM a) -> TCM a
typecheckAction ((Telescope -> TCM ([Name], Telescope, [(Name, LetBinding)]))
 -> TCM ([Name], Telescope, [(Name, LetBinding)]))
-> (Telescope -> TCM ([Name], Telescope, [(Name, LetBinding)]))
-> TCM ([Name], Telescope, [(Name, LetBinding)])
forall a b. (a -> b) -> a -> b
$ \ Telescope
tel -> do
      Context
cxt <- Int -> Context -> Context
forall a. Int -> [a] -> [a]
take (Telescope -> Int
forall a. Sized a => a -> Int
size Telescope
tel) (Context -> Context) -> TCMT IO Context -> TCMT IO Context
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCMT IO Context
forall (m :: * -> *). MonadTCEnv m => m Context
getContext
      [(Name, LetBinding)]
lbs <- TCMT IO [(Name, LetBinding)]
forall (tcm :: * -> *). MonadTCEnv tcm => tcm [(Name, LetBinding)]
getLetBindings -- This gives let-bindings valid in the current context
      ([Name], Telescope, [(Name, LetBinding)])
-> TCM ([Name], Telescope, [(Name, LetBinding)])
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((Dom' Term (Name, Type) -> Name) -> Context -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map ((Name, Type) -> Name
forall a b. (a, b) -> a
fst ((Name, Type) -> Name)
-> (Dom' Term (Name, Type) -> (Name, Type))
-> Dom' Term (Name, Type)
-> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dom' Term (Name, Type) -> (Name, Type)
forall t e. Dom' t e -> e
unDom) Context
cxt, Telescope
tel, [(Name, LetBinding)]
lbs)

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.metas" Int
60 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ TCMT IO Doc
"open metas =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> (String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text (String -> TCMT IO Doc)
-> (Map MetaId MetaVariable -> String)
-> Map MetaId MetaVariable
-> TCMT IO Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map MetaId (String, Arg DoGeneralize) -> String
forall a. Show a => a -> String
show (Map MetaId (String, Arg DoGeneralize) -> String)
-> (Map MetaId MetaVariable
    -> Map MetaId (String, Arg DoGeneralize))
-> Map MetaId MetaVariable
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaVariable -> (String, Arg DoGeneralize))
-> Map MetaId MetaVariable -> Map MetaId (String, Arg DoGeneralize)
forall a b. (a -> b) -> Map MetaId a -> Map MetaId b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((MetaInfo -> String
miNameSuggestion (MetaInfo -> String)
-> (MetaInfo -> Arg DoGeneralize)
-> MetaInfo
-> (String, Arg DoGeneralize)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& MetaInfo -> Arg DoGeneralize
miGeneralizable) (MetaInfo -> (String, Arg DoGeneralize))
-> (MetaVariable -> MetaInfo)
-> MetaVariable
-> (String, Arg DoGeneralize)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaVariable -> MetaInfo
mvInfo)) (LocalMetaStores -> Map MetaId MetaVariable
openMetas (LocalMetaStores -> Map MetaId MetaVariable)
-> LocalMetaStores -> Map MetaId MetaVariable
forall a b. (a -> b) -> a -> b
$ LocalMetaStores
allmetas)
    ]
  -- Translate the QName to the corresponding bound variable
  (Telescope
genTel, [Maybe QName]
genTelNames, Substitution
sub) <- Type
-> Map MetaId QName
-> LocalMetaStores
-> TCM (Telescope, [Maybe QName], Substitution)
forall name.
Type
-> Map MetaId name
-> LocalMetaStores
-> TCM (Telescope, [Maybe name], Substitution)
computeGeneralization Type
genRecMeta Map MetaId QName
namedMetas LocalMetaStores
allmetas

  let boundVar :: QName -> Name
boundVar QName
q = Name -> Maybe Name -> Name
forall a. a -> Maybe a -> a
fromMaybe Name
forall a. HasCallStack => a
__IMPOSSIBLE__ (Maybe Name -> Name) -> Maybe Name -> Name
forall a b. (a -> b) -> a -> b
$ QName -> Map QName Name -> Maybe Name
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup QName
q Map QName Name
vars
      genTelVars :: [Maybe Name]
genTelVars = ((Maybe QName -> Maybe Name) -> [Maybe QName] -> [Maybe Name]
forall a b. (a -> b) -> [a] -> [b]
map ((Maybe QName -> Maybe Name) -> [Maybe QName] -> [Maybe Name])
-> ((QName -> Name) -> Maybe QName -> Maybe Name)
-> (QName -> Name)
-> [Maybe QName]
-> [Maybe Name]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (QName -> Name) -> Maybe QName -> Maybe Name
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) QName -> Name
boundVar [Maybe QName]
genTelNames

  Telescope
tel' <- Substitution' (SubstArg Telescope) -> Telescope -> Telescope
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst Substitution
Substitution' (SubstArg Telescope)
sub (Telescope -> Telescope) -> TCMT IO Telescope -> TCMT IO Telescope
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Telescope -> TCMT IO Telescope
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull Telescope
tel

  -- This is not so nice. When changing the context from Γ (r : R) to Γ Δ we need to do this at the
  -- level of contexts (as a Context -> Context function), so we repeat the name logic here. Take
  -- care to preserve the name of named generalized variables.
  let setName :: c -> f (b, d) -> f (c, d)
setName c
name f (b, d)
d = (b -> c) -> (b, d) -> (c, d)
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (c -> b -> c
forall a b. a -> b -> a
const c
name) ((b, d) -> (c, d)) -> f (b, d) -> f (c, d)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f (b, d)
d
      cxtEntry :: (Maybe Name, Dom' t (b, d)) -> m (Dom' t (Name, d))
cxtEntry (Maybe Name
mname, Dom' t (b, d)
d) = do
          Name
name <- m Name -> (Name -> m Name) -> Maybe Name -> m Name
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Name -> Name
forall a. LensInScope a => a -> a
setNotInScope (Name -> Name) -> m Name -> m Name
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b -> m Name
forall a (m :: * -> *).
(FreshName a, MonadFresh NameId m) =>
a -> m Name
forall (m :: * -> *). MonadFresh NameId m => b -> m Name
freshName_ b
s) Name -> m Name
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Name
mname
          Dom' t (Name, d) -> m (Dom' t (Name, d))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Dom' t (Name, d) -> m (Dom' t (Name, d)))
-> Dom' t (Name, d) -> m (Dom' t (Name, d))
forall a b. (a -> b) -> a -> b
$ Name -> Dom' t (b, d) -> Dom' t (Name, d)
forall {f :: * -> *} {c} {b} {d}.
Functor f =>
c -> f (b, d) -> f (c, d)
setName Name
name Dom' t (b, d)
d
        where s :: b
s  = (b, d) -> b
forall a b. (a, b) -> a
fst ((b, d) -> b) -> (b, d) -> b
forall a b. (a -> b) -> a -> b
$ Dom' t (b, d) -> (b, d)
forall t e. Dom' t e -> e
unDom Dom' t (b, d)
d
      dropCxt :: Impossible -> m a -> m a
dropCxt Impossible
err = Substitution -> (Context -> Context) -> m a -> m a
forall a. Substitution -> (Context -> Context) -> m a -> m a
forall (m :: * -> *) a.
MonadAddContext m =>
Substitution -> (Context -> Context) -> m a -> m a
updateContext (Impossible -> Int -> Substitution
forall a. Impossible -> Int -> Substitution' a
strengthenS Impossible
err Int
1) (Int -> Context -> Context
forall a. Int -> [a] -> [a]
drop Int
1)
  Context
genTelCxt <- Impossible -> TCMT IO Context -> TCMT IO Context
forall {m :: * -> *} {a}.
MonadAddContext m =>
Impossible -> m a -> m a
dropCxt Impossible
forall a. HasCallStack => a
__IMPOSSIBLE__ (TCMT IO Context -> TCMT IO Context)
-> TCMT IO Context -> TCMT IO Context
forall a b. (a -> b) -> a -> b
$ ((Maybe Name, Dom (String, Type))
 -> TCMT IO (Dom' Term (Name, Type)))
-> [(Maybe Name, Dom (String, Type))] -> TCMT IO Context
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Maybe Name, Dom (String, Type))
-> TCMT IO (Dom' Term (Name, Type))
forall {m :: * -> *} {b} {t} {d}.
(FreshName b, MonadFresh NameId m) =>
(Maybe Name, Dom' t (b, d)) -> m (Dom' t (Name, d))
cxtEntry ([(Maybe Name, Dom (String, Type))] -> TCMT IO Context)
-> [(Maybe Name, Dom (String, Type))] -> TCMT IO Context
forall a b. (a -> b) -> a -> b
$ [(Maybe Name, Dom (String, Type))]
-> [(Maybe Name, Dom (String, Type))]
forall a. [a] -> [a]
reverse ([(Maybe Name, Dom (String, Type))]
 -> [(Maybe Name, Dom (String, Type))])
-> [(Maybe Name, Dom (String, Type))]
-> [(Maybe Name, Dom (String, Type))]
forall a b. (a -> b) -> a -> b
$ [Maybe Name]
-> [Dom (String, Type)] -> [(Maybe Name, Dom (String, Type))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Maybe Name]
genTelVars ([Dom (String, Type)] -> [(Maybe Name, Dom (String, Type))])
-> [Dom (String, Type)] -> [(Maybe Name, Dom (String, Type))]
forall a b. (a -> b) -> a -> b
$ Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
genTel

  -- For the explicit module telescope we get the names from the typecheck
  -- action.
  let newTelCxt :: Context
newTelCxt = (Name -> Dom (String, Type) -> Dom' Term (Name, Type))
-> [Name] -> [Dom (String, Type)] -> Context
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Name -> Dom (String, Type) -> Dom' Term (Name, Type)
forall {f :: * -> *} {c} {b} {d}.
Functor f =>
c -> f (b, d) -> f (c, d)
setName [Name]
cxtNames ([Dom (String, Type)] -> Context)
-> [Dom (String, Type)] -> Context
forall a b. (a -> b) -> a -> b
$ [Dom (String, Type)] -> [Dom (String, Type)]
forall a. [a] -> [a]
reverse ([Dom (String, Type)] -> [Dom (String, Type)])
-> [Dom (String, Type)] -> [Dom (String, Type)]
forall a b. (a -> b) -> a -> b
$ Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
tel'

  -- We are in context Γ (r : R) and should call the continuation in context Γ Δ Θρ passing it Δ Θρ
  -- We have
  --   Γ (r : R) ⊢ Θ            Θ = tel
  --   Γ ⊢ Δ                    Δ = genTel
  --   Γ Δ ⊢ ρ : Γ (r : R)      ρ = sub
  --   Γ ⊢ Δ Θρ                 Θρ = tel'
  -- And we shouldn't forget about the let-bindings (#3470)
  --   Γ (r : R) Θ ⊢ letbinds
  --   Γ Δ Θρ      ⊢ letbinds' = letbinds(lift |Θ| ρ)
  -- And modules created in the telescope (#6916)
  --   TODO
  [(Name, LetBinding)]
letbinds' <- Substitution' (SubstArg [(Name, LetBinding)])
-> [(Name, LetBinding)] -> [(Name, LetBinding)]
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst (Int -> Substitution -> Substitution
forall a. Int -> Substitution' a -> Substitution' a
liftS (Telescope -> Int
forall a. Sized a => a -> Int
size Telescope
tel) Substitution
sub) ([(Name, LetBinding)] -> [(Name, LetBinding)])
-> TCMT IO [(Name, LetBinding)] -> TCMT IO [(Name, LetBinding)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Name, LetBinding)] -> TCMT IO [(Name, LetBinding)]
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull [(Name, LetBinding)]
letbinds
  let addLet :: (Name, LetBinding) -> m a -> m a
addLet (Name
x, LetBinding Origin
o Term
v Dom Type
dom) = Origin -> Name -> Term -> Dom Type -> m a -> m a
forall a. Origin -> Name -> Term -> Dom Type -> m a -> m a
forall (m :: * -> *) a.
MonadAddContext m =>
Origin -> Name -> Term -> Dom Type -> m a -> m a
addLetBinding' Origin
o Name
x Term
v Dom Type
dom

  Substitution -> (Context -> Context) -> TCM a -> TCM a
forall a.
Substitution -> (Context -> Context) -> TCMT IO a -> TCMT IO a
forall (m :: * -> *) a.
MonadAddContext m =>
Substitution -> (Context -> Context) -> m a -> m a
updateContext Substitution
sub ((Context
genTelCxt Context -> Context -> Context
forall a. [a] -> [a] -> [a]
++) (Context -> Context) -> (Context -> Context) -> Context -> Context
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Context -> Context
forall a. Int -> [a] -> [a]
drop Int
1) (TCM a -> TCM a) -> TCM a -> TCM a
forall a b. (a -> b) -> a -> b
$
    Substitution -> (Context -> Context) -> TCM a -> TCM a
forall a.
Substitution -> (Context -> Context) -> TCMT IO a -> TCMT IO a
forall (m :: * -> *) a.
MonadAddContext m =>
Substitution -> (Context -> Context) -> m a -> m a
updateContext (Int -> Substitution
forall a. Int -> Substitution' a
raiseS (Telescope -> Int
forall a. Sized a => a -> Int
size Telescope
tel')) (Context
newTelCxt Context -> Context -> Context
forall a. [a] -> [a] -> [a]
++) (TCM a -> TCM a) -> TCM a -> TCM a
forall a b. (a -> b) -> a -> b
$
      ((Name, LetBinding) -> TCM a -> TCM a)
-> TCM a -> [(Name, LetBinding)] -> TCM a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Name, LetBinding) -> TCM a -> TCM a
forall {m :: * -> *} {a}.
MonadAddContext m =>
(Name, LetBinding) -> m a -> m a
addLet ([Maybe Name] -> Telescope -> TCM a
ret [Maybe Name]
genTelVars (Telescope -> TCM a) -> Telescope -> TCM a
forall a b. (a -> b) -> a -> b
$ Telescope -> Telescope -> Telescope
forall t. Abstract t => Telescope -> t -> t
abstract Telescope
genTel Telescope
tel') [(Name, LetBinding)]
letbinds'


-- | Generalize a type over a set of (used) generalizable variables.
generalizeType :: Set QName -> TCM Type -> TCM ([Maybe QName], Type)
generalizeType :: Set QName -> TCM Type -> TCM ([Maybe QName], Type)
generalizeType Set QName
s TCM Type
typecheckAction = do
  ([Maybe QName]
ns, Type
t, ()
_) <- Set QName -> TCM (Type, ()) -> TCM ([Maybe QName], Type, ())
forall a.
Set QName -> TCM (Type, a) -> TCM ([Maybe QName], Type, a)
generalizeType' Set QName
s (TCM (Type, ()) -> TCM ([Maybe QName], Type, ()))
-> TCM (Type, ()) -> TCM ([Maybe QName], Type, ())
forall a b. (a -> b) -> a -> b
$ (,()) (Type -> (Type, ())) -> TCM Type -> TCM (Type, ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCM Type
typecheckAction
  ([Maybe QName], Type) -> TCM ([Maybe QName], Type)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Maybe QName]
ns, Type
t)

-- | Allow returning additional information from the type checking action.
generalizeType' :: Set QName -> TCM (Type, a) -> TCM ([Maybe QName], Type, a)
generalizeType' :: forall a.
Set QName -> TCM (Type, a) -> TCM ([Maybe QName], Type, a)
generalizeType' Set QName
s TCM (Type, a)
typecheckAction = Account (BenchPhase (TCMT IO))
-> TCMT IO ([Maybe QName], Type, a)
-> TCMT IO ([Maybe QName], Type, a)
forall (m :: * -> *) c.
MonadBench m =>
Account (BenchPhase m) -> m c -> m c
billTo [BenchPhase (TCMT IO)
Phase
Typing, BenchPhase (TCMT IO)
Phase
Generalize] (TCMT IO ([Maybe QName], Type, a)
 -> TCMT IO ([Maybe QName], Type, a))
-> TCMT IO ([Maybe QName], Type, a)
-> TCMT IO ([Maybe QName], Type, a)
forall a b. (a -> b) -> a -> b
$ (Type -> TCMT IO ([Maybe QName], Type, a))
-> TCMT IO ([Maybe QName], Type, a)
forall a. (Type -> TCM a) -> TCM a
withGenRecVar ((Type -> TCMT IO ([Maybe QName], Type, a))
 -> TCMT IO ([Maybe QName], Type, a))
-> (Type -> TCMT IO ([Maybe QName], Type, a))
-> TCMT IO ([Maybe QName], Type, a)
forall a b. (a -> b) -> a -> b
$ \ Type
genRecMeta -> do

  ((Type
t, a
userdata), Map MetaId QName
namedMetas, LocalMetaStores
allmetas) <- Set QName
-> TCM (Type, a)
-> TCM ((Type, a), Map MetaId QName, LocalMetaStores)
forall a.
Set QName -> TCM a -> TCM (a, Map MetaId QName, LocalMetaStores)
createMetasAndTypeCheck Set QName
s TCM (Type, a)
typecheckAction

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.metas" Int
60 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ TCMT IO Doc
"open metas =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> (String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text (String -> TCMT IO Doc)
-> (Map MetaId MetaVariable -> String)
-> Map MetaId MetaVariable
-> TCMT IO Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map MetaId (String, Arg DoGeneralize) -> String
forall a. Show a => a -> String
show (Map MetaId (String, Arg DoGeneralize) -> String)
-> (Map MetaId MetaVariable
    -> Map MetaId (String, Arg DoGeneralize))
-> Map MetaId MetaVariable
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaVariable -> (String, Arg DoGeneralize))
-> Map MetaId MetaVariable -> Map MetaId (String, Arg DoGeneralize)
forall a b. (a -> b) -> Map MetaId a -> Map MetaId b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((MetaInfo -> String
miNameSuggestion (MetaInfo -> String)
-> (MetaInfo -> Arg DoGeneralize)
-> MetaInfo
-> (String, Arg DoGeneralize)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& MetaInfo -> Arg DoGeneralize
miGeneralizable) (MetaInfo -> (String, Arg DoGeneralize))
-> (MetaVariable -> MetaInfo)
-> MetaVariable
-> (String, Arg DoGeneralize)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaVariable -> MetaInfo
mvInfo)) (LocalMetaStores -> Map MetaId MetaVariable
openMetas (LocalMetaStores -> Map MetaId MetaVariable)
-> LocalMetaStores -> Map MetaId MetaVariable
forall a b. (a -> b) -> a -> b
$ LocalMetaStores
allmetas)
    ]

  (Telescope
genTel, [Maybe QName]
genTelNames, Substitution
sub) <- Type
-> Map MetaId QName
-> LocalMetaStores
-> TCM (Telescope, [Maybe QName], Substitution)
forall name.
Type
-> Map MetaId name
-> LocalMetaStores
-> TCM (Telescope, [Maybe name], Substitution)
computeGeneralization Type
genRecMeta Map MetaId QName
namedMetas LocalMetaStores
allmetas

  Type
t' <- Telescope -> Type -> Type
forall t. Abstract t => Telescope -> t -> t
abstract Telescope
genTel (Type -> Type) -> (Type -> Type) -> Type -> Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Substitution' (SubstArg Type) -> Type -> Type
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst Substitution
Substitution' (SubstArg Type)
sub (Type -> Type) -> TCM Type -> TCM Type
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Type -> TCM Type
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull Type
t

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
40 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ TCMT IO Doc
"generalized"
    , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"t =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Impossible -> Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *) a.
MonadAddContext m =>
Impossible -> Int -> m a -> m a
escapeContext Impossible
HasCallStack => Impossible
impossible Int
1 (Type -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Type -> m Doc
prettyTCM Type
t') ]

  ([Maybe QName], Type, a) -> TCMT IO ([Maybe QName], Type, a)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Maybe QName]
genTelNames, Type
t', a
userdata)

-- | Create metas for the generalizable variables and run the type check action.
createMetasAndTypeCheck ::
  Set QName -> TCM a -> TCM (a, Map MetaId QName, LocalMetaStores)
createMetasAndTypeCheck :: forall a.
Set QName -> TCM a -> TCM (a, Map MetaId QName, LocalMetaStores)
createMetasAndTypeCheck Set QName
s TCM a
typecheckAction = do
  ((Map MetaId QName
namedMetas, a
x), LocalMetaStores
allmetas) <- TCMT IO (Map MetaId QName, a)
-> TCMT IO ((Map MetaId QName, a), LocalMetaStores)
forall (m :: * -> *) a.
ReadTCState m =>
m a -> m (a, LocalMetaStores)
metasCreatedBy (TCMT IO (Map MetaId QName, a)
 -> TCMT IO ((Map MetaId QName, a), LocalMetaStores))
-> TCMT IO (Map MetaId QName, a)
-> TCMT IO ((Map MetaId QName, a), LocalMetaStores)
forall a b. (a -> b) -> a -> b
$ do
    (Map MetaId QName
metamap, Map QName GeneralizedValue
genvals) <- Set QName -> TCM (Map MetaId QName, Map QName GeneralizedValue)
createGenValues Set QName
s
    a
x <- Lens' TCEnv (Map QName GeneralizedValue)
-> (Map QName GeneralizedValue -> Map QName GeneralizedValue)
-> TCM a
-> TCM a
forall (m :: * -> *) a b.
MonadTCEnv m =>
Lens' TCEnv a -> (a -> a) -> m b -> m b
locallyTC (Map QName GeneralizedValue -> f (Map QName GeneralizedValue))
-> TCEnv -> f TCEnv
Lens' TCEnv (Map QName GeneralizedValue)
eGeneralizedVars (Map QName GeneralizedValue
-> Map QName GeneralizedValue -> Map QName GeneralizedValue
forall a b. a -> b -> a
const Map QName GeneralizedValue
genvals) TCM a
typecheckAction
    (Map MetaId QName, a) -> TCMT IO (Map MetaId QName, a)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Map MetaId QName
metamap, a
x)
  (a, Map MetaId QName, LocalMetaStores)
-> TCM (a, Map MetaId QName, LocalMetaStores)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
x, Map MetaId QName
namedMetas, LocalMetaStores
allmetas)

-- | Add a placeholder variable that will be substituted with a record value packing up all the
--   generalized variables.
withGenRecVar :: (Type -> TCM a) -> TCM a
withGenRecVar :: forall a. (Type -> TCM a) -> TCM a
withGenRecVar Type -> TCM a
ret = do
  -- Create a meta type (in Set₀) for the telescope record. It won't
  -- necessarily fit in Set₀, but since it's only used locally the sort
  -- shouldn't matter. Another option would be to put it in Setω, which is a
  -- bit more honest, but this leads to performance problems (see #3306).
  Type
genRecMeta <- Sort -> TCM Type
newTypeMeta (Integer -> Sort
mkType Integer
0)
  Dom (String, Type) -> TCM a -> TCM a
forall b (m :: * -> *) a.
(AddContext b, MonadAddContext m) =>
b -> m a -> m a
forall (m :: * -> *) a.
MonadAddContext m =>
Dom (String, Type) -> m a -> m a
addContext ((String, Type) -> Dom (String, Type)
forall a. a -> Dom a
defaultDom (String
"genTel" :: String, Type
genRecMeta)) (TCM a -> TCM a) -> TCM a -> TCM a
forall a b. (a -> b) -> a -> b
$ Type -> TCM a
ret Type
genRecMeta

-- | Compute the generalized telescope from metas created when checking the *thing* (type or telescope) to be
--   generalized. Called in the context extended with the telescope record variable (whose type is
--   the first argument). Returns the telescope of generalized variables and a substitution from
--   this telescope to the current context.
computeGeneralization
  :: Type
       -- ^ The metavariable to be instantiated with record type containing
       --   as fields the variables generalized in the *thing*.
  -> Map MetaId name
       -- ^ Metas created from an occurrence of a @variable@. (The original free variables.)
       --   E.g. if you have
       --   @
       --     variable  l : Level; A : Set l
       --     postulate f : A → A
       --   @
       --   then @A@ would be in this @Map@, but not @l@.
  -> LocalMetaStores
       -- ^ The metas created when type-checking the *thing*.
  -> TCM (Telescope, [Maybe name], Substitution)
       -- ^ The telescope together with binder name (left-to-right order),
       --   and substitution from this telescope to the current context.
computeGeneralization :: forall name.
Type
-> Map MetaId name
-> LocalMetaStores
-> TCM (Telescope, [Maybe name], Substitution)
computeGeneralization Type
genRecMeta Map MetaId name
nameMap LocalMetaStores
allmetas = TCM (Telescope, [Maybe name], Substitution)
-> TCM (Telescope, [Maybe name], Substitution)
forall a. TCM a -> TCM a
postponeInstanceConstraints (TCM (Telescope, [Maybe name], Substitution)
 -> TCM (Telescope, [Maybe name], Substitution))
-> TCM (Telescope, [Maybe name], Substitution)
-> TCM (Telescope, [Maybe name], Substitution)
forall a b. (a -> b) -> a -> b
$ do

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
10 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"computing generalization for type" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Type -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Type -> m Doc
prettyTCM Type
genRecMeta

  -- Pair metas with their metaInfo
  let mvs :: [(MetaId, MetaVariable)]
      mvs :: [(MetaId, MetaVariable)]
mvs = Map MetaId MetaVariable -> [(MetaId, MetaVariable)]
forall k a. Map k a -> [(k, a)]
MapS.assocs (LocalMetaStores -> Map MetaId MetaVariable
openMetas LocalMetaStores
allmetas) [(MetaId, MetaVariable)]
-> [(MetaId, MetaVariable)] -> [(MetaId, MetaVariable)]
forall a. [a] -> [a] -> [a]
++
            Map MetaId MetaVariable -> [(MetaId, MetaVariable)]
forall k a. Map k a -> [(k, a)]
MapS.assocs (LocalMetaStores -> Map MetaId MetaVariable
solvedMetas LocalMetaStores
allmetas)

  -- Issue 4727: filter out metavariables that were created before the
  -- current checkpoint, since they are too old to be generalized.
  -- TODO: make metasCreatedBy smarter so it doesn't see pruned
  -- versions of old metas as new metas.
  CheckpointId
cp <- Lens' TCEnv CheckpointId -> TCMT IO CheckpointId
forall (m :: * -> *) a. MonadTCEnv m => Lens' TCEnv a -> m a
viewTC (CheckpointId -> f CheckpointId) -> TCEnv -> f TCEnv
Lens' TCEnv CheckpointId
eCurrentCheckpoint
  let isFreshMeta :: MonadReduce m => MetaVariable -> m Bool
      isFreshMeta :: forall (m :: * -> *). MonadReduce m => MetaVariable -> m Bool
isFreshMeta MetaVariable
mv = MetaVariable -> (Range -> m Bool) -> m Bool
forall (m :: * -> *) c a b.
(MonadTCEnv m, ReadTCState m, LensClosure c a) =>
c -> (a -> m b) -> m b
enterClosure MetaVariable
mv ((Range -> m Bool) -> m Bool) -> (Range -> m Bool) -> m Bool
forall a b. (a -> b) -> a -> b
$ \ Range
_ -> Maybe Substitution -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Substitution -> Bool) -> m (Maybe Substitution) -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CheckpointId -> m (Maybe Substitution)
forall (tcm :: * -> *).
MonadTCEnv tcm =>
CheckpointId -> tcm (Maybe Substitution)
checkpointSubstitution' CheckpointId
cp
  [(MetaId, MetaVariable)]
mvs :: [(MetaId, MetaVariable)] <- ((MetaId, MetaVariable) -> TCMT IO Bool)
-> [(MetaId, MetaVariable)] -> TCMT IO [(MetaId, MetaVariable)]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (MetaVariable -> TCMT IO Bool
forall (m :: * -> *). MonadReduce m => MetaVariable -> m Bool
isFreshMeta (MetaVariable -> TCMT IO Bool)
-> ((MetaId, MetaVariable) -> MetaVariable)
-> (MetaId, MetaVariable)
-> TCMT IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaId, MetaVariable) -> MetaVariable
forall a b. (a, b) -> b
snd) [(MetaId, MetaVariable)]
mvs

  [ProblemConstraint]
cs <- [ProblemConstraint] -> [ProblemConstraint] -> [ProblemConstraint]
forall a. [a] -> [a] -> [a]
(++) ([ProblemConstraint] -> [ProblemConstraint] -> [ProblemConstraint])
-> TCMT IO [ProblemConstraint]
-> TCMT IO ([ProblemConstraint] -> [ProblemConstraint])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Lens' TCState [ProblemConstraint] -> TCMT IO [ProblemConstraint]
forall (m :: * -> *) a. ReadTCState m => Lens' TCState a -> m a
useTC ([ProblemConstraint] -> f [ProblemConstraint])
-> TCState -> f TCState
Lens' TCState [ProblemConstraint]
stAwakeConstraints
             TCMT IO ([ProblemConstraint] -> [ProblemConstraint])
-> TCMT IO [ProblemConstraint] -> TCMT IO [ProblemConstraint]
forall a b. TCMT IO (a -> b) -> TCMT IO a -> TCMT IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Lens' TCState [ProblemConstraint] -> TCMT IO [ProblemConstraint]
forall (m :: * -> *) a. ReadTCState m => Lens' TCState a -> m a
useTC ([ProblemConstraint] -> f [ProblemConstraint])
-> TCState -> f TCState
Lens' TCState [ProblemConstraint]
stSleepingConstraints

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
50 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"current constraints:" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<?> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat ((ProblemConstraint -> TCMT IO Doc)
-> [ProblemConstraint] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map ProblemConstraint -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => ProblemConstraint -> m Doc
prettyTCM [ProblemConstraint]
cs)

  Set MetaId
constrainedMetas <- [Set MetaId] -> Set MetaId
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
Set.unions ([Set MetaId] -> Set MetaId)
-> TCMT IO [Set MetaId] -> TCMT IO (Set MetaId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ProblemConstraint -> TCMT IO (Set MetaId))
-> [ProblemConstraint] -> TCMT IO [Set MetaId]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Constraint -> TCMT IO (Set MetaId)
constraintMetas (Constraint -> TCMT IO (Set MetaId))
-> (ProblemConstraint -> Constraint)
-> ProblemConstraint
-> TCMT IO (Set MetaId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Closure Constraint -> Constraint
forall a. Closure a -> a
clValue (Closure Constraint -> Constraint)
-> (ProblemConstraint -> Closure Constraint)
-> ProblemConstraint
-> Constraint
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProblemConstraint -> Closure Constraint
theConstraint) [ProblemConstraint]
cs

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
30 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$
    TCMT IO Doc
"constrainedMetas     = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ ((MetaId -> TCMT IO Doc) -> [MetaId] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM ([MetaId] -> [TCMT IO Doc]) -> [MetaId] -> [TCMT IO Doc]
forall a b. (a -> b) -> a -> b
$ Set MetaId -> [MetaId]
forall a. Set a -> [a]
Set.toList Set MetaId
constrainedMetas)

  let isConstrained :: MetaId -> Bool
isConstrained MetaId
x = MetaId -> Set MetaId -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member MetaId
x Set MetaId
constrainedMetas
      -- Note: Always generalize named metas even if they are constrained. We
      -- freeze them so they won't be instantiated by the constraint, and we do
      -- want the nice error from checking the constraint after generalization.
      -- See #3276.
      isGeneralizable :: (MetaId, MetaVariable) -> Bool
isGeneralizable (MetaId
x, MetaVariable
mv) = MetaId -> Map MetaId name -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member MetaId
x Map MetaId name
nameMap Bool -> Bool -> Bool
||
                                Bool -> Bool
not (MetaId -> Bool
isConstrained MetaId
x) Bool -> Bool -> Bool
&& DoGeneralize
NoGeneralize DoGeneralize -> DoGeneralize -> Bool
forall a. Eq a => a -> a -> Bool
/= Arg DoGeneralize -> DoGeneralize
forall e. Arg e -> e
unArg (MetaInfo -> Arg DoGeneralize
miGeneralizable (MetaVariable -> MetaInfo
mvInfo MetaVariable
mv))
      isSort :: (a, MetaVariable) -> Bool
isSort = MetaVariable -> Bool
isSortMeta_ (MetaVariable -> Bool)
-> ((a, MetaVariable) -> MetaVariable) -> (a, MetaVariable) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, MetaVariable) -> MetaVariable
forall a b. (a, b) -> b
snd
      isOpen :: (a, MetaVariable) -> Bool
isOpen = MetaInstantiation -> Bool
isOpenMeta (MetaInstantiation -> Bool)
-> ((a, MetaVariable) -> MetaInstantiation)
-> (a, MetaVariable)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaVariable -> MetaInstantiation
mvInstantiation (MetaVariable -> MetaInstantiation)
-> ((a, MetaVariable) -> MetaVariable)
-> (a, MetaVariable)
-> MetaInstantiation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, MetaVariable) -> MetaVariable
forall a b. (a, b) -> b
snd

  -- Split the generalizable metas in open and closed
  let ([(MetaId, MetaVariable)]
generalizable, [(MetaId, MetaVariable)]
nongeneralizable)         = ((MetaId, MetaVariable) -> Bool)
-> [(MetaId, MetaVariable)]
-> ([(MetaId, MetaVariable)], [(MetaId, MetaVariable)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (MetaId, MetaVariable) -> Bool
isGeneralizable [(MetaId, MetaVariable)]
mvs
      ([(MetaId, MetaVariable)]
generalizableOpen', [(MetaId, MetaVariable)]
generalizableClosed) = ((MetaId, MetaVariable) -> Bool)
-> [(MetaId, MetaVariable)]
-> ([(MetaId, MetaVariable)], [(MetaId, MetaVariable)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (MetaId, MetaVariable) -> Bool
forall {a}. (a, MetaVariable) -> Bool
isOpen [(MetaId, MetaVariable)]
generalizable
      ([(MetaId, MetaVariable)]
openSortMetas, [(MetaId, MetaVariable)]
generalizableOpen)        = ((MetaId, MetaVariable) -> Bool)
-> [(MetaId, MetaVariable)]
-> ([(MetaId, MetaVariable)], [(MetaId, MetaVariable)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (MetaId, MetaVariable) -> Bool
forall {a}. (a, MetaVariable) -> Bool
isSort [(MetaId, MetaVariable)]
generalizableOpen'
      nongeneralizableOpen :: [(MetaId, MetaVariable)]
nongeneralizableOpen                      = ((MetaId, MetaVariable) -> Bool)
-> [(MetaId, MetaVariable)] -> [(MetaId, MetaVariable)]
forall a. (a -> Bool) -> [a] -> [a]
filter (MetaId, MetaVariable) -> Bool
forall {a}. (a, MetaVariable) -> Bool
isOpen [(MetaId, MetaVariable)]
nongeneralizable

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
30 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ TCMT IO Doc
"generalizable        = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ (((MetaId, MetaVariable) -> TCMT IO Doc)
-> [(MetaId, MetaVariable)] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM (MetaId -> TCMT IO Doc)
-> ((MetaId, MetaVariable) -> MetaId)
-> (MetaId, MetaVariable)
-> TCMT IO Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaId, MetaVariable) -> MetaId
forall a b. (a, b) -> a
fst) [(MetaId, MetaVariable)]
generalizable)
    , TCMT IO Doc
"generalizableOpen    = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ (((MetaId, MetaVariable) -> TCMT IO Doc)
-> [(MetaId, MetaVariable)] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM (MetaId -> TCMT IO Doc)
-> ((MetaId, MetaVariable) -> MetaId)
-> (MetaId, MetaVariable)
-> TCMT IO Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaId, MetaVariable) -> MetaId
forall a b. (a, b) -> a
fst) [(MetaId, MetaVariable)]
generalizableOpen)
    , TCMT IO Doc
"openSortMetas        = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ (((MetaId, MetaVariable) -> TCMT IO Doc)
-> [(MetaId, MetaVariable)] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM (MetaId -> TCMT IO Doc)
-> ((MetaId, MetaVariable) -> MetaId)
-> (MetaId, MetaVariable)
-> TCMT IO Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaId, MetaVariable) -> MetaId
forall a b. (a, b) -> a
fst) [(MetaId, MetaVariable)]
openSortMetas)
    ]

  -- Issue 3301: We can't generalize over sorts
  [(MetaId, MetaVariable)]
-> ([(MetaId, MetaVariable)] -> TCMT IO ()) -> TCMT IO ()
forall (m :: * -> *) a.
(Monad m, Null a) =>
a -> (a -> m ()) -> m ()
unlessNull [(MetaId, MetaVariable)]
openSortMetas (([(MetaId, MetaVariable)] -> TCMT IO ()) -> TCMT IO ())
-> ([(MetaId, MetaVariable)] -> TCMT IO ()) -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ \ [(MetaId, MetaVariable)]
ms ->
    Warning -> TCMT IO ()
forall (m :: * -> *).
(HasCallStack, MonadWarning m) =>
Warning -> m ()
warning (Warning -> TCMT IO ()) -> Warning -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [MetaId] -> Warning
CantGeneralizeOverSorts ([MetaId] -> Warning) -> [MetaId] -> Warning
forall a b. (a -> b) -> a -> b
$ ((MetaId, MetaVariable) -> MetaId)
-> [(MetaId, MetaVariable)] -> [MetaId]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId, MetaVariable) -> MetaId
forall a b. (a, b) -> a
fst [(MetaId, MetaVariable)]
ms

  -- Any meta in the solution of a generalizable meta should be generalized over (if possible).
  CheckpointId
cp <- Lens' TCEnv CheckpointId -> TCMT IO CheckpointId
forall (m :: * -> *) a. MonadTCEnv m => Lens' TCEnv a -> m a
viewTC (CheckpointId -> f CheckpointId) -> TCEnv -> f TCEnv
Lens' TCEnv CheckpointId
eCurrentCheckpoint
  let canGeneralize :: MetaId -> TCMT IO Bool
canGeneralize MetaId
x | MetaId -> Bool
isConstrained MetaId
x = Bool -> TCMT IO Bool
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
      canGeneralize MetaId
x = do
          MetaVariable
mv   <- MetaId -> TCMT IO MetaVariable
forall (m :: * -> *).
(HasCallStack, MonadDebug m, ReadTCState m) =>
MetaId -> m MetaVariable
lookupLocalMeta MetaId
x
          Maybe Substitution
msub <- MetaVariable
-> (Range -> TCMT IO (Maybe Substitution))
-> TCMT IO (Maybe Substitution)
forall (m :: * -> *) c a b.
(MonadTCEnv m, ReadTCState m, LensClosure c a) =>
c -> (a -> m b) -> m b
enterClosure MetaVariable
mv ((Range -> TCMT IO (Maybe Substitution))
 -> TCMT IO (Maybe Substitution))
-> (Range -> TCMT IO (Maybe Substitution))
-> TCMT IO (Maybe Substitution)
forall a b. (a -> b) -> a -> b
$ \ Range
_ ->
                    CheckpointId -> TCMT IO (Maybe Substitution)
forall (tcm :: * -> *).
MonadTCEnv tcm =>
CheckpointId -> tcm (Maybe Substitution)
checkpointSubstitution' CheckpointId
cp
          let sameContext :: Bool
sameContext =
                -- We can only generalize if the metavariable takes the context variables of the
                -- current context as arguments. This happens either when the context of the meta
                -- is the same as the current context and there is no pruning, or the meta context
                -- is a weakening but the extra variables have been pruned.
                -- It would be possible to generalize also in the case when some context variables
                -- (other than genTel) have been pruned, but it's hard to construct an example
                -- where this actually happens.
                case (Maybe Substitution
msub, MetaVariable -> Permutation
mvPermutation MetaVariable
mv) of
                  (Just Substitution
IdS, Perm Int
m [Int]
xs)        -> [Int]
xs [Int] -> [Int] -> Bool
forall a. Eq a => a -> a -> Bool
== [Int
0 .. Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
                  (Just (Wk Int
n Substitution
IdS), Perm Int
m [Int]
xs) -> [Int]
xs [Int] -> [Int] -> Bool
forall a. Eq a => a -> a -> Bool
== [Int
0 .. Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
                  (Maybe Substitution, Permutation)
_                            -> Bool
False
          Bool -> TCMT IO () -> TCMT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
sameContext (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
20 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ do
            Type
ty <- MetaId -> TCM Type
forall (m :: * -> *). ReadTCState m => MetaId -> m Type
getMetaType MetaId
x
            let Perm Int
m [Int]
xs = MetaVariable -> Permutation
mvPermutation MetaVariable
mv
            [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
              [ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"Don't know how to generalize over"
              , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM MetaId
x TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
":" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Type -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Type -> m Doc
prettyTCM Type
ty
              , String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"in context"
              , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc -> TCMT IO Doc
forall (tcm :: * -> *) a.
(MonadTCEnv tcm, ReadTCState tcm) =>
tcm a -> tcm a
inTopContext (TCMT IO Doc -> TCMT IO Doc)
-> (Telescope -> TCMT IO Doc) -> Telescope -> TCMT IO Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Telescope -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Telescope -> m Doc
prettyTCM (Telescope -> TCMT IO Doc) -> TCMT IO Telescope -> TCMT IO Doc
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< TCMT IO Telescope
forall (m :: * -> *). (Applicative m, MonadTCEnv m) => m Telescope
getContextTelescope
              , String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"permutation:" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text ((Int, [Int]) -> String
forall a. Show a => a -> String
show (Int
m, [Int]
xs))
              , String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"subst:" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Maybe Substitution -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Maybe Substitution
msub ]
          Bool -> TCMT IO Bool
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
sameContext

  Set MetaId
inherited :: Set MetaId <- [Set MetaId] -> Set MetaId
forall (f :: * -> *) a. (Foldable f, Ord a) => f (Set a) -> Set a
Set.unions ([Set MetaId] -> Set MetaId)
-> TCMT IO [Set MetaId] -> TCMT IO (Set MetaId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(MetaId, MetaVariable)]
-> ((MetaId, MetaVariable) -> TCMT IO (Set MetaId))
-> TCMT IO [Set MetaId]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [(MetaId, MetaVariable)]
generalizableClosed \ (MetaId
x, MetaVariable
mv) ->
    case MetaVariable -> MetaInstantiation
mvInstantiation MetaVariable
mv of
      InstV Instantiation
inst -> do
        String
parentName <- MetaId -> TCMT IO String
forall (m :: * -> *).
(HasCallStack, MonadDebug m, ReadTCState m) =>
MetaId -> m String
getMetaNameSuggestion MetaId
x
        [MetaId]
metas <- (MetaId -> TCMT IO Bool) -> [MetaId] -> TCMT IO [MetaId]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM MetaId -> TCMT IO Bool
canGeneralize ([MetaId] -> TCMT IO [MetaId])
-> (Term -> [MetaId]) -> Term -> TCMT IO [MetaId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set MetaId -> [MetaId]
forall a. Set a -> [a]
Set.toList (Set MetaId -> [MetaId])
-> (Term -> Set MetaId) -> Term -> [MetaId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                 (MetaId -> Set MetaId) -> Term -> Set MetaId
forall m. Monoid m => (MetaId -> m) -> Term -> m
forall t m. (AllMetas t, Monoid m) => (MetaId -> m) -> t -> m
allMetas MetaId -> Set MetaId
forall a. a -> Set a
Set.singleton (Term -> TCMT IO [MetaId]) -> TCMT IO Term -> TCMT IO [MetaId]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<
                 Term -> TCMT IO Term
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull (Instantiation -> Term
instBody Instantiation
inst)
        Bool -> TCMT IO () -> TCMT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([MetaId] -> Bool
forall a. Null a => a -> Bool
null [MetaId]
metas) (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$
          String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
40 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$
            [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
hcat [TCMT IO Doc
"Inherited metas from ", MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM MetaId
x, TCMT IO Doc
":"] TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<?> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ ((MetaId -> TCMT IO Doc) -> [MetaId] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM [MetaId]
metas)
        -- #4291: Override existing meta name suggestion.
        -- Don't suggest names for explicitly named generalizable metas.
        case (MetaId -> Bool) -> [MetaId] -> [MetaId]
forall a. (a -> Bool) -> [a] -> [a]
filter (MetaId -> Map MetaId name -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.notMember` Map MetaId name
nameMap) [MetaId]
metas of
          -- If we solved the parent with a new meta use the parent name for that.
          [MetaId
m] | MetaV{} <- Instantiation -> Term
instBody Instantiation
inst -> MetaId -> String -> TCMT IO ()
forall (m :: * -> *). MonadMetaSolver m => MetaId -> String -> m ()
setMetaNameSuggestion MetaId
m String
parentName
          -- Otherwise suffix with a number.
          [MetaId]
ms -> (Integer -> MetaId -> TCMT IO ())
-> [Integer] -> [MetaId] -> TCMT IO ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ (\ Integer
i MetaId
m -> MetaId -> String -> TCMT IO ()
forall (m :: * -> *). MonadMetaSolver m => MetaId -> String -> m ()
setMetaNameSuggestion MetaId
m (String
parentName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"." String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
i)) [Integer
1..] [MetaId]
ms
        Set MetaId -> TCMT IO (Set MetaId)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Set MetaId -> TCMT IO (Set MetaId))
-> Set MetaId -> TCMT IO (Set MetaId)
forall a b. (a -> b) -> a -> b
$ [MetaId] -> Set MetaId
forall a. Ord a => [a] -> Set a
Set.fromList [MetaId]
metas
      MetaInstantiation
_ -> TCMT IO (Set MetaId)
forall a. HasCallStack => a
__IMPOSSIBLE__

  let ([MetaId]
alsoGeneralize, [MetaId]
reallyDontGeneralize) = (MetaId -> Bool) -> [MetaId] -> ([MetaId], [MetaId])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (MetaId -> Set MetaId -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set MetaId
inherited) ([MetaId] -> ([MetaId], [MetaId]))
-> [MetaId] -> ([MetaId], [MetaId])
forall a b. (a -> b) -> a -> b
$ ((MetaId, MetaVariable) -> MetaId)
-> [(MetaId, MetaVariable)] -> [MetaId]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId, MetaVariable) -> MetaId
forall a b. (a, b) -> a
fst [(MetaId, MetaVariable)]
nongeneralizableOpen
      generalizeOver :: [MetaId]
generalizeOver   = ((MetaId, MetaVariable) -> MetaId)
-> [(MetaId, MetaVariable)] -> [MetaId]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId, MetaVariable) -> MetaId
forall a b. (a, b) -> a
fst [(MetaId, MetaVariable)]
generalizableOpen [MetaId] -> [MetaId] -> [MetaId]
forall a. [a] -> [a] -> [a]
++ [MetaId]
alsoGeneralize
      shouldGeneralize :: MetaId -> Bool
shouldGeneralize = ([MetaId]
generalizeOver [MetaId] -> MetaId -> Bool
forall a. Ord a => [a] -> a -> Bool
`hasElem`)

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
30 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ TCMT IO Doc
"alsoGeneralize       = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ ((MetaId -> TCMT IO Doc) -> [MetaId] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM [MetaId]
alsoGeneralize)
    , TCMT IO Doc
"reallyDontGeneralize = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ ((MetaId -> TCMT IO Doc) -> [MetaId] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM [MetaId]
reallyDontGeneralize)
    ]

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
10 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"we're generalizing over" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ ((MetaId -> TCMT IO Doc) -> [MetaId] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM [MetaId]
generalizeOver)

  -- Sort metas in dependency order. Include open metas that we are not
  -- generalizing over, since they will need to be pruned appropriately (see
  -- Issue 3672).
  [MetaId]
allSortedMetas <- TCMT IO [MetaId] -> TCMT IO (Maybe [MetaId]) -> TCMT IO [MetaId]
forall (m :: * -> *) a. Monad m => m a -> m (Maybe a) -> m a
fromMaybeM (TypeError -> TCMT IO [MetaId]
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
TypeError -> m a
typeError TypeError
GeneralizeCyclicDependency) (TCMT IO (Maybe [MetaId]) -> TCMT IO [MetaId])
-> TCMT IO (Maybe [MetaId]) -> TCMT IO [MetaId]
forall a b. (a -> b) -> a -> b
$
    [MetaId] -> TCMT IO (Maybe [MetaId])
dependencySortMetas ([MetaId]
generalizeOver [MetaId] -> [MetaId] -> [MetaId]
forall a. [a] -> [a] -> [a]
++ [MetaId]
reallyDontGeneralize [MetaId] -> [MetaId] -> [MetaId]
forall a. [a] -> [a] -> [a]
++ ((MetaId, MetaVariable) -> MetaId)
-> [(MetaId, MetaVariable)] -> [MetaId]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId, MetaVariable) -> MetaId
forall a b. (a, b) -> a
fst [(MetaId, MetaVariable)]
openSortMetas)
  let sortedMetas :: [MetaId]
sortedMetas = (MetaId -> Bool) -> [MetaId] -> [MetaId]
forall a. (a -> Bool) -> [a] -> [a]
filter MetaId -> Bool
shouldGeneralize [MetaId]
allSortedMetas

  let dropCxt :: Impossible -> m a -> m a
dropCxt Impossible
err = Substitution -> (Context -> Context) -> m a -> m a
forall a. Substitution -> (Context -> Context) -> m a -> m a
forall (m :: * -> *) a.
MonadAddContext m =>
Substitution -> (Context -> Context) -> m a -> m a
updateContext (Impossible -> Int -> Substitution
forall a. Impossible -> Int -> Substitution' a
strengthenS Impossible
err Int
1) (Int -> Context -> Context
forall a. Int -> [a] -> [a]
drop Int
1)

  -- Create the pre-record type (we don't yet know the types of the fields)
  (QName
genRecName, ConHead
genRecCon, [QName]
genRecFields) <- Impossible
-> TCMT IO (QName, ConHead, [QName])
-> TCMT IO (QName, ConHead, [QName])
forall {m :: * -> *} {a}.
MonadAddContext m =>
Impossible -> m a -> m a
dropCxt Impossible
forall a. HasCallStack => a
__IMPOSSIBLE__ (TCMT IO (QName, ConHead, [QName])
 -> TCMT IO (QName, ConHead, [QName]))
-> TCMT IO (QName, ConHead, [QName])
-> TCMT IO (QName, ConHead, [QName])
forall a b. (a -> b) -> a -> b
$
      Type -> [MetaId] -> TCMT IO (QName, ConHead, [QName])
createGenRecordType Type
genRecMeta [MetaId]
sortedMetas

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
30 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat ([TCMT IO Doc] -> TCMT IO Doc) -> [TCMT IO Doc] -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$
    [ TCMT IO Doc
"created genRecordType"
    , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"genRecName   = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> QName -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => QName -> m Doc
prettyTCM QName
genRecName
    , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"genRecCon    = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> ConHead -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => ConHead -> m Doc
prettyTCM ConHead
genRecCon
    , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"genRecFields = " TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ ((QName -> TCMT IO Doc) -> [QName] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map QName -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => QName -> m Doc
prettyTCM [QName]
genRecFields)
    ]

  -- Solve the generalizable metas. Each generalizable meta is solved by projecting the
  -- corresponding field from the genTel record.
  Telescope
cxtTel <- TCMT IO Telescope
forall (m :: * -> *). (Applicative m, MonadTCEnv m) => m Telescope
getContextTelescope
  let solve :: MetaId -> QName -> TCMT IO ()
solve MetaId
m QName
field = do
        String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
30 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"solving generalized meta" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+>
          MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => MetaId -> m Doc
prettyTCM MetaId
m TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc
":=" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Term -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Term -> m Doc
prettyTCM (Int -> Elims -> Term
Var Int
0 [ProjOrigin -> QName -> Elim' Term
forall a. ProjOrigin -> QName -> Elim' a
Proj ProjOrigin
ProjSystem QName
field])
        -- m should not be instantiated, but if we don't check constraints
        -- properly it could be (#3666 and #3667). Fail hard instead of
        -- generating bogus types.
        TCMT IO Bool -> TCMT IO () -> TCMT IO ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM (MetaId -> TCMT IO Bool
forall a (m :: * -> *).
(IsInstantiatedMeta a, MonadFail m, ReadTCState m) =>
a -> m Bool
forall (m :: * -> *).
(MonadFail m, ReadTCState m) =>
MetaId -> m Bool
isInstantiatedMeta MetaId
m) TCMT IO ()
forall a. HasCallStack => a
__IMPOSSIBLE__
        MetaId -> [Arg String] -> Term -> TCMT IO ()
forall (m :: * -> *).
(MonadMetaSolver m, MonadMetaSolver m) =>
MetaId -> [Arg String] -> Term -> m ()
assignTerm' MetaId
m (Telescope -> [Arg String]
forall a. TelToArgs a => a -> [Arg String]
telToArgs Telescope
cxtTel) (Term -> TCMT IO ()) -> Term -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Int -> Elims -> Term
Var Int
0 [ProjOrigin -> QName -> Elim' Term
forall a. ProjOrigin -> QName -> Elim' a
Proj ProjOrigin
ProjSystem QName
field]
  (MetaId -> QName -> TCMT IO ())
-> [MetaId] -> [QName] -> TCMT IO ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ MetaId -> QName -> TCMT IO ()
solve [MetaId]
sortedMetas [QName]
genRecFields

  -- Record the named variables in the telescope
  let telNames :: [Maybe name]
telNames = (MetaId -> Maybe name) -> [MetaId] -> [Maybe name]
forall a b. (a -> b) -> [a] -> [b]
map (MetaId -> Map MetaId name -> Maybe name
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map MetaId name
nameMap) [MetaId]
sortedMetas

  -- Build the telescope of generalized metas
  [(Arg String, Type)]
teleTypes <- do
    Args
args <- TCMT IO Args
forall (m :: * -> *). (Applicative m, MonadTCEnv m) => m Args
getContextArgs
    [[(Arg String, Type)]] -> [(Arg String, Type)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[(Arg String, Type)]] -> [(Arg String, Type)])
-> TCMT IO [[(Arg String, Type)]] -> TCMT IO [(Arg String, Type)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [MetaId]
-> (MetaId -> TCMT IO [(Arg String, Type)])
-> TCMT IO [[(Arg String, Type)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [MetaId]
sortedMetas \ MetaId
m -> do
      MetaVariable
mv <- MetaId -> TCMT IO MetaVariable
forall (m :: * -> *).
(HasCallStack, MonadDebug m, ReadTCState m) =>
MetaId -> m MetaVariable
lookupLocalMeta MetaId
m
      let info :: ArgInfo
info =
            (ArgInfo -> ArgInfo
forall a. LensHiding a => a -> a
hideOrKeepInstance (ArgInfo -> ArgInfo) -> ArgInfo -> ArgInfo
forall a b. (a -> b) -> a -> b
$
            Arg DoGeneralize -> ArgInfo
forall a. LensArgInfo a => a -> ArgInfo
getArgInfo (Arg DoGeneralize -> ArgInfo) -> Arg DoGeneralize -> ArgInfo
forall a b. (a -> b) -> a -> b
$ MetaInfo -> Arg DoGeneralize
miGeneralizable (MetaInfo -> Arg DoGeneralize) -> MetaInfo -> Arg DoGeneralize
forall a b. (a -> b) -> a -> b
$ MetaVariable -> MetaInfo
mvInfo MetaVariable
mv) { argInfoOrigin = Generalization }
          HasType{ jMetaType :: forall a. Judgement a -> Type
jMetaType = Type
t } = MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv
          perm :: Permutation
perm = MetaVariable -> Permutation
mvPermutation MetaVariable
mv
      Type
t' <- Type -> Args -> TCM Type
forall a (m :: * -> *).
(PiApplyM a, MonadReduce m, HasBuiltins m) =>
Type -> a -> m Type
forall (m :: * -> *).
(MonadReduce m, HasBuiltins m) =>
Type -> Args -> m Type
piApplyM Type
t (Args -> TCM Type) -> Args -> TCM Type
forall a b. (a -> b) -> a -> b
$ Permutation -> Args -> Args
forall a. Permutation -> [a] -> [a]
permute (Int -> Permutation -> Permutation
takeP (Args -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Args
args) Permutation
perm) Args
args
      [(Arg String, Type)] -> TCMT IO [(Arg String, Type)]
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [(ArgInfo -> String -> Arg String
forall e. ArgInfo -> e -> Arg e
Arg ArgInfo
info (String -> Arg String) -> String -> Arg String
forall a b. (a -> b) -> a -> b
$ MetaInfo -> String
miNameSuggestion (MetaInfo -> String) -> MetaInfo -> String
forall a b. (a -> b) -> a -> b
$ MetaVariable -> MetaInfo
mvInfo MetaVariable
mv, Type
t')]
  let genTel :: Telescope
genTel = ConHead -> [(Arg String, Type)] -> Telescope
buildGeneralizeTel ConHead
genRecCon [(Arg String, Type)]
teleTypes

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
40 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"teleTypes =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [(Arg String, Type)] -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *).
MonadPretty m =>
[(Arg String, Type)] -> m Doc
prettyTCM [(Arg String, Type)]
teleTypes
    , String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"genTel    =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Telescope -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Telescope -> m Doc
prettyTCM Telescope
genTel
    ]

  -- Now we need to prune the unsolved metas to make sure they respect the new
  -- dependencies (#3672). Also update interaction points to point to pruned metas.
  let inscope :: (InteractionId, InteractionPoint) -> Maybe (MetaId, InteractionId)
inscope (InteractionId
ii, InteractionPoint{ipMeta :: InteractionPoint -> Maybe MetaId
ipMeta = Just MetaId
x})
        | MetaId -> Map MetaId MetaVariable -> Bool
forall k a. Ord k => k -> Map k a -> Bool
MapS.member MetaId
x (LocalMetaStores -> Map MetaId MetaVariable
openMetas LocalMetaStores
allmetas) Bool -> Bool -> Bool
||
          MetaId -> Map MetaId MetaVariable -> Bool
forall k a. Ord k => k -> Map k a -> Bool
MapS.member MetaId
x (LocalMetaStores -> Map MetaId MetaVariable
solvedMetas LocalMetaStores
allmetas) =
          (MetaId, InteractionId) -> Maybe (MetaId, InteractionId)
forall a. a -> Maybe a
Just (MetaId
x, InteractionId
ii)
      inscope (InteractionId, InteractionPoint)
_ = Maybe (MetaId, InteractionId)
forall a. Maybe a
Nothing
  Map MetaId InteractionId
ips <- [(MetaId, InteractionId)] -> Map MetaId InteractionId
forall k a. [(k, a)] -> Map k a
Map.fromDistinctAscList ([(MetaId, InteractionId)] -> Map MetaId InteractionId)
-> (BiMap InteractionId InteractionPoint
    -> [(MetaId, InteractionId)])
-> BiMap InteractionId InteractionPoint
-> Map MetaId InteractionId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((InteractionId, InteractionPoint)
 -> Maybe (MetaId, InteractionId))
-> [(InteractionId, InteractionPoint)] -> [(MetaId, InteractionId)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (InteractionId, InteractionPoint) -> Maybe (MetaId, InteractionId)
inscope ([(InteractionId, InteractionPoint)] -> [(MetaId, InteractionId)])
-> (BiMap InteractionId InteractionPoint
    -> [(InteractionId, InteractionPoint)])
-> BiMap InteractionId InteractionPoint
-> [(MetaId, InteractionId)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([(InteractionId, InteractionPoint)], [(MetaId, InteractionId)])
-> [(InteractionId, InteractionPoint)]
forall a b. (a, b) -> a
fst (([(InteractionId, InteractionPoint)], [(MetaId, InteractionId)])
 -> [(InteractionId, InteractionPoint)])
-> (BiMap InteractionId InteractionPoint
    -> ([(InteractionId, InteractionPoint)],
        [(MetaId, InteractionId)]))
-> BiMap InteractionId InteractionPoint
-> [(InteractionId, InteractionPoint)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BiMap InteractionId InteractionPoint
-> ([(InteractionId, InteractionPoint)],
    [(Tag InteractionPoint, InteractionId)])
BiMap InteractionId InteractionPoint
-> ([(InteractionId, InteractionPoint)], [(MetaId, InteractionId)])
forall k v. BiMap k v -> ([(k, v)], [(Tag v, k)])
BiMap.toDistinctAscendingLists (BiMap InteractionId InteractionPoint -> Map MetaId InteractionId)
-> TCMT IO (BiMap InteractionId InteractionPoint)
-> TCMT IO (Map MetaId InteractionId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Lens' TCState (BiMap InteractionId InteractionPoint)
-> TCMT IO (BiMap InteractionId InteractionPoint)
forall (m :: * -> *) a. ReadTCState m => Lens' TCState a -> m a
useTC (BiMap InteractionId InteractionPoint
 -> f (BiMap InteractionId InteractionPoint))
-> TCState -> f TCState
Lens' TCState (BiMap InteractionId InteractionPoint)
stInteractionPoints
  QName
-> ConHead
-> Telescope
-> [QName]
-> Map MetaId InteractionId
-> (MetaId -> Bool)
-> [MetaId]
-> TCMT IO ()
pruneUnsolvedMetas QName
genRecName ConHead
genRecCon Telescope
genTel [QName]
genRecFields Map MetaId InteractionId
ips MetaId -> Bool
shouldGeneralize [MetaId]
allSortedMetas

  -- Fill in the missing details of the telescope record.
  Impossible -> TCMT IO () -> TCMT IO ()
forall {m :: * -> *} {a}.
MonadAddContext m =>
Impossible -> m a -> m a
dropCxt Impossible
forall a. HasCallStack => a
__IMPOSSIBLE__ (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ QName -> ConHead -> [QName] -> Type -> Telescope -> TCMT IO ()
fillInGenRecordDetails QName
genRecName ConHead
genRecCon [QName]
genRecFields Type
genRecMeta Telescope
genTel

  -- Now abstract over the telescope. We need to apply the substitution that subsitutes a record
  -- value packing up the generalized variables for the genTel variable.
  let sub :: Substitution
sub = ConHead -> [ArgInfo] -> Int -> Substitution
unpackSub ConHead
genRecCon (((Arg String, Type) -> ArgInfo)
-> [(Arg String, Type)] -> [ArgInfo]
forall a b. (a -> b) -> [a] -> [b]
map (Arg String -> ArgInfo
forall e. Arg e -> ArgInfo
argInfo (Arg String -> ArgInfo)
-> ((Arg String, Type) -> Arg String)
-> (Arg String, Type)
-> ArgInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg String, Type) -> Arg String
forall a b. (a, b) -> a
fst) [(Arg String, Type)]
teleTypes) ([(Arg String, Type)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Arg String, Type)]
teleTypes)

  -- Instantiate all fresh meta-variables to get rid of
  -- __DUMMY_TERM__.
  Telescope
genTel <- ((MetaId -> ReduceM Bool) -> Telescope -> TCMT IO Telescope)
-> Telescope -> (MetaId -> ReduceM Bool) -> TCMT IO Telescope
forall a b c. (a -> b -> c) -> b -> a -> c
flip (MetaId -> ReduceM Bool) -> Telescope -> TCMT IO Telescope
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
(MetaId -> ReduceM Bool) -> a -> m a
instantiateWhen Telescope
genTel ((MetaId -> ReduceM Bool) -> TCMT IO Telescope)
-> (MetaId -> ReduceM Bool) -> TCMT IO Telescope
forall a b. (a -> b) -> a -> b
$ \MetaId
m -> do
    Maybe (Either RemoteMetaVariable MetaVariable)
mv <- MetaId -> ReduceM (Maybe (Either RemoteMetaVariable MetaVariable))
forall (m :: * -> *).
ReadTCState m =>
MetaId -> m (Maybe (Either RemoteMetaVariable MetaVariable))
lookupMeta MetaId
m
    case Maybe (Either RemoteMetaVariable MetaVariable)
mv of
      Maybe (Either RemoteMetaVariable MetaVariable)
Nothing         -> ReduceM Bool
forall a. HasCallStack => a
__IMPOSSIBLE__
      Just Left{}     -> Bool -> ReduceM Bool
forall a. a -> ReduceM a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
      Just (Right MetaVariable
mv) -> MetaVariable -> ReduceM Bool
forall (m :: * -> *). MonadReduce m => MetaVariable -> m Bool
isFreshMeta MetaVariable
mv

  (Telescope, [Maybe name], Substitution)
-> TCM (Telescope, [Maybe name], Substitution)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Telescope
genTel, [Maybe name]
telNames, Substitution
sub)

-- | Prune unsolved metas (#3672). The input includes also the generalized metas and is sorted in
-- dependency order. The telescope is the generalized telescope.
pruneUnsolvedMetas :: QName -> ConHead -> Telescope -> [QName] -> Map MetaId InteractionId -> (MetaId -> Bool) -> [MetaId] -> TCM ()
pruneUnsolvedMetas :: QName
-> ConHead
-> Telescope
-> [QName]
-> Map MetaId InteractionId
-> (MetaId -> Bool)
-> [MetaId]
-> TCMT IO ()
pruneUnsolvedMetas QName
genRecName ConHead
genRecCon Telescope
genTel [QName]
genRecFields Map MetaId InteractionId
interactionPoints MetaId -> Bool
isGeneralized [MetaId]
metas
  | (MetaId -> Bool) -> [MetaId] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all MetaId -> Bool
isGeneralized [MetaId]
metas = () -> TCMT IO ()
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  | Bool
otherwise               = [Dom (String, Type)] -> Telescope -> [MetaId] -> TCMT IO ()
prune [] Telescope
genTel [MetaId]
metas
  where
    prune :: [Dom (String, Type)] -> Telescope -> [MetaId] -> TCMT IO ()
prune [Dom (String, Type)]
_ Telescope
_ [] = () -> TCMT IO ()
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    prune [Dom (String, Type)]
cxt Telescope
tel (MetaId
x : [MetaId]
xs) | Bool -> Bool
not (MetaId -> Bool
isGeneralized MetaId
x) = do
      -- If x is a blocked term we shouldn't instantiate it.
      TCMT IO Bool -> TCMT IO () -> TCMT IO ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM (Bool -> Bool
not (Bool -> Bool) -> TCMT IO Bool -> TCMT IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MetaId -> TCMT IO Bool
isBlockedTerm MetaId
x) (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ do
        MetaId
x <- if Telescope -> Bool
forall a. Null a => a -> Bool
null Telescope
tel then MetaId -> TCMT IO MetaId
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MetaId
x else MetaId -> TCMT IO MetaId
prePrune MetaId
x
        Telescope -> MetaId -> TCMT IO ()
pruneMeta ([Dom (String, Type)] -> Telescope
telFromList ([Dom (String, Type)] -> Telescope)
-> [Dom (String, Type)] -> Telescope
forall a b. (a -> b) -> a -> b
$ [Dom (String, Type)] -> [Dom (String, Type)]
forall a. [a] -> [a]
reverse [Dom (String, Type)]
cxt) MetaId
x
      [Dom (String, Type)] -> Telescope -> [MetaId] -> TCMT IO ()
prune [Dom (String, Type)]
cxt Telescope
tel [MetaId]
xs
    prune [Dom (String, Type)]
cxt (ExtendTel Dom Type
a Abs Telescope
tel) (MetaId
x : [MetaId]
xs) = [Dom (String, Type)] -> Telescope -> [MetaId] -> TCMT IO ()
prune ((Type -> (String, Type)) -> Dom Type -> Dom (String, Type)
forall a b. (a -> b) -> Dom' Term a -> Dom' Term b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String
x,) Dom Type
a Dom (String, Type) -> [Dom (String, Type)] -> [Dom (String, Type)]
forall a. a -> [a] -> [a]
: [Dom (String, Type)]
cxt) (Abs Telescope -> Telescope
forall a. Abs a -> a
unAbs Abs Telescope
tel) [MetaId]
xs
      where x :: String
x = Abs Telescope -> String
forall a. Abs a -> String
absName Abs Telescope
tel
    prune [Dom (String, Type)]
_ Telescope
_ [MetaId]
_ = TCMT IO ()
forall a. HasCallStack => a
__IMPOSSIBLE__

    sub :: Int -> Substitution
sub = ConHead -> [ArgInfo] -> Int -> Substitution
unpackSub ConHead
genRecCon ([ArgInfo] -> Int -> Substitution)
-> [ArgInfo] -> Int -> Substitution
forall a b. (a -> b) -> a -> b
$ (Dom (String, Type) -> ArgInfo)
-> [Dom (String, Type)] -> [ArgInfo]
forall a b. (a -> b) -> [a] -> [b]
map Dom (String, Type) -> ArgInfo
forall a. LensArgInfo a => a -> ArgInfo
getArgInfo ([Dom (String, Type)] -> [ArgInfo])
-> [Dom (String, Type)] -> [ArgInfo]
forall a b. (a -> b) -> a -> b
$ Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
genTel

    prepruneErrorRefinedContext :: MetaId -> TCM a
prepruneErrorRefinedContext = String -> MetaId -> TCM a
forall a. String -> MetaId -> TCM a
prepruneError (String -> MetaId -> TCM a) -> String -> MetaId -> TCM a
forall a b. (a -> b) -> a -> b
$
      String
"Failed to generalize because some of the generalized variables depend on an " String -> String -> String
forall a. [a] -> [a] -> [a]
++
      String
"unsolved meta created in a refined context (not a simple extension of the context where " String -> String -> String
forall a. [a] -> [a] -> [a]
++
      String
"generalization happens)."

    prepruneErrorCyclicDependencies :: MetaId -> TCM a
prepruneErrorCyclicDependencies = String -> MetaId -> TCM a
forall a. String -> MetaId -> TCM a
prepruneError (String -> MetaId -> TCM a) -> String -> MetaId -> TCM a
forall a b. (a -> b) -> a -> b
$
      String
"Failed to generalize due to circular dependencies between the generalized " String -> String -> String
forall a. [a] -> [a] -> [a]
++
      String
"variables and an unsolved meta."

    prepruneErrorFailedToInstantiate :: MetaId -> TCM a
prepruneErrorFailedToInstantiate = String -> MetaId -> TCM a
forall a. String -> MetaId -> TCM a
prepruneError (String -> MetaId -> TCM a) -> String -> MetaId -> TCM a
forall a b. (a -> b) -> a -> b
$
      String
"Failed to generalize because the generalized variables depend on an unsolved meta " String -> String -> String
forall a. [a] -> [a] -> [a]
++
      String
"that could not be lifted outside the generalization."

    prepruneError :: String -> MetaId -> TCM a
    prepruneError :: forall a. String -> MetaId -> TCM a
prepruneError String
msg MetaId
x = do
      Range
r <- MetaId -> TCMT IO Range
forall (m :: * -> *).
(HasCallStack, MonadDebug m, ReadTCState m) =>
MetaId -> m Range
getMetaRange MetaId
x
      Doc -> TCM a
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
Doc -> m a
genericDocError (Doc -> TCM a) -> TCMT IO Doc -> TCM a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<
        (String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords (String
msg String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" The problematic unsolved meta is") TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
$$
                 Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (Term -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Term -> m Doc
prettyTCM (MetaId -> Elims -> Term
MetaV MetaId
x []) TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc
"at" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Range -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Range
r)
        )

    -- If one of the fields depend on this meta, we have to make sure that this meta doesn't depend
    -- on any variables introduced after the genRec. See test/Fail/Issue3672b.agda for a test case.
    prePrune :: MetaId -> TCMT IO MetaId
prePrune MetaId
x = do
      CheckpointId
cp <- Lens' TCEnv CheckpointId -> TCMT IO CheckpointId
forall (m :: * -> *) a. MonadTCEnv m => Lens' TCEnv a -> m a
viewTC (CheckpointId -> f CheckpointId) -> TCEnv -> f TCEnv
Lens' TCEnv CheckpointId
eCurrentCheckpoint
      MetaVariable
mv <- MetaId -> TCMT IO MetaVariable
forall (m :: * -> *).
(HasCallStack, MonadDebug m, ReadTCState m) =>
MetaId -> m MetaVariable
lookupLocalMeta MetaId
x
      (Int
i, Maybe Type
_A) <- MetaVariable
-> (Range -> TCMT IO (Int, Maybe Type))
-> TCMT IO (Int, Maybe Type)
forall (m :: * -> *) c a b.
(MonadTCEnv m, ReadTCState m, LensClosure c a) =>
c -> (a -> m b) -> m b
enterClosure MetaVariable
mv ((Range -> TCMT IO (Int, Maybe Type)) -> TCMT IO (Int, Maybe Type))
-> (Range -> TCMT IO (Int, Maybe Type))
-> TCMT IO (Int, Maybe Type)
forall a b. (a -> b) -> a -> b
$ \ Range
_ -> do
        Substitution
δ <- CheckpointId -> TCMT IO Substitution
forall (tcm :: * -> *).
MonadTCEnv tcm =>
CheckpointId -> tcm Substitution
checkpointSubstitution CheckpointId
cp
        Maybe Type
_A <- case MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv of
                IsSort{}  -> Maybe Type -> TCMT IO (Maybe Type)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Type
forall a. Maybe a
Nothing
                HasType{} -> Type -> Maybe Type
forall a. a -> Maybe a
Just (Type -> Maybe Type) -> TCM Type -> TCMT IO (Maybe Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MetaId -> TCM Type
forall (m :: * -> *).
(HasBuiltins m, HasCallStack, MonadDebug m, MonadReduce m,
 MonadTCEnv m, ReadTCState m) =>
MetaId -> m Type
getMetaTypeInContext MetaId
x
        case Substitution
δ of
          Wk Int
n Substitution
IdS -> (Int, Maybe Type) -> TCMT IO (Int, Maybe Type)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
n, Maybe Type
_A)
          Substitution
IdS      -> (Int, Maybe Type) -> TCMT IO (Int, Maybe Type)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
0, Maybe Type
_A)
          Substitution
_        -> MetaId -> TCMT IO (Int, Maybe Type)
forall {a}. MetaId -> TCM a
prepruneErrorRefinedContext MetaId
x
      if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then MetaId -> TCMT IO MetaId
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MetaId
x else do
        String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.prune.pre" Int
40 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
          [ TCMT IO Doc
"prepruning"
          , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ MetaId -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty MetaId
x TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc
":" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Type -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty (Judgement MetaId -> Type
forall a. Judgement a -> Type
jMetaType (Judgement MetaId -> Type) -> Judgement MetaId -> Type
forall a b. (a -> b) -> a -> b
$ MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv)
          , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"|Δ| =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Int -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Show a) => a -> m Doc
pshow Int
i ]

        -- We have
        --   Γ (r : GenRec)            current context
        --   Γ (r : GenRec) Δ ⊢ x : A  with |Δ| = i
        -- and we need to get rid of the dependency on Δ.

        -- We can only do this if A does not depend on Δ, so check this first.
        case IntSet -> Maybe (Int, IntSet)
IntSet.minView (Maybe Type -> IntSet
forall t. Free t => t -> IntSet
allFreeVars Maybe Type
_A) of
          Just (Int
j, IntSet
_) | Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
i -> MetaId -> TCMT IO ()
forall {a}. MetaId -> TCM a
prepruneErrorCyclicDependencies MetaId
x
          Maybe (Int, IntSet)
_                   -> () -> TCMT IO ()
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

        -- If it doesn't we can strenghten it to the current context (this is done by
        -- newMetaFromOld).
        --   Γ (r : GenRec) ⊢ ρ : Γ (r : GenRec) Δ
        let ρ :: Substitution
ρ  = Impossible -> Int -> Substitution
forall a. Impossible -> Int -> Substitution' a
strengthenS Impossible
HasCallStack => Impossible
impossible Int
i
            ρ' :: Substitution
ρ' = Int -> Substitution
forall a. Int -> Substitution' a
raiseS Int
i

        (MetaId
y, Term
u) <- MetaVariable -> Substitution -> Maybe Type -> TCM (MetaId, Term)
newMetaFromOld MetaVariable
mv Substitution
ρ Maybe Type
_A

        let uρ' :: Term
uρ' = Substitution' (SubstArg Term) -> Term -> Term
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst Substitution
Substitution' (SubstArg Term)
ρ' Term
u

        String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.prune.pre" Int
40 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
          [ TCMT IO Doc
"u    =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Term -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Term
u
          , TCMT IO Doc
"uρ⁻¹ =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Term -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Term
uρ' ]

        -- To solve it we enter the context of x again
        MetaVariable -> (Range -> TCMT IO MetaId) -> TCMT IO MetaId
forall (m :: * -> *) c a b.
(MonadTCEnv m, ReadTCState m, LensClosure c a) =>
c -> (a -> m b) -> m b
enterClosure MetaVariable
mv ((Range -> TCMT IO MetaId) -> TCMT IO MetaId)
-> (Range -> TCMT IO MetaId) -> TCMT IO MetaId
forall a b. (a -> b) -> a -> b
$ \ Range
_ -> do
          -- v is x applied to the context variables
          Term
v <- case Maybe Type
_A of
                 Maybe Type
Nothing -> Sort -> Term
Sort (Sort -> Term) -> (Args -> Sort) -> Args -> Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaId -> Elims -> Sort
forall t. MetaId -> [Elim' t] -> Sort' t
MetaS MetaId
x (Elims -> Sort) -> (Args -> Elims) -> Args -> Sort
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg Term -> Elim' Term) -> Args -> Elims
forall a b. (a -> b) -> [a] -> [b]
map Arg Term -> Elim' Term
forall a. Arg a -> Elim' a
Apply (Args -> Term) -> TCMT IO Args -> TCMT IO Term
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MetaVariable -> TCMT IO Args
forall (m :: * -> *). MonadTCEnv m => MetaVariable -> m Args
getMetaContextArgs MetaVariable
mv
                 Just{}  -> MetaId -> Elims -> Term
MetaV MetaId
x (Elims -> Term) -> (Args -> Elims) -> Args -> Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg Term -> Elim' Term) -> Args -> Elims
forall a b. (a -> b) -> [a] -> [b]
map Arg Term -> Elim' Term
forall a. Arg a -> Elim' a
Apply (Args -> Term) -> TCMT IO Args -> TCMT IO Term
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MetaVariable -> TCMT IO Args
forall (m :: * -> *). MonadTCEnv m => MetaVariable -> m Args
getMetaContextArgs MetaVariable
mv
          TCMT IO () -> TCMT IO ()
forall (m :: * -> *) a.
(MonadConstraint m, MonadWarning m, MonadError TCErr m,
 MonadFresh ProblemId m) =>
m a -> m a
noConstraints (MetaId -> MetaVariable -> Maybe Type -> Term -> Term -> TCMT IO ()
doPrune MetaId
x MetaVariable
mv Maybe Type
_A Term
v Term
uρ') TCMT IO () -> (TCErr -> TCMT IO ()) -> TCMT IO ()
forall a. TCMT IO a -> (TCErr -> TCMT IO a) -> TCMT IO a
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` \ TCErr
_ -> MetaId -> TCMT IO ()
forall {a}. MetaId -> TCM a
prepruneErrorFailedToInstantiate MetaId
x
          MetaId -> MetaId -> TCMT IO ()
setInteractionPoint MetaId
x MetaId
y
          MetaId -> TCMT IO MetaId
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return MetaId
y

    pruneMeta :: Telescope -> MetaId -> TCMT IO ()
pruneMeta Telescope
 MetaId
x = do
      CheckpointId
cp <- Lens' TCEnv CheckpointId -> TCMT IO CheckpointId
forall (m :: * -> *) a. MonadTCEnv m => Lens' TCEnv a -> m a
viewTC (CheckpointId -> f CheckpointId) -> TCEnv -> f TCEnv
Lens' TCEnv CheckpointId
eCurrentCheckpoint
      MetaVariable
mv <- MetaId -> TCMT IO MetaVariable
forall (m :: * -> *).
(HasCallStack, MonadDebug m, ReadTCState m) =>
MetaId -> m MetaVariable
lookupLocalMeta MetaId
x
      -- The reason we are doing all this inside the closure of x is so that if x is an interaction
      -- meta we get the right context for the pruned interaction meta.
      MetaVariable -> (Range -> TCMT IO ()) -> TCMT IO ()
forall (m :: * -> *) c a b.
(MonadTCEnv m, ReadTCState m, LensClosure c a) =>
c -> (a -> m b) -> m b
enterClosure MetaVariable
mv ((Range -> TCMT IO ()) -> TCMT IO ())
-> (Range -> TCMT IO ()) -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ \ Range
_ ->
        -- If we can't find the generalized record, it's already been pruned and we don't have to do
        -- anything.
        TCMT IO (Maybe Int) -> (Int -> TCMT IO ()) -> TCMT IO ()
forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> (a -> m ()) -> m ()
whenJustM (MetaVariable -> TCMT IO (Maybe Int)
findGenRec MetaVariable
mv) ((Int -> TCMT IO ()) -> TCMT IO ())
-> (Int -> TCMT IO ()) -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ \ Int
i -> do

        String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.prune" Int
30 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
          [ TCMT IO Doc
"pruning"
          , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc -> TCMT IO Doc
forall (tcm :: * -> *) a.
(MonadTCEnv tcm, ReadTCState tcm) =>
tcm a -> tcm a
inTopContext (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ Judgement MetaId -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Judgement MetaId -> m Doc
prettyTCM (MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv)
          , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"GenRecTel is var" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Int -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Int
i ]

        Telescope
_ΓrΔ <- TCMT IO Telescope
forall (m :: * -> *). (Applicative m, MonadTCEnv m) => m Telescope
getContextTelescope
        let (Telescope
, Telescope
) = ([Dom (String, Type)] -> Telescope
telFromList [Dom (String, Type)]
gs, [Dom (String, Type)] -> Telescope
telFromList [Dom (String, Type)]
ds)
              where ([Dom (String, Type)]
gs, Dom (String, Type)
_ : [Dom (String, Type)]
ds) = Int
-> [Dom (String, Type)]
-> ([Dom (String, Type)], [Dom (String, Type)])
forall a. Int -> [a] -> ([a], [a])
splitAt (Telescope -> Int
forall a. Sized a => a -> Int
size Telescope
_ΓrΔ Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
_ΓrΔ)

        -- Get the type of x. By doing this here we let the checkpoint machinery sort out the
        Maybe Type
_A <- case MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv of
                IsSort{}  -> Maybe Type -> TCMT IO (Maybe Type)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Type
forall a. Maybe a
Nothing
                HasType{} -> Type -> Maybe Type
forall a. a -> Maybe a
Just (Type -> Maybe Type) -> TCM Type -> TCMT IO (Maybe Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MetaId -> TCM Type
forall (m :: * -> *).
(HasBuiltins m, HasCallStack, MonadDebug m, MonadReduce m,
 MonadTCEnv m, ReadTCState m) =>
MetaId -> m Type
getMetaTypeInContext MetaId
x

        -- We have
        --   Γ  (r : GenTel) Δ         current context
        --   Γ₀ (r : GenTel)           top context
        --   Γ₀ ⊢ Θ                    prefix of the generalized telescope currently in scope
        --   Γ (r : GenTel) Δ ⊢ x : A  the meta to prune

        -- Get the substitution from the point of generalization to the current context. This always
        -- succeeds since if the meta depends on GenTel it must have been created inside the
        -- generalization:
        --   Γ (r : GenTel) Δ ⊢ δ : Γ₀ (r : GenTel)
        Substitution
δ <- CheckpointId -> TCMT IO Substitution
forall (tcm :: * -> *).
MonadTCEnv tcm =>
CheckpointId -> tcm Substitution
checkpointSubstitution CheckpointId
cp

        -- v is x applied to the context variables
        Term
v <- case Maybe Type
_A of
               Maybe Type
Nothing -> Sort -> Term
Sort (Sort -> Term) -> (Args -> Sort) -> Args -> Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaId -> Elims -> Sort
forall t. MetaId -> [Elim' t] -> Sort' t
MetaS MetaId
x (Elims -> Sort) -> (Args -> Elims) -> Args -> Sort
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg Term -> Elim' Term) -> Args -> Elims
forall a b. (a -> b) -> [a] -> [b]
map Arg Term -> Elim' Term
forall a. Arg a -> Elim' a
Apply (Args -> Term) -> TCMT IO Args -> TCMT IO Term
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MetaVariable -> TCMT IO Args
forall (m :: * -> *). MonadTCEnv m => MetaVariable -> m Args
getMetaContextArgs MetaVariable
mv
               Just{}  -> MetaId -> Elims -> Term
MetaV MetaId
x (Elims -> Term) -> (Args -> Elims) -> Args -> Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg Term -> Elim' Term) -> Args -> Elims
forall a b. (a -> b) -> [a] -> [b]
map Arg Term -> Elim' Term
forall a. Arg a -> Elim' a
Apply (Args -> Term) -> TCMT IO Args -> TCMT IO Term
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MetaVariable -> TCMT IO Args
forall (m :: * -> *). MonadTCEnv m => MetaVariable -> m Args
getMetaContextArgs MetaVariable
mv

        -- Now ultimately we want to create the fresh meta in the context
        --   Γ Θγ Δσ where Γ    ⊢ γ : Γ₀
        --                 Γ Θγ ⊢ σ : Γ (r : GenTel)
        -- σ is the unpacking substitution (which is polymorphic in Γ)
        let σ :: Substitution
σ   = Int -> Substitution
sub (Telescope -> Int
forall a. Sized a => a -> Int
size Telescope
)
            --    Γ <- Γ (r : GenTel) Δ <- Γ₀ (r : GenTel) <- Γ₀
            γ :: Substitution
γ   = Impossible -> Int -> Substitution
forall a. Impossible -> Int -> Substitution' a
strengthenS Impossible
HasCallStack => Impossible
impossible (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Substitution -> Substitution -> Substitution
forall a.
EndoSubst a =>
Substitution' a -> Substitution' a -> Substitution' a
`composeS` Substitution
δ Substitution -> Substitution -> Substitution
forall a.
EndoSubst a =>
Substitution' a -> Substitution' a -> Substitution' a
`composeS` Int -> Substitution
forall a. Int -> Substitution' a
raiseS Int
1
            _Θγ :: Telescope
_Θγ = Substitution' (SubstArg Telescope) -> Telescope -> Telescope
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst Substitution
Substitution' (SubstArg Telescope)
γ Telescope

            _Δσ :: Telescope
_Δσ = Substitution' (SubstArg Telescope) -> Telescope -> Telescope
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst Substitution
Substitution' (SubstArg Telescope)
σ Telescope


        -- The substitution into the new context is simply lifting σ over Δ:
        --   Γ Θγ Δσ ⊢ lift i σ : Γ (r : GenTel) Δ
        let ρ :: Substitution
ρ  = Int -> Substitution -> Substitution
forall a. Int -> Substitution' a -> Substitution' a
liftS Int
i Substitution
σ
            -- We also need ρ⁻¹, which is a lot easier to construct.
            ρ' :: Substitution
ρ' = Int -> Substitution -> Substitution
forall a. Int -> Substitution' a -> Substitution' a
liftS Int
i (Substitution -> Substitution) -> Substitution -> Substitution
forall a b. (a -> b) -> a -> b
$ [ Int -> Elims -> Term
Var Int
0 [ProjOrigin -> QName -> Elim' Term
forall a. ProjOrigin -> QName -> Elim' a
Proj ProjOrigin
ProjSystem QName
fld] | QName
fld <- [QName] -> [QName]
forall a. [a] -> [a]
reverse ([QName] -> [QName]) -> [QName] -> [QName]
forall a b. (a -> b) -> a -> b
$ Int -> [QName] -> [QName]
forall a. Int -> [a] -> [a]
take (Telescope -> Int
forall a. Sized a => a -> Int
size Telescope
) ([QName] -> [QName]) -> [QName] -> [QName]
forall a b. (a -> b) -> a -> b
$ [QName]
genRecFields ] [Term] -> Substitution -> Substitution
forall a. DeBruijn a => [a] -> Substitution' a -> Substitution' a
++# Int -> Substitution
forall a. Int -> Substitution' a
raiseS Int
1

        String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.prune" Int
30 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
          [ TCMT IO Doc
"Γ   =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Telescope -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Telescope

          , TCMT IO Doc
"Θ   =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Telescope -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Telescope

          , TCMT IO Doc
"Δ   =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Telescope -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Telescope

          , TCMT IO Doc
"σ   =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Substitution -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Substitution
σ
          , TCMT IO Doc
"γ   =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Substitution -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Substitution
γ
          , TCMT IO Doc
"δ   =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Substitution -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Substitution
δ
          , TCMT IO Doc
"ρ   =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Substitution -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Substitution
ρ
          , TCMT IO Doc
"ρ⁻¹ =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Substitution -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Substitution
ρ'
          , TCMT IO Doc
"Θγ  =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Telescope -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Telescope
_Θγ
          , TCMT IO Doc
"Δσ  =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Telescope -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Telescope
_Δσ
          , TCMT IO Doc
"_A  =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Maybe Type -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Maybe Type
_A
          ]

        -- When updating the context we also need to pick names for the variables. Get them from the
        -- current context and generate fresh ones for the generalized variables in Θ.
        (Context
newCxt, Context
) <- do
          (Context
, Dom' Term (Name, Type)
_ : Context
) <- Int -> Context -> (Context, Context)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
i (Context -> (Context, Context))
-> TCMT IO Context -> TCMT IO (Context, Context)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCMT IO Context
forall (m :: * -> *). MonadTCEnv m => m Context
getContext
          let setName :: Dom' Term (String, t) -> TCMT IO (Dom' Term (Name, t))
setName = ((String, t) -> TCMT IO (Name, t))
-> Dom' Term (String, t) -> TCMT IO (Dom' Term (Name, t))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Dom' Term a -> f (Dom' Term b)
traverse (((String, t) -> TCMT IO (Name, t))
 -> Dom' Term (String, t) -> TCMT IO (Dom' Term (Name, t)))
-> ((String, t) -> TCMT IO (Name, t))
-> Dom' Term (String, t)
-> TCMT IO (Dom' Term (Name, t))
forall a b. (a -> b) -> a -> b
$ \ (String
s, t
ty) -> (,t
ty) (Name -> (Name, t)) -> TCMT IO Name -> TCMT IO (Name, t)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> TCMT IO Name
forall a (m :: * -> *).
(FreshName a, MonadFresh NameId m) =>
a -> m Name
forall (m :: * -> *). MonadFresh NameId m => String -> m Name
freshName_ String
s
          Context
 <- (Dom (String, Type) -> TCMT IO (Dom' Term (Name, Type)))
-> [Dom (String, Type)] -> TCMT IO Context
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Dom (String, Type) -> TCMT IO (Dom' Term (Name, Type))
forall {t}. Dom' Term (String, t) -> TCMT IO (Dom' Term (Name, t))
setName ([Dom (String, Type)] -> TCMT IO Context)
-> [Dom (String, Type)] -> TCMT IO Context
forall a b. (a -> b) -> a -> b
$ [Dom (String, Type)] -> [Dom (String, Type)]
forall a. [a] -> [a]
reverse ([Dom (String, Type)] -> [Dom (String, Type)])
-> [Dom (String, Type)] -> [Dom (String, Type)]
forall a b. (a -> b) -> a -> b
$ Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
_Θγ
          let rΔσ :: Context
rΔσ = (Name -> Dom (String, Type) -> Dom' Term (Name, Type))
-> [Name] -> [Dom (String, Type)] -> Context
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\ Name
name Dom (String, Type)
dom -> (String -> Name) -> (String, Type) -> (Name, Type)
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (Name -> String -> Name
forall a b. a -> b -> a
const Name
name) ((String, Type) -> (Name, Type))
-> Dom (String, Type) -> Dom' Term (Name, Type)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Dom (String, Type)
dom)
                            ((Dom' Term (Name, Type) -> Name) -> Context -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map ((Name, Type) -> Name
forall a b. (a, b) -> a
fst ((Name, Type) -> Name)
-> (Dom' Term (Name, Type) -> (Name, Type))
-> Dom' Term (Name, Type)
-> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dom' Term (Name, Type) -> (Name, Type)
forall t e. Dom' t e -> e
unDom) Context
)
                            ([Dom (String, Type)] -> [Dom (String, Type)]
forall a. [a] -> [a]
reverse ([Dom (String, Type)] -> [Dom (String, Type)])
-> [Dom (String, Type)] -> [Dom (String, Type)]
forall a b. (a -> b) -> a -> b
$ Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
_Δσ)
          (Context, Context) -> TCMT IO (Context, Context)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Context
rΔσ Context -> Context -> Context
forall a. [a] -> [a] -> [a]
++ Context
 Context -> Context -> Context
forall a. [a] -> [a] -> [a]
++ Context
, Context
)

        -- Now we can enter the new context and create our meta variable.
        (MetaId
y, Term
u) <- Substitution
-> (Context -> Context) -> TCM (MetaId, Term) -> TCM (MetaId, Term)
forall a.
Substitution -> (Context -> Context) -> TCMT IO a -> TCMT IO a
forall (m :: * -> *) a.
MonadAddContext m =>
Substitution -> (Context -> Context) -> m a -> m a
updateContext Substitution
ρ (Context -> Context -> Context
forall a b. a -> b -> a
const Context
newCxt) (TCM (MetaId, Term) -> TCM (MetaId, Term))
-> TCM (MetaId, Term) -> TCM (MetaId, Term)
forall a b. (a -> b) -> a -> b
$ TCM (MetaId, Term) -> TCM (MetaId, Term)
forall a. TCM a -> TCM a
localScope (TCM (MetaId, Term) -> TCM (MetaId, Term))
-> TCM (MetaId, Term) -> TCM (MetaId, Term)
forall a b. (a -> b) -> a -> b
$ do

          -- First, we add the named variables to the scope, to allow
          -- them to be used in holes (#3341). These should go outside Δ (#3735).
          Int -> TCMT IO () -> TCMT IO ()
forall a. Int -> ScopeM a -> ScopeM a
outsideLocalVars Int
i (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Context -> TCMT IO ()
forall {t :: * -> *} {t} {b}.
Foldable t =>
t (Dom' t (Name, b)) -> TCMT IO ()
addNamedVariablesToScope Context


          -- Now we can create the new meta
          MetaVariable -> Substitution -> Maybe Type -> TCM (MetaId, Term)
newMetaFromOld MetaVariable
mv Substitution
ρ Maybe Type
_A

        -- Finally we solve x := yρ⁻¹. The reason for solving it this way instead of xρ := y is that
        -- ρ contains dummy terms for the variables that are not in scope.
        -- If x has been instantiated by some constraint unblocked by previous pruning or
        -- generalization, use equalTerm instead of assigning to x. If this fails (see
        -- test/Fail/Issue3655b.agda for a test case), we need to give an error. This can happen if
        -- there are dependencies between generalized variables that are hidden by constraints and
        -- the dependency sorting happens to pick the wrong order. For instance, if we have
        --    α : Nat   (unsolved meta)
        --    t : F α   (named variable)
        --    n : Nat   (named variable)
        -- and a constraint F α == F n, where F does some pattern matching preventing the constraint
        -- to be solved when n is still a meta. If t appears before n in the type these will be sorted
        -- as α, t, n, but we will solve α := n before we get to the pruning here. It's good that we
        -- solve first though, because that means we can give a more informative error message than
        -- the "Cannot instantiate..." we would otherwise get.
        let uρ' :: Term
uρ' = Substitution' (SubstArg Term) -> Term -> Term
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst Substitution
Substitution' (SubstArg Term)
ρ' Term
u
        String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.prune" Int
80 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
          [ TCMT IO Doc
"solving"
          , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
sep [ Term -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Term
v   TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc
"=="
                         , Term -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Term
uρ' TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc
":"
                         , Maybe Type -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty Maybe Type
_A ] ]
        TCMT IO () -> TCMT IO ()
forall (m :: * -> *) a.
(MonadConstraint m, MonadWarning m, MonadError TCErr m,
 MonadFresh ProblemId m) =>
m a -> m a
noConstraints (MetaId -> MetaVariable -> Maybe Type -> Term -> Term -> TCMT IO ()
doPrune MetaId
x MetaVariable
mv Maybe Type
_A Term
v Term
uρ') TCMT IO () -> (TCErr -> TCMT IO ()) -> TCMT IO ()
forall a. TCMT IO a -> (TCErr -> TCMT IO a) -> TCMT IO a
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` MetaId -> Term -> TCErr -> TCMT IO ()
niceError MetaId
x Term
v

        String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize.prune" Int
80 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
          [ TCMT IO Doc
"solved"
          , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"v    =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> (Term -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty (Term -> TCMT IO Doc) -> TCMT IO Term -> TCMT IO Doc
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Term -> TCMT IO Term
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull Term
v)
          , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"uρ⁻¹ =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> (Term -> TCMT IO Doc
forall (m :: * -> *) a. (Applicative m, Pretty a) => a -> m Doc
pretty (Term -> TCMT IO Doc) -> TCMT IO Term -> TCMT IO Doc
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Term -> TCMT IO Term
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull Term
uρ') ]

        MetaId -> MetaId -> TCMT IO ()
setInteractionPoint MetaId
x MetaId
y

    findGenRec :: MetaVariable -> TCM (Maybe Int)
    findGenRec :: MetaVariable -> TCMT IO (Maybe Int)
findGenRec MetaVariable
mv = do
      Context
cxt <- Context -> TCMT IO Context
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull (Context -> TCMT IO Context) -> TCMT IO Context -> TCMT IO Context
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< TCMT IO Context
forall (m :: * -> *). MonadTCEnv m => m Context
getContext
      let n :: Int
n         = Context -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Context
cxt
          notPruned :: IntSet
notPruned = [Int] -> IntSet
IntSet.fromList ([Int] -> IntSet) -> [Int] -> IntSet
forall a b. (a -> b) -> a -> b
$
                      Permutation -> [Int] -> [Int]
forall a. Permutation -> [a] -> [a]
permute (Int -> Permutation -> Permutation
takeP Int
n (Permutation -> Permutation) -> Permutation -> Permutation
forall a b. (a -> b) -> a -> b
$ MetaVariable -> Permutation
mvPermutation MetaVariable
mv) ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$
                      Int -> [Int]
forall a. Integral a => a -> [a]
downFrom Int
n
      case [ Int
i
           | (Int
i, Dom{unDom :: forall t e. Dom' t e -> e
unDom = (Name
_, El Sort
_ (Def QName
q Elims
_))}) <- [Int] -> Context -> [(Int, Dom' Term (Name, Type))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] Context
cxt
           , QName
q QName -> QName -> Bool
forall a. Eq a => a -> a -> Bool
== QName
genRecName
           , Int
i Int -> IntSet -> Bool
`IntSet.member` IntSet
notPruned
           ] of
        []    -> Maybe Int -> TCMT IO (Maybe Int)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Int
forall a. Maybe a
Nothing
        Int
_:Int
_:[Int]
_ -> TCMT IO (Maybe Int)
forall a. HasCallStack => a
__IMPOSSIBLE__
        [Int
i]   -> Maybe Int -> TCMT IO (Maybe Int)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
i)
                                                    -- Nothing if sort meta
    newMetaFromOld :: MetaVariable -> Substitution -> Maybe Type -> TCM (MetaId, Term)
    newMetaFromOld :: MetaVariable -> Substitution -> Maybe Type -> TCM (MetaId, Term)
newMetaFromOld MetaVariable
mv Substitution
ρ Maybe Type
mA = MetaVariable -> TCM (MetaId, Term) -> TCM (MetaId, Term)
forall (m :: * -> *) x a.
(MonadTrace m, HasRange x) =>
x -> m a -> m a
setCurrentRange MetaVariable
mv (TCM (MetaId, Term) -> TCM (MetaId, Term))
-> TCM (MetaId, Term) -> TCM (MetaId, Term)
forall a b. (a -> b) -> a -> b
$
      case Maybe Type
mA of
        Maybe Type
Nothing -> do
          s :: Sort
s@(MetaS MetaId
y Elims
_) <- TCMT IO Sort
forall (m :: * -> *). MonadMetaSolver m => m Sort
newSortMeta
          (MetaId, Term) -> TCM (MetaId, Term)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (MetaId
y, Sort -> Term
Sort Sort
s)
        Just Type
_A -> do
          let _Aρ :: Type
_Aρ = Substitution' (SubstArg Type) -> Type -> Type
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst Substitution
Substitution' (SubstArg Type)
ρ Type
_A
          RunMetaOccursCheck
-> String -> Comparison -> Type -> TCM (MetaId, Term)
forall (m :: * -> *).
MonadMetaSolver m =>
RunMetaOccursCheck
-> String -> Comparison -> Type -> m (MetaId, Term)
newNamedValueMeta RunMetaOccursCheck
DontRunMetaOccursCheck
                            (MetaInfo -> String
miNameSuggestion (MetaInfo -> String) -> MetaInfo -> String
forall a b. (a -> b) -> a -> b
$ MetaVariable -> MetaInfo
mvInfo MetaVariable
mv)
                            (Judgement MetaId -> Comparison
forall a. Judgement a -> Comparison
jComparison (Judgement MetaId -> Comparison) -> Judgement MetaId -> Comparison
forall a b. (a -> b) -> a -> b
$ MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv) Type
_Aρ

    -- If x is a hole, update the hole to point to y instead.
    setInteractionPoint :: MetaId -> MetaId -> TCMT IO ()
setInteractionPoint MetaId
x MetaId
y =
      Maybe InteractionId -> (InteractionId -> TCMT IO ()) -> TCMT IO ()
forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
whenJust (MetaId -> Map MetaId InteractionId -> Maybe InteractionId
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup MetaId
x Map MetaId InteractionId
interactionPoints) (InteractionId -> MetaId -> TCMT IO ()
forall (m :: * -> *).
MonadInteractionPoints m =>
InteractionId -> MetaId -> m ()
`connectInteractionPoint` MetaId
y)

    doPrune :: MetaId -> MetaVariable -> Maybe Type -> Term -> Term -> TCM ()
    doPrune :: MetaId -> MetaVariable -> Maybe Type -> Term -> Term -> TCMT IO ()
doPrune MetaId
x MetaVariable
mv Maybe Type
mt Term
v Term
u =
      case Maybe Type
mt of
        Maybe Type
_ | Bool
isOpen -> CompareDirection
-> MetaId -> Args -> Term -> CompareAs -> TCMT IO ()
assign CompareDirection
DirEq MetaId
x (Term -> Args
getArgs Term
v) Term
u (CompareAs -> TCMT IO ()) -> CompareAs -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ CompareAs -> (Type -> CompareAs) -> Maybe Type -> CompareAs
forall b a. b -> (a -> b) -> Maybe a -> b
maybe CompareAs
AsTypes Type -> CompareAs
AsTermsOf Maybe Type
mt
        Maybe Type
Nothing    -> Sort -> Sort -> TCMT IO ()
forall (m :: * -> *). MonadConversion m => Sort -> Sort -> m ()
equalSort (Term -> Sort
unwrapSort Term
v) (Term -> Sort
unwrapSort Term
u)
        Just Type
t     -> Type -> Term -> Term -> TCMT IO ()
forall (m :: * -> *).
MonadConversion m =>
Type -> Term -> Term -> m ()
equalTerm Type
t Term
v Term
u
      where
        isOpen :: Bool
isOpen = MetaInstantiation -> Bool
isOpenMeta (MetaInstantiation -> Bool) -> MetaInstantiation -> Bool
forall a b. (a -> b) -> a -> b
$ MetaVariable -> MetaInstantiation
mvInstantiation MetaVariable
mv
        getArgs :: Term -> Args
getArgs = \case
            Sort (MetaS MetaId
_ Elims
es) -> Args -> Maybe Args -> Args
forall a. a -> Maybe a -> a
fromMaybe Args
forall a. HasCallStack => a
__IMPOSSIBLE__ (Maybe Args -> Args) -> Maybe Args -> Args
forall a b. (a -> b) -> a -> b
$ Elims -> Maybe Args
forall a. [Elim' a] -> Maybe [Arg a]
allApplyElims Elims
es
            MetaV MetaId
_ Elims
es        -> Args -> Maybe Args -> Args
forall a. a -> Maybe a -> a
fromMaybe Args
forall a. HasCallStack => a
__IMPOSSIBLE__ (Maybe Args -> Args) -> Maybe Args -> Args
forall a b. (a -> b) -> a -> b
$ Elims -> Maybe Args
forall a. [Elim' a] -> Maybe [Arg a]
allApplyElims Elims
es
            Term
_                 -> Args
forall a. HasCallStack => a
__IMPOSSIBLE__
        unwrapSort :: Term -> Sort
unwrapSort (Sort Sort
s) = Sort
s
        unwrapSort Term
_        = Sort
forall a. HasCallStack => a
__IMPOSSIBLE__

    niceError :: MetaId -> Term -> TCErr -> TCMT IO ()
niceError MetaId
x Term
u TCErr
err = do
      Term
u <- Term -> TCMT IO Term
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull Term
u
      let err' :: TCErr
err' = case TCErr
err of
                   TypeError{tcErrClosErr :: TCErr -> Closure TypeError
tcErrClosErr = Closure TypeError
cl} ->
                     -- Remove the 'when' part from the error since it's most like the same as ours.
                     TCErr
err{ tcErrClosErr = cl{ clEnv = (clEnv cl) { envCall = Nothing } } }
                   TCErr
_ -> TCErr
err
          telList :: [Dom (String, Type)]
telList = Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
genTel
          names :: [String]
names   = (Dom (String, Type) -> String) -> [Dom (String, Type)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String, Type) -> String
forall a b. (a, b) -> a
fst ((String, Type) -> String)
-> (Dom (String, Type) -> (String, Type))
-> Dom (String, Type)
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dom (String, Type) -> (String, Type)
forall t e. Dom' t e -> e
unDom) [Dom (String, Type)]
telList
          late :: [String]
late    = (Dom (String, Type) -> String) -> [Dom (String, Type)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String, Type) -> String
forall a b. (a, b) -> a
fst ((String, Type) -> String)
-> (Dom (String, Type) -> (String, Type))
-> Dom (String, Type)
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dom (String, Type) -> (String, Type)
forall t e. Dom' t e -> e
unDom) ([Dom (String, Type)] -> [String])
-> [Dom (String, Type)] -> [String]
forall a b. (a -> b) -> a -> b
$ (Dom (String, Type) -> Bool)
-> [Dom (String, Type)] -> [Dom (String, Type)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Any -> Bool
getAny (Any -> Bool)
-> (Dom (String, Type) -> Any) -> Dom (String, Type) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaId -> Any) -> Dom (String, Type) -> Any
forall m. Monoid m => (MetaId -> m) -> Dom (String, Type) -> m
forall t m. (AllMetas t, Monoid m) => (MetaId -> m) -> t -> m
allMetas (Bool -> Any
Any (Bool -> Any) -> (MetaId -> Bool) -> MetaId -> Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MetaId -> MetaId -> Bool
forall a. Eq a => a -> a -> Bool
== MetaId
x))) [Dom (String, Type)]
telList
          projs :: Elim' Term -> Set String
projs (Proj ProjOrigin
_ QName
q)
            | QName
q QName -> [QName] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [QName]
genRecFields = [String] -> Set String
forall a. Ord a => [a] -> Set a
Set.fromList ([String] -> Set String) -> [String] -> Set String
forall a b. (a -> b) -> a -> b
$ [Maybe String] -> [String]
forall a. [Maybe a] -> [a]
catMaybes [QName -> Maybe String
getGeneralizedFieldName QName
q]
          projs Elim' Term
_                 = Set String
forall a. Set a
Set.empty
          early :: [String]
early = Set String -> [String]
forall a. Set a -> [a]
Set.toList (Set String -> [String]) -> Set String -> [String]
forall a b. (a -> b) -> a -> b
$ ((Term -> Set String) -> Term -> Set String)
-> Term -> (Term -> Set String) -> Set String
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Term -> Set String) -> Term -> Set String
forall m. Monoid m => (Term -> m) -> Term -> m
forall a m. (TermLike a, Monoid m) => (Term -> m) -> a -> m
foldTerm Term
u ((Term -> Set String) -> Set String)
-> (Term -> Set String) -> Set String
forall a b. (a -> b) -> a -> b
$ \ case
                  Var Int
_ Elims
es   -> (Elim' Term -> Set String) -> Elims -> Set String
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Elim' Term -> Set String
projs Elims
es
                  Def QName
_ Elims
es   -> (Elim' Term -> Set String) -> Elims -> Set String
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Elim' Term -> Set String
projs Elims
es
                  MetaV MetaId
_ Elims
es -> (Elim' Term -> Set String) -> Elims -> Set String
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Elim' Term -> Set String
projs Elims
es
                  Term
_          -> Set String
forall a. Set a
Set.empty
          commas :: [String] -> String
commas []       = String
forall a. HasCallStack => a
__IMPOSSIBLE__
          commas [String
x]      = String
x
          commas [String
x, String
y]   = String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", and " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
y
          commas (String
x : [String]
xs) = String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
commas [String]
xs
          cause :: String
cause = String
"There were unsolved constraints that obscured the " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                  String
"dependencies between the generalized variables."
          solution :: String
solution = String
"The most reliable solution is to provide enough information to make the dependencies " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                     String
"clear, but simply mentioning the variables in the right order should also work."
          order :: TCMT IO Doc
order = [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
sep [ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords String
"Dependency analysis suggested this (likely incorrect) order:",
                        Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords ([String] -> String
unwords [String]
names) ]
          guess :: String
guess = [String] -> String
unwords
            [ String
"After constraint solving it looks like", [String] -> String
commas [String]
late
            , [String]
-> (String -> String) -> (String -> String) -> String -> String
forall a c. Sized a => a -> c -> c -> c
singPlural [String]
late (String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"s") String -> String
forall a. a -> a
id String
"actually depend"
            , String
"on", [String] -> String
commas [String]
early
            ]
      Doc -> TCMT IO ()
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
Doc -> m a
genericDocError (Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
        [ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords (String -> TCMT IO Doc) -> String -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ String
"Variable generalization failed."
        , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
sep [TCMT IO Doc
"- Probable cause", Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
4 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords String
cause]
        , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
sep [TCMT IO Doc
"- Suggestion", Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
4 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords String
solution]
        , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
sep ([TCMT IO Doc] -> TCMT IO Doc) -> [TCMT IO Doc] -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc
"- Further information"
                         , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"-" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc
order ] [TCMT IO Doc] -> [TCMT IO Doc] -> [TCMT IO Doc]
forall a. [a] -> [a] -> [a]
++
                         [ Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"-" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords String
guess | Bool -> Bool
not ([String] -> Bool
forall a. Null a => a -> Bool
null [String]
late), Bool -> Bool
not ([String] -> Bool
forall a. Null a => a -> Bool
null [String]
early) ] [TCMT IO Doc] -> [TCMT IO Doc] -> [TCMT IO Doc]
forall a. [a] -> [a] -> [a]
++
                         [ Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"-" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
sep [ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
fwords String
"The dependency I error is", TCErr -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => TCErr -> m Doc
prettyTCM TCErr
err' ] ]
        ]

    addNamedVariablesToScope :: t (Dom' t (Name, b)) -> TCMT IO ()
addNamedVariablesToScope t (Dom' t (Name, b))
cxt =
      t (Dom' t (Name, b))
-> (Dom' t (Name, b) -> TCMT IO ()) -> TCMT IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ t (Dom' t (Name, b))
cxt ((Dom' t (Name, b) -> TCMT IO ()) -> TCMT IO ())
-> (Dom' t (Name, b) -> TCMT IO ()) -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ \ Dom{ unDom :: forall t e. Dom' t e -> e
unDom = (Name
x, b
_) } -> do
        -- Recognize named variables by lack of '.' (TODO: hacky!)
        String -> Int -> String -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> String -> m ()
reportSLn String
"tc.generalize.eta.scope" Int
40 (String -> TCMT IO ()) -> String -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ String
"Adding (or not) " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Name -> String
forall a. Pretty a => a -> String
prettyShow (Name -> Name
nameConcrete Name
x) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" to the scope"
        Bool -> TCMT IO () -> TCMT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Char
'.' Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` Name -> String
forall a. Pretty a => a -> String
prettyShow (Name -> Name
nameConcrete Name
x)) (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ do
          String -> Int -> String -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> String -> m ()
reportSLn String
"tc.generalize.eta.scope" Int
40 String
"  (added)"
          BindingSource -> Name -> Name -> TCMT IO ()
bindVariable BindingSource
LambdaBound (Name -> Name
nameConcrete Name
x) Name
x

-- | Create a substition from a context where the i first record fields are variables to a context
--   where you have a single variable of the record type. Packs up the field variables in a record
--   constructor and pads with __DUMMY_TERM__s for the missing fields. Important that you apply this
--   to terms that only projects the defined fields from the record variable.
--   Used with partial record values when building the telescope of generalized variables in which
--   case we have done the dependency analysis that guarantees it is safe.
unpackSub :: ConHead -> [ArgInfo] -> Int -> Substitution
unpackSub :: ConHead -> [ArgInfo] -> Int -> Substitution
unpackSub ConHead
con [ArgInfo]
infos Int
i = Substitution
recSub
  where
    ar :: Int
ar = [ArgInfo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ArgInfo]
infos
    appl :: ArgInfo -> a -> Elim' a
appl ArgInfo
info a
v = Arg a -> Elim' a
forall a. Arg a -> Elim' a
Apply (ArgInfo -> a -> Arg a
forall e. ArgInfo -> e -> Arg e
Arg ArgInfo
info a
v)
    recVal :: Term
recVal = ConHead -> ConInfo -> Elims -> Term
Con ConHead
con ConInfo
ConOSystem (Elims -> Term) -> Elims -> Term
forall a b. (a -> b) -> a -> b
$ (ArgInfo -> Term -> Elim' Term) -> [ArgInfo] -> [Term] -> Elims
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ArgInfo -> Term -> Elim' Term
forall {a}. ArgInfo -> a -> Elim' a
appl [ArgInfo]
infos ([Term] -> Elims) -> [Term] -> Elims
forall a b. (a -> b) -> a -> b
$ [Int -> Term
var Int
j | Int
j <- [Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1, Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2..Int
0]] [Term] -> [Term] -> [Term]
forall a. [a] -> [a] -> [a]
++ Int -> Term -> [Term]
forall a. Int -> a -> [a]
replicate (Int
ar Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) Term
HasCallStack => Term
__DUMMY_TERM__

    -- want: Γ Δᵢ ⊢ recSub i : Γ (r : R)
    -- have:
    -- Γ Δᵢ ⊢ recVal i :# σ : Θ (r : R),  if Γ Δᵢ ⊢ σ : Θ
    -- Γ Δᵢ ⊢ WkS i IdS : Γ
    recSub :: Substitution
recSub = Term
recVal Term -> Substitution -> Substitution
forall a. a -> Substitution' a -> Substitution' a
:# Int -> Substitution -> Substitution
forall a. Int -> Substitution' a -> Substitution' a
Wk Int
i Substitution
forall a. Substitution' a
IdS

-- | Takes the list of types
--    A₁ []
--    A₂ [r.f₁]
--    A₃ [r.f₂, r.f₃]
--    ...
--   And builds the telescope
--    (x₁ : A₁ [ r := c _       .. _ ])
--    (x₂ : A₂ [ r := c x₁ _    .. _ ])
--    (x₃ : A₃ [ r := c x₁ x₂ _ .. _ ])
--    ...
buildGeneralizeTel :: ConHead -> [(Arg MetaNameSuggestion, Type)] -> Telescope
buildGeneralizeTel :: ConHead -> [(Arg String, Type)] -> Telescope
buildGeneralizeTel ConHead
con [(Arg String, Type)]
xs = Int -> [(Arg String, Type)] -> Telescope
go Int
0 [(Arg String, Type)]
xs
  where
    infos :: [ArgInfo]
infos = ((Arg String, Type) -> ArgInfo)
-> [(Arg String, Type)] -> [ArgInfo]
forall a b. (a -> b) -> [a] -> [b]
map (Arg String -> ArgInfo
forall e. Arg e -> ArgInfo
argInfo (Arg String -> ArgInfo)
-> ((Arg String, Type) -> Arg String)
-> (Arg String, Type)
-> ArgInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Arg String, Type) -> Arg String
forall a b. (a, b) -> a
fst) [(Arg String, Type)]
xs
    recSub :: Int -> Substitution
recSub Int
i = ConHead -> [ArgInfo] -> Int -> Substitution
unpackSub ConHead
con [ArgInfo]
infos Int
i
    go :: Int -> [(Arg String, Type)] -> Telescope
go Int
_ [] = Telescope
forall a. Tele a
EmptyTel
    go Int
i ((Arg String
name, Type
ty) : [(Arg String, Type)]
xs) = Dom Type -> Abs Telescope -> Telescope
forall a. a -> Abs (Tele a) -> Tele a
ExtendTel (Type -> Dom Type
dom Type
ty') (Abs Telescope -> Telescope) -> Abs Telescope -> Telescope
forall a b. (a -> b) -> a -> b
$ String -> Telescope -> Abs Telescope
forall a. String -> a -> Abs a
Abs (Arg String -> String
forall e. Arg e -> e
unArg Arg String
name) (Telescope -> Abs Telescope) -> Telescope -> Abs Telescope
forall a b. (a -> b) -> a -> b
$ Int -> [(Arg String, Type)] -> Telescope
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [(Arg String, Type)]
xs
      where ty' :: Type
ty' = Substitution' (SubstArg Type) -> Type -> Type
forall a. Subst a => Substitution' (SubstArg a) -> a -> a
applySubst (Int -> Substitution
recSub Int
i) Type
ty
            dom :: Type -> Dom Type
dom = ArgInfo -> String -> Type -> Dom Type
forall a. ArgInfo -> String -> a -> Dom a
defaultNamedArgDom (Arg String -> ArgInfo
forall a. LensArgInfo a => a -> ArgInfo
getArgInfo Arg String
name) (Arg String -> String
forall e. Arg e -> e
unArg Arg String
name)

-- | Create metas for all used generalizable variables and their dependencies.
createGenValues :: Set QName -> TCM (Map MetaId QName, Map QName GeneralizedValue)
createGenValues :: Set QName -> TCM (Map MetaId QName, Map QName GeneralizedValue)
createGenValues Set QName
s = do
  [(QName, MetaId, GeneralizedValue)]
genvals <- Lens' TCEnv DoGeneralize
-> (DoGeneralize -> DoGeneralize)
-> TCMT IO [(QName, MetaId, GeneralizedValue)]
-> TCMT IO [(QName, MetaId, GeneralizedValue)]
forall (m :: * -> *) a b.
MonadTCEnv m =>
Lens' TCEnv a -> (a -> a) -> m b -> m b
locallyTC (DoGeneralize -> f DoGeneralize) -> TCEnv -> f TCEnv
Lens' TCEnv DoGeneralize
eGeneralizeMetas (DoGeneralize -> DoGeneralize -> DoGeneralize
forall a b. a -> b -> a
const DoGeneralize
YesGeneralizeVar) (TCMT IO [(QName, MetaId, GeneralizedValue)]
 -> TCMT IO [(QName, MetaId, GeneralizedValue)])
-> TCMT IO [(QName, MetaId, GeneralizedValue)]
-> TCMT IO [(QName, MetaId, GeneralizedValue)]
forall a b. (a -> b) -> a -> b
$
               (QName -> TCMT IO (QName, MetaId, GeneralizedValue))
-> [QName] -> TCMT IO [(QName, MetaId, GeneralizedValue)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM QName -> TCMT IO (QName, MetaId, GeneralizedValue)
createGenValue ([QName] -> TCMT IO [(QName, MetaId, GeneralizedValue)])
-> [QName] -> TCMT IO [(QName, MetaId, GeneralizedValue)]
forall a b. (a -> b) -> a -> b
$ (QName -> QName -> Ordering) -> [QName] -> [QName]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Range -> Range -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Range -> Range -> Ordering)
-> (QName -> Range) -> QName -> QName -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` QName -> Range
forall a. HasRange a => a -> Range
getRange) ([QName] -> [QName]) -> [QName] -> [QName]
forall a b. (a -> b) -> a -> b
$ Set QName -> [QName]
forall a. Set a -> [a]
Set.toList Set QName
s
  let metaMap :: Map MetaId QName
metaMap = (QName -> QName -> QName) -> [(MetaId, QName)] -> Map MetaId QName
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith QName -> QName -> QName
forall a. HasCallStack => a
__IMPOSSIBLE__ [ (MetaId
m, QName
x) | (QName
x, MetaId
m, GeneralizedValue
_) <- [(QName, MetaId, GeneralizedValue)]
genvals ]
      nameMap :: Map QName GeneralizedValue
nameMap = (GeneralizedValue -> GeneralizedValue -> GeneralizedValue)
-> [(QName, GeneralizedValue)] -> Map QName GeneralizedValue
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith GeneralizedValue -> GeneralizedValue -> GeneralizedValue
forall a. HasCallStack => a
__IMPOSSIBLE__ [ (QName
x, GeneralizedValue
v) | (QName
x, MetaId
_, GeneralizedValue
v) <- [(QName, MetaId, GeneralizedValue)]
genvals ]
  (Map MetaId QName, Map QName GeneralizedValue)
-> TCM (Map MetaId QName, Map QName GeneralizedValue)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Map MetaId QName
metaMap, Map QName GeneralizedValue
nameMap)

-- | Create a generalisable meta for a generalisable variable.
createGenValue :: QName -> TCM (QName, MetaId, GeneralizedValue)
createGenValue :: QName -> TCMT IO (QName, MetaId, GeneralizedValue)
createGenValue QName
x = QName
-> TCMT IO (QName, MetaId, GeneralizedValue)
-> TCMT IO (QName, MetaId, GeneralizedValue)
forall (m :: * -> *) x a.
(MonadTrace m, HasRange x) =>
x -> m a -> m a
setCurrentRange QName
x (TCMT IO (QName, MetaId, GeneralizedValue)
 -> TCMT IO (QName, MetaId, GeneralizedValue))
-> TCMT IO (QName, MetaId, GeneralizedValue)
-> TCMT IO (QName, MetaId, GeneralizedValue)
forall a b. (a -> b) -> a -> b
$ do
  CheckpointId
cp  <- Lens' TCEnv CheckpointId -> TCMT IO CheckpointId
forall (m :: * -> *) a. MonadTCEnv m => Lens' TCEnv a -> m a
viewTC (CheckpointId -> f CheckpointId) -> TCEnv -> f TCEnv
Lens' TCEnv CheckpointId
eCurrentCheckpoint
  Definition
def <- Definition -> TCMT IO Definition
forall (m :: * -> *).
(Functor m, HasConstInfo m, HasOptions m, ReadTCState m,
 MonadTCEnv m, MonadDebug m) =>
Definition -> m Definition
instantiateDef (Definition -> TCMT IO Definition)
-> TCMT IO Definition -> TCMT IO Definition
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< QName -> TCMT IO Definition
forall (m :: * -> *). HasConstInfo m => QName -> m Definition
getConstInfo QName
x
                   -- Only prefix of generalizable arguments (for now?)
  let nGen :: Int
nGen       = case Definition -> NumGeneralizableArgs
defArgGeneralizable Definition
def of
                     NumGeneralizableArgs
NoGeneralizableArgs     -> Int
0
                     SomeGeneralizableArgs Int
n -> Int
n
      ty :: Type
ty         = Definition -> Type
defType Definition
def
      TelV Telescope
tel Type
_ = Type -> TelV Type
telView' Type
ty
      -- Generalizable variables are never explicit, so if they're given as
      -- explicit we default to hidden.
      hideExplicit :: a -> a
hideExplicit a
arg | a -> Bool
forall a. LensHiding a => a -> Bool
visible a
arg = a -> a
forall a. LensHiding a => a -> a
hide a
arg
                       | Bool
otherwise   = a
arg
      argTel :: Telescope
argTel     = [Dom (String, Type)] -> Telescope
telFromList ([Dom (String, Type)] -> Telescope)
-> [Dom (String, Type)] -> Telescope
forall a b. (a -> b) -> a -> b
$ (Dom (String, Type) -> Dom (String, Type))
-> [Dom (String, Type)] -> [Dom (String, Type)]
forall a b. (a -> b) -> [a] -> [b]
map Dom (String, Type) -> Dom (String, Type)
forall a. LensHiding a => a -> a
hideExplicit ([Dom (String, Type)] -> [Dom (String, Type)])
-> [Dom (String, Type)] -> [Dom (String, Type)]
forall a b. (a -> b) -> a -> b
$ Int -> [Dom (String, Type)] -> [Dom (String, Type)]
forall a. Int -> [a] -> [a]
take Int
nGen ([Dom (String, Type)] -> [Dom (String, Type)])
-> [Dom (String, Type)] -> [Dom (String, Type)]
forall a b. (a -> b) -> a -> b
$ Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
tel

  Args
args <- Telescope -> TCMT IO Args
forall (m :: * -> *). MonadMetaSolver m => Telescope -> m Args
newTelMeta Telescope
argTel
  Type
metaType <- Type -> Args -> TCM Type
forall a (m :: * -> *).
(PiApplyM a, MonadReduce m, HasBuiltins m) =>
Type -> a -> m Type
forall (m :: * -> *).
(MonadReduce m, HasBuiltins m) =>
Type -> Args -> m Type
piApplyM Type
ty Args
args

  let name :: String
name     = Name -> String
forall a. Pretty a => a -> String
prettyShow (Name -> Name
nameConcrete (Name -> Name) -> Name -> Name
forall a b. (a -> b) -> a -> b
$ QName -> Name
qnameName QName
x)
  (MetaId
m, Term
term) <- RunMetaOccursCheck
-> String -> Comparison -> Type -> TCM (MetaId, Term)
forall (m :: * -> *).
MonadMetaSolver m =>
RunMetaOccursCheck
-> String -> Comparison -> Type -> m (MetaId, Term)
newNamedValueMeta RunMetaOccursCheck
DontRunMetaOccursCheck String
name Comparison
CmpLeq Type
metaType

  -- Freeze the meta to prevent named generalizable metas from being
  -- instantiated, and set the quantity of the meta to the declared
  -- quantity of the generalisable variable.
  MetaId -> (MetaVariable -> MetaVariable) -> TCMT IO ()
forall (m :: * -> *).
MonadMetaSolver m =>
MetaId -> (MetaVariable -> MetaVariable) -> m ()
updateMetaVar MetaId
m ((MetaVariable -> MetaVariable) -> TCMT IO ())
-> (MetaVariable -> MetaVariable) -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ \ MetaVariable
mv ->
    Modality -> MetaVariable -> MetaVariable
forall a. LensModality a => Modality -> a -> a
setModality (ArgInfo -> Modality
forall a. LensModality a => a -> Modality
getModality (Definition -> ArgInfo
defArgInfo Definition
def)) (MetaVariable -> MetaVariable) -> MetaVariable -> MetaVariable
forall a b. (a -> b) -> a -> b
$
    MetaVariable
mv { mvFrozen = Frozen }

  -- Set up names of arg metas
  [(Integer, Term, Dom (String, Type))]
-> ((Integer, Term, Dom (String, Type)) -> TCMT IO ())
-> TCMT IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Integer]
-> [Term]
-> [Dom (String, Type)]
-> [(Integer, Term, Dom (String, Type))]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [Integer
1..] ((Arg Term -> Term) -> Args -> [Term]
forall a b. (a -> b) -> [a] -> [b]
map Arg Term -> Term
forall e. Arg e -> e
unArg Args
args) (Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
argTel)) (((Integer, Term, Dom (String, Type)) -> TCMT IO ()) -> TCMT IO ())
-> ((Integer, Term, Dom (String, Type)) -> TCMT IO ())
-> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ \ case
    (Integer
i, MetaV MetaId
m Elims
_, Dom{unDom :: forall t e. Dom' t e -> e
unDom = (String
x, Type
_)}) -> do
      let suf :: String -> String
suf String
"_" = Integer -> String
forall a. Show a => a -> String
show Integer
i
          suf String
""  = Integer -> String
forall a. Show a => a -> String
show Integer
i
          suf String
x   = String
x
      MetaId -> String -> TCMT IO ()
forall (m :: * -> *). MonadMetaSolver m => MetaId -> String -> m ()
setMetaNameSuggestion MetaId
m (String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
suf String
x)
    (Integer, Term, Dom (String, Type))
_ -> () -> TCMT IO ()
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()  -- eta expanded

  -- Update the ArgInfos for the named meta. The argument metas are
  -- created with the correct ArgInfo.
  MetaId -> ArgInfo -> TCMT IO ()
forall (m :: * -> *).
MonadMetaSolver m =>
MetaId -> ArgInfo -> m ()
setMetaGeneralizableArgInfo MetaId
m (ArgInfo -> TCMT IO ()) -> ArgInfo -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ ArgInfo -> ArgInfo
forall a. LensHiding a => a -> a
hideExplicit (Definition -> ArgInfo
defArgInfo Definition
def)

  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
50 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ TCMT IO Doc
"created metas for generalized variable" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> QName -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => QName -> m Doc
prettyTCM QName
x
    , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"top  =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Term -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Term -> m Doc
prettyTCM Term
term
    , Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ TCMT IO Doc
"args =" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> Args -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Args -> m Doc
prettyTCM Args
args ]

  case Term
term of
    MetaV{} -> () -> TCMT IO ()
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    Term
_       -> Doc -> TCMT IO ()
forall (m :: * -> *) a.
(HasCallStack, MonadTCError m) =>
Doc -> m a
genericDocError (Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (TCMT IO Doc
"Cannot generalize over" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> QName -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => QName -> m Doc
prettyTCM QName
x TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc
"of eta-expandable type") TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<?>
                                    Type -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Type -> m Doc
prettyTCM Type
metaType
  (QName, MetaId, GeneralizedValue)
-> TCMT IO (QName, MetaId, GeneralizedValue)
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (QName
x, MetaId
m, GeneralizedValue{ genvalCheckpoint :: CheckpointId
genvalCheckpoint = CheckpointId
cp
                                , genvalTerm :: Term
genvalTerm       = Term
term
                                , genvalType :: Type
genvalType       = Type
metaType })

-- | Create a not-yet correct record type for the generalized telescope. It's not yet correct since
--   we haven't computed the telescope yet, and we need the record type to do it.
createGenRecordType :: Type -> [MetaId] -> TCM (QName, ConHead, [QName])
createGenRecordType :: Type -> [MetaId] -> TCMT IO (QName, ConHead, [QName])
createGenRecordType genRecMeta :: Type
genRecMeta@(El Sort
genRecSort Term
_) [MetaId]
sortedMetas = do
  ModuleName
current <- TCMT IO ModuleName
forall (m :: * -> *). MonadTCEnv m => m ModuleName
currentModule
  let freshQName :: String -> TCMT IO QName
freshQName String
s = ModuleName -> Name -> QName
qualify ModuleName
current (Name -> QName) -> TCMT IO Name -> TCMT IO QName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> TCMT IO Name
forall a (m :: * -> *).
(FreshName a, MonadFresh NameId m) =>
a -> m Name
forall (m :: * -> *). MonadFresh NameId m => String -> m Name
freshName_ (String
s :: String)
      mkFieldName :: MetaId -> TCMT IO QName
mkFieldName  = String -> TCMT IO QName
freshQName (String -> TCMT IO QName)
-> (String -> String) -> String -> TCMT IO QName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
generalizedFieldName String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> TCMT IO QName)
-> (MetaId -> TCMT IO String) -> MetaId -> TCMT IO QName
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< MetaId -> TCMT IO String
forall (m :: * -> *).
(HasCallStack, MonadDebug m, ReadTCState m) =>
MetaId -> m String
getMetaNameSuggestion
  [Dom QName]
genRecFields <- (MetaId -> TCMT IO (Dom QName)) -> [MetaId] -> TCMT IO [Dom QName]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (QName -> Dom QName
forall a. a -> Dom a
defaultDom (QName -> Dom QName)
-> (MetaId -> TCMT IO QName) -> MetaId -> TCMT IO (Dom QName)
forall (m :: * -> *) b c a.
Functor m =>
(b -> c) -> (a -> m b) -> a -> m c
<.> MetaId -> TCMT IO QName
mkFieldName) [MetaId]
sortedMetas
  QName
genRecName   <- String -> TCMT IO QName
freshQName String
"GeneralizeTel"
  ConHead
genRecCon    <- String -> TCMT IO QName
freshQName String
"mkGeneralizeTel" TCMT IO QName -> (QName -> ConHead) -> TCMT IO ConHead
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \ QName
con -> ConHead
                  { conName :: QName
conName      = QName
con
                  , conDataRecord :: DataOrRecord
conDataRecord= PatternOrCopattern -> DataOrRecord
forall p. p -> DataOrRecord' p
IsRecord PatternOrCopattern
CopatternMatching
                  , conInductive :: Induction
conInductive = Induction
Inductive
                  , conFields :: [Arg QName]
conFields    = (Dom QName -> Arg QName) -> [Dom QName] -> [Arg QName]
forall a b. (a -> b) -> [a] -> [b]
map Dom QName -> Arg QName
forall t a. Dom' t a -> Arg a
argFromDom [Dom QName]
genRecFields
                  }
  Int
projIx <- Int -> Int
forall a. Enum a => a -> a
succ (Int -> Int) -> (Context -> Int) -> Context -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Context -> Int
forall a. Sized a => a -> Int
size (Context -> Int) -> TCMT IO Context -> TCMT IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCMT IO Context
forall (m :: * -> *). MonadTCEnv m => m Context
getContext
  Bool
erasure <- PragmaOptions -> Bool
optErasure (PragmaOptions -> Bool) -> TCMT IO PragmaOptions -> TCMT IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCMT IO PragmaOptions
forall (m :: * -> *). HasOptions m => m PragmaOptions
pragmaOptions
  TCMT IO () -> TCMT IO ()
forall (tcm :: * -> *) a.
(MonadTCEnv tcm, ReadTCState tcm) =>
tcm a -> tcm a
inTopContext (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [(MetaId, Dom QName)]
-> ((MetaId, Dom QName) -> TCMT IO ()) -> TCMT IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([MetaId] -> [Dom QName] -> [(MetaId, Dom QName)]
forall a b. [a] -> [b] -> [(a, b)]
zip [MetaId]
sortedMetas [Dom QName]
genRecFields) (((MetaId, Dom QName) -> TCMT IO ()) -> TCMT IO ())
-> ((MetaId, Dom QName) -> TCMT IO ()) -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ \ (MetaId
meta, Dom QName
fld) -> do
    Type
fieldTy <- MetaId -> TCM Type
forall (m :: * -> *). ReadTCState m => MetaId -> m Type
getMetaType MetaId
meta
    let field :: QName
field = Dom QName -> QName
forall t e. Dom' t e -> e
unDom Dom QName
fld
    QName -> ArgInfo -> QName -> Type -> Defn -> TCMT IO ()
addConstant' QName
field (Dom QName -> ArgInfo
forall a. LensArgInfo a => a -> ArgInfo
getArgInfo Dom QName
fld) QName
field Type
fieldTy (Defn -> TCMT IO ()) -> Defn -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ FunctionData -> Defn
FunctionDefn (FunctionData -> Defn) -> FunctionData -> Defn
forall a b. (a -> b) -> a -> b
$
      (Bool -> FunctionData
emptyFunctionData_ Bool
erasure)
        { _funMutual     = Just []
        , _funTerminates = Just True
        , _funProjection = Right Projection
          { projProper   = Just genRecName
          , projOrig     = field
          , projFromType = defaultArg genRecName
          , projIndex    = projIx
          , projLams     = ProjLams [defaultArg "gtel"]
          }
        }
  QName -> ArgInfo -> QName -> Type -> Defn -> TCMT IO ()
addConstant' (ConHead -> QName
conName ConHead
genRecCon) ArgInfo
defaultArgInfo (ConHead -> QName
conName ConHead
genRecCon) Type
HasCallStack => Type
__DUMMY_TYPE__ (Defn -> TCMT IO ()) -> Defn -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ -- Filled in later
    Constructor { conPars :: Int
conPars   = Int
0
                , conArity :: Int
conArity  = [Dom QName] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Dom QName]
genRecFields
                , conSrcCon :: ConHead
conSrcCon = ConHead
genRecCon
                , conData :: QName
conData   = QName
genRecName
                , conAbstr :: IsAbstract
conAbstr  = IsAbstract
ConcreteDef
                , conComp :: CompKit
conComp   = CompKit
emptyCompKit
                , conProj :: Maybe [QName]
conProj   = Maybe [QName]
forall a. Maybe a
Nothing
                , conForced :: [IsForced]
conForced = []
                , conErased :: Maybe [Bool]
conErased = Maybe [Bool]
forall a. Maybe a
Nothing
                , conErasure :: Bool
conErasure = Bool
erasure
                , conInline :: Bool
conInline  = Bool
False
                }
  let dummyTel :: t -> Telescope
dummyTel t
0 = Telescope
forall a. Tele a
EmptyTel
      dummyTel t
n = Dom Type -> Abs Telescope -> Telescope
forall a. a -> Abs (Tele a) -> Tele a
ExtendTel (Type -> Dom Type
forall a. a -> Dom a
defaultDom Type
HasCallStack => Type
__DUMMY_TYPE__) (Abs Telescope -> Telescope) -> Abs Telescope -> Telescope
forall a b. (a -> b) -> a -> b
$ String -> Telescope -> Abs Telescope
forall a. String -> a -> Abs a
Abs String
"_" (Telescope -> Abs Telescope) -> Telescope -> Abs Telescope
forall a b. (a -> b) -> a -> b
$ t -> Telescope
dummyTel (t
n t -> t -> t
forall a. Num a => a -> a -> a
- t
1)
  QName -> ArgInfo -> QName -> Type -> Defn -> TCMT IO ()
addConstant' QName
genRecName ArgInfo
defaultArgInfo QName
genRecName (Sort -> Type
sort Sort
genRecSort) (Defn -> TCMT IO ()) -> Defn -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$
    Record { recPars :: Int
recPars         = Int
0
           , recClause :: Maybe Clause
recClause       = Maybe Clause
forall a. Maybe a
Nothing
           , recConHead :: ConHead
recConHead      = ConHead
genRecCon
           , recNamedCon :: Bool
recNamedCon     = Bool
False
           , recFields :: [Dom QName]
recFields       = [Dom QName]
genRecFields
           , recTel :: Telescope
recTel          = Int -> Telescope
forall {t}. (Eq t, Num t) => t -> Telescope
dummyTel ([Dom QName] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Dom QName]
genRecFields) -- Filled in later
           , recMutual :: Maybe [QName]
recMutual       = [QName] -> Maybe [QName]
forall a. a -> Maybe a
Just []
           , recEtaEquality' :: EtaEquality
recEtaEquality' = HasEta -> EtaEquality
Inferred HasEta
forall a. HasEta' a
YesEta
           , recPatternMatching :: PatternOrCopattern
recPatternMatching = PatternOrCopattern
CopatternMatching
           , recInduction :: Maybe Induction
recInduction    = Maybe Induction
forall a. Maybe a
Nothing
           , recTerminates :: Maybe Bool
recTerminates   = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True    -- not recursive
           , recAbstr :: IsAbstract
recAbstr        = IsAbstract
ConcreteDef
           , recComp :: CompKit
recComp         = CompKit
emptyCompKit
           }
  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
20 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"created genRec" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Semigroup (m Doc), Foldable t) =>
t (m Doc) -> m Doc
prettyList_ ((Dom QName -> TCMT IO Doc) -> [Dom QName] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map (String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text (String -> TCMT IO Doc)
-> (Dom QName -> String) -> Dom QName -> TCMT IO Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QName -> String
forall a. Pretty a => a -> String
prettyShow (QName -> String) -> (Dom QName -> QName) -> Dom QName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dom QName -> QName
forall t e. Dom' t e -> e
unDom) [Dom QName]
genRecFields) ]
  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
80 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat
    [ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"created genRec" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text ([Dom QName] -> String
forall a. Pretty a => a -> String
prettyShow [Dom QName]
genRecFields) ]
  -- Solve the genRecMeta
  Args
args <- TCMT IO Args
forall (m :: * -> *). (Applicative m, MonadTCEnv m) => m Args
getContextArgs
  let genRecTy :: Type
genRecTy = Sort -> Term -> Type
forall t a. Sort' t -> a -> Type'' t a
El Sort
genRecSort (Term -> Type) -> Term -> Type
forall a b. (a -> b) -> a -> b
$ QName -> Elims -> Term
Def QName
genRecName (Elims -> Term) -> Elims -> Term
forall a b. (a -> b) -> a -> b
$ (Arg Term -> Elim' Term) -> Args -> Elims
forall a b. (a -> b) -> [a] -> [b]
map Arg Term -> Elim' Term
forall a. Arg a -> Elim' a
Apply Args
args
  TCMT IO () -> TCMT IO ()
forall (m :: * -> *) a.
(MonadConstraint m, MonadWarning m, MonadError TCErr m,
 MonadFresh ProblemId m) =>
m a -> m a
noConstraints (TCMT IO () -> TCMT IO ()) -> TCMT IO () -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Type -> Type -> TCMT IO ()
forall (m :: * -> *). MonadConversion m => Type -> Type -> m ()
equalType Type
genRecTy Type
genRecMeta
  (QName, ConHead, [QName]) -> TCMT IO (QName, ConHead, [QName])
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (QName
genRecName, ConHead
genRecCon, (Dom QName -> QName) -> [Dom QName] -> [QName]
forall a b. (a -> b) -> [a] -> [b]
map Dom QName -> QName
forall t e. Dom' t e -> e
unDom [Dom QName]
genRecFields)

-- | Once we have the generalized telescope we can fill in the missing details of the record type.
fillInGenRecordDetails :: QName -> ConHead -> [QName] -> Type -> Telescope -> TCM ()
fillInGenRecordDetails :: QName -> ConHead -> [QName] -> Type -> Telescope -> TCMT IO ()
fillInGenRecordDetails QName
name ConHead
con [QName]
fields Type
recTy Telescope
fieldTel = do
  Telescope
cxtTel <- (Dom Type -> Dom Type) -> Telescope -> Telescope
forall a b. (a -> b) -> Tele a -> Tele b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Dom Type -> Dom Type
forall a. (LensHiding a, LensRelevance a) => a -> a
hideAndRelParams (Telescope -> Telescope) -> TCMT IO Telescope -> TCMT IO Telescope
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCMT IO Telescope
forall (m :: * -> *). (Applicative m, MonadTCEnv m) => m Telescope
getContextTelescope
  let fullTel :: Telescope
fullTel = Telescope
cxtTel Telescope -> Telescope -> Telescope
forall t. Abstract t => Telescope -> t -> t
`abstract` Telescope
fieldTel
  -- Field types
  let mkFieldTypes :: [QName] -> Telescope -> [Type]
mkFieldTypes [] Telescope
EmptyTel = []
      mkFieldTypes (QName
fld : [QName]
flds) (ExtendTel Dom Type
ty Abs Telescope
ftel) =
          Telescope -> Type -> Type
forall t. Abstract t => Telescope -> t -> t
abstract Telescope
cxtTel (Sort -> Term -> Type
forall t a. Sort' t -> a -> Type'' t a
El Sort
s (Term -> Type) -> Term -> Type
forall a b. (a -> b) -> a -> b
$ Dom Type -> Abs Type -> Term
Pi (Type -> Dom Type
forall a. a -> Dom a
defaultDom Type
recTy) (String -> Type -> Abs Type
forall a. String -> a -> Abs a
Abs String
"r" (Type -> Abs Type) -> Type -> Abs Type
forall a b. (a -> b) -> a -> b
$ Dom Type -> Type
forall t e. Dom' t e -> e
unDom Dom Type
ty)) Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
:
          [QName] -> Telescope -> [Type]
mkFieldTypes [QName]
flds (Abs Telescope -> SubstArg Telescope -> Telescope
forall a. Subst a => Abs a -> SubstArg a -> a
absApp Abs Telescope
ftel Term
SubstArg Telescope
proj)
        where
          s :: Sort
s = Dom Type -> Abs Type -> Sort
mkPiSort (Type -> Dom Type
forall a. a -> Dom a
defaultDom Type
recTy) (String -> Type -> Abs Type
forall a. String -> a -> Abs a
Abs String
"r" (Type -> Abs Type) -> Type -> Abs Type
forall a b. (a -> b) -> a -> b
$ Dom Type -> Type
forall t e. Dom' t e -> e
unDom Dom Type
ty)
          proj :: Term
proj = Int -> Elims -> Term
Var Int
0 [ProjOrigin -> QName -> Elim' Term
forall a. ProjOrigin -> QName -> Elim' a
Proj ProjOrigin
ProjSystem QName
fld]
      mkFieldTypes [QName]
_ Telescope
_ = [Type]
forall a. HasCallStack => a
__IMPOSSIBLE__
  let fieldTypes :: [Type]
fieldTypes = [QName] -> Telescope -> [Type]
mkFieldTypes [QName]
fields (Int -> Telescope -> Telescope
forall a. Subst a => Int -> a -> a
raise Int
1 Telescope
fieldTel)
  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
40 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"Field types:" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc -> TCMT IO Doc
forall (tcm :: * -> *) a.
(MonadTCEnv tcm, ReadTCState tcm) =>
tcm a -> tcm a
inTopContext (Int -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Functor m => Int -> m Doc -> m Doc
nest Int
2 (TCMT IO Doc -> TCMT IO Doc) -> TCMT IO Doc -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ [TCMT IO Doc] -> TCMT IO Doc
forall (m :: * -> *) (t :: * -> *).
(Applicative m, Foldable t) =>
t (m Doc) -> m Doc
vcat ([TCMT IO Doc] -> TCMT IO Doc) -> [TCMT IO Doc] -> TCMT IO Doc
forall a b. (a -> b) -> a -> b
$ (Type -> TCMT IO Doc) -> [Type] -> [TCMT IO Doc]
forall a b. (a -> b) -> [a] -> [b]
map Type -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Type -> m Doc
prettyTCM [Type]
fieldTypes)
  (QName -> Type -> TCMT IO ()) -> [QName] -> [Type] -> TCMT IO ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ QName -> Type -> TCMT IO ()
forall {m :: * -> *}. MonadTCState m => QName -> Type -> m ()
setType [QName]
fields [Type]
fieldTypes
  -- Constructor type
  let conType :: Type
conType = Telescope
fullTel Telescope -> Type -> Type
forall t. Abstract t => Telescope -> t -> t
`abstract` Int -> Type -> Type
forall a. Subst a => Int -> a -> a
raise (Telescope -> Int
forall a. Sized a => a -> Int
size Telescope
fieldTel) Type
recTy
  String -> Int -> TCMT IO Doc -> TCMT IO ()
forall (m :: * -> *).
MonadDebug m =>
String -> Int -> TCMT IO Doc -> m ()
reportSDoc String
"tc.generalize" Int
40 (TCMT IO Doc -> TCMT IO ()) -> TCMT IO Doc -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ String -> TCMT IO Doc
forall (m :: * -> *). Applicative m => String -> m Doc
text String
"Final genRecCon type:" TCMT IO Doc -> TCMT IO Doc -> TCMT IO Doc
forall (m :: * -> *). Applicative m => m Doc -> m Doc -> m Doc
<+> TCMT IO Doc -> TCMT IO Doc
forall (tcm :: * -> *) a.
(MonadTCEnv tcm, ReadTCState tcm) =>
tcm a -> tcm a
inTopContext (Type -> TCMT IO Doc
forall a (m :: * -> *). (PrettyTCM a, MonadPretty m) => a -> m Doc
forall (m :: * -> *). MonadPretty m => Type -> m Doc
prettyTCM Type
conType)
  QName -> Type -> TCMT IO ()
forall {m :: * -> *}. MonadTCState m => QName -> Type -> m ()
setType (ConHead -> QName
conName ConHead
con) Type
conType
  -- Record telescope: Includes both parameters and fields.
  QName -> (Definition -> Definition) -> TCMT IO ()
forall (m :: * -> *).
MonadTCState m =>
QName -> (Definition -> Definition) -> m ()
modifyGlobalDefinition QName
name ((Definition -> Definition) -> TCMT IO ())
-> (Definition -> Definition) -> TCMT IO ()
forall a b. (a -> b) -> a -> b
$ Lens' Definition Telescope -> LensSet Definition Telescope
forall o i. Lens' o i -> LensSet o i
set ((Defn -> f Defn) -> Definition -> f Definition
Lens' Definition Defn
lensTheDef ((Defn -> f Defn) -> Definition -> f Definition)
-> ((Telescope -> f Telescope) -> Defn -> f Defn)
-> (Telescope -> f Telescope)
-> Definition
-> f Definition
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (RecordData -> f RecordData) -> Defn -> f Defn
Lens' Defn RecordData
lensRecord ((RecordData -> f RecordData) -> Defn -> f Defn)
-> ((Telescope -> f Telescope) -> RecordData -> f RecordData)
-> (Telescope -> f Telescope)
-> Defn
-> f Defn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Telescope -> f Telescope) -> RecordData -> f RecordData
Lens' RecordData Telescope
lensRecTel) Telescope
fullTel
  -- #7380: Also add clauses to the field definitions
  let n :: Int
n      = [QName] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [QName]
fields
      cpi :: ConPatternInfo
cpi    = ConPatternInfo
noConPatternInfo
      fldTys :: [Arg Type]
fldTys = (Dom (String, Type) -> Arg Type)
-> [Dom (String, Type)] -> [Arg Type]
forall a b. (a -> b) -> [a] -> [b]
map (((String, Type) -> Type) -> Arg (String, Type) -> Arg Type
forall a b. (a -> b) -> Arg a -> Arg b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String, Type) -> Type
forall a b. (a, b) -> b
snd (Arg (String, Type) -> Arg Type)
-> (Dom (String, Type) -> Arg (String, Type))
-> Dom (String, Type)
-> Arg Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dom (String, Type) -> Arg (String, Type)
forall t a. Dom' t a -> Arg a
argFromDom) ([Dom (String, Type)] -> [Arg Type])
-> [Dom (String, Type)] -> [Arg Type]
forall a b. (a -> b) -> a -> b
$ Telescope -> [Dom (String, Type)]
forall t. Tele (Dom t) -> [Dom (String, t)]
telToList Telescope
fieldTel
      conPat :: Pattern' DBPatVar
conPat = ConHead
-> ConPatternInfo
-> [NamedArg (Pattern' DBPatVar)]
-> Pattern' DBPatVar
forall x.
ConHead -> ConPatternInfo -> [NamedArg (Pattern' x)] -> Pattern' x
ConP ConHead
con ConPatternInfo
cpi [ (Pattern' DBPatVar -> Named_ (Pattern' DBPatVar))
-> Arg (Pattern' DBPatVar) -> NamedArg (Pattern' DBPatVar)
forall a b. (a -> b) -> Arg a -> Arg b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Pattern' DBPatVar -> Named_ (Pattern' DBPatVar)
forall a name. a -> Named name a
unnamed (Arg (Pattern' DBPatVar) -> NamedArg (Pattern' DBPatVar))
-> Arg (Pattern' DBPatVar) -> NamedArg (Pattern' DBPatVar)
forall a b. (a -> b) -> a -> b
$ DBPatVar -> Pattern' DBPatVar
forall a. a -> Pattern' a
varP (String -> Int -> DBPatVar
DBPatVar String
"x" Int
i) Pattern' DBPatVar -> Arg Type -> Arg (Pattern' DBPatVar)
forall a b. a -> Arg b -> Arg a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Arg Type
arg | (Int
i, Arg Type
arg) <- [Int] -> [Arg Type] -> [(Int, Arg Type)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Int -> [Int]
forall a. Integral a => a -> [a]
downFrom Int
n) [Arg Type]
fldTys ]
  [(Int, QName, Arg Type)]
-> ((Int, QName, Arg Type) -> TCMT IO ()) -> TCMT IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Int] -> [QName] -> [Arg Type] -> [(Int, QName, Arg Type)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 (Int -> [Int]
forall a. Integral a => a -> [a]
downFrom Int
n) [QName]
fields [Arg Type]
fldTys) \ (Int
i, QName
fld, Arg Type
fldTy) -> do
    QName -> ([Clause] -> [Clause]) -> TCMT IO ()
modifyFunClauses QName
fld \ [Clause]
_ ->
      [Clause
        { clauseLHSRange :: Range
clauseLHSRange    = Range
forall a. Range' a
noRange
        , clauseFullRange :: Range
clauseFullRange   = Range
forall a. Range' a
noRange
        , clauseTel :: Telescope
clauseTel         = Telescope
fieldTel
        , namedClausePats :: [NamedArg (Pattern' DBPatVar)]
namedClausePats   = [Pattern' DBPatVar -> NamedArg (Pattern' DBPatVar)
forall a. a -> NamedArg a
defaultNamedArg Pattern' DBPatVar
conPat]
        , clauseBody :: Maybe Term
clauseBody        = Term -> Maybe Term
forall a. a -> Maybe a
Just (Term -> Maybe Term) -> Term -> Maybe Term
forall a b. (a -> b) -> a -> b
$ Int -> Term
var Int
i
        , clauseType :: Maybe (Arg Type)
clauseType        = Arg Type -> Maybe (Arg Type)
forall a. a -> Maybe a
Just (Arg Type -> Maybe (Arg Type)) -> Arg Type -> Maybe (Arg Type)
forall a b. (a -> b) -> a -> b
$ Int -> Arg Type -> Arg Type
forall a. Subst a => Int -> a -> a
raise (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Arg Type
fldTy
        , clauseCatchall :: Bool
clauseCatchall    = Bool
False
        , clauseExact :: Maybe Bool
clauseExact       = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True
        , clauseRecursive :: Maybe Bool
clauseRecursive   = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False
        , clauseUnreachable :: Maybe Bool
clauseUnreachable = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False
        , clauseEllipsis :: ExpandedEllipsis
clauseEllipsis    = ExpandedEllipsis
NoEllipsis
        , clauseWhereModule :: Maybe ModuleName
clauseWhereModule = Maybe ModuleName
forall a. Maybe a
Nothing
        }]
  where
    setType :: QName -> Type -> m ()
setType QName
q Type
ty = QName -> (Definition -> Definition) -> m ()
forall (m :: * -> *).
MonadTCState m =>
QName -> (Definition -> Definition) -> m ()
modifyGlobalDefinition QName
q ((Definition -> Definition) -> m ())
-> (Definition -> Definition) -> m ()
forall a b. (a -> b) -> a -> b
$ \ Definition
d -> Definition
d { defType = ty }