| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Agda.TypeChecking.Conversion.Errors
Description
Implementation of conversion checking errors which can reify part of the context leading to the actual failure as terms.
Synopsis
- failConversion :: (MonadTCError m, HasBuiltins m) => Comparison -> Term -> Term -> CompareAs -> m a
- mismatchedProjections :: (MonadError TCErr m, PureTCM m) => Type -> Term -> Elims -> Type -> Term -> Elims -> m a
- addConversionContext :: MonadTCError m => (ConversionZipper -> ConversionZipper) -> m a -> m a
- nowConversionChecking :: (MonadTCError m, HasBuiltins m) => Comparison -> Term -> Term -> CompareAs -> m a -> m a
- cutConversionErrors :: (MonadPretty m, MonadError TCErr m) => m a -> m a
- data ConversionError = ConversionError {}
- data ConversionZipper
- data ConversionErrorContext
- = Floating ConversionZipper
- | Finished HereOrThere (Maybe HeadMismatch)
- data FailedCompareAs
Public interface
Conversion checking errors are initially thrown (by failConversion)
in the floating state, which means they can accumulate information
on where they happened as the call stack unwinds. This information
will be presented to the user by wrapping the actual mismatched terms
in a skeleton of the term where the mismatch happened. These terms
had better not be nonsense! This requires that recursive calls within
the conversion checker cooperate with the reconstruction process,
using the functions in this module. Their use can be summarised as
follows:
- A recursive call to compare a subterm of a normal form should be
guarded by
addConversionContext. - A recursive call to a domain-specific conversion checking function
which takes the input terms apart using a nontrivial view (e.g.,
equalLevel) should be guarded bynowConversionChecking. - A recursive call under an application of a nontrivial substitution
to the context and terms under consideration should be guarded by
cutConversionErrors. - Recursive calls that preserve the definitional identities of the terms under consideration do not need any special handling.
The goal of these rules is to allow for the user to pretend that conversion checking works by normalising then checking for syntactic equality: the reconstructed term should wrap the actual mismatch in "hereditary neutrals (to the left)", i.e. everything that compared equal on the way to the mismatched terms is normalised, but parts of the term that are beyond the mismatch are left as-is (and, in the future, will be presented "deemphasized").
How much of the context to reify is a design parameter that can be
tuned. At the moment, we drop all ConvLam, ConvDom, ConvCod and
visible ConvApply from the front of the zipper. Regardless, the
conversion checker must be set up as if the entire context will be
reified.
Arguments
| :: (MonadTCError m, HasBuiltins m) | |
| => Comparison | Equality or subtyping? |
| -> Term | See |
| -> Term | See |
| -> CompareAs | Will be converted to a |
| -> m a |
Throw a floating ConversionError, given the arguments of
compareAs.
mismatchedProjections Source #
Arguments
| :: (MonadError TCErr m, PureTCM m) | |
| => Type | LHS type, |
| -> Term | LHS term, |
| -> Elims | Additional eliminations |
| -> Type | RHS type, |
| -> Term | RHS term, |
| -> Elims | Additional eliminations |
| -> m a |
raises a floating
conversion-checking error (as per mismatchedProjections t1 v1 e1 t2 v2 e2failConversion) indicating that
the terms v1 and v2 (which have type t1 and t2 respectively,
and are typically neutral) disagree on the last elimination in their
spines.
The further eliminations e1 and e2 are treated as "uncompared"
context for the error message.
Arguments
| :: MonadTCError m | |
| => (ConversionZipper -> ConversionZipper) | How to modify the zipper |
| -> m a | Generally, a recursive call to the conversion checker |
| -> m a |
Add some call stack context to floating ConversionErrors thrown
from the continuation.
This function should be placed on the outside of addContext,
and the changes to the context should be reflected in the
ConversionZipper.
Unreifiable recursive calls
The ConversionZipper reflects recursive calls made to conversion
checking of the immediate subterms of a normal form, and it can
handle most cases of a recursive call happening in a weakening of the
current context as well. However, some conversion-checking functions
take the input values apart in nontrivial, type-specific ways before
eventually calling into "ordinary" term conversion checking again.
If a floating ConversionError happens in one of these eventual
calls, the reified call stack will not have anything corresponding to
the value that got taken apart; this can result in the terms
presented to the user being ill-typed (see
testFailConvErrCtxLevels for an example). These calls can be
handled in two ways, depending on whether or not preserving the
surrounding context is likely to be useful in an error message. Here
are examples of using each:
Calls to
equalLevelare likely to happen while checking hidden arguments to a defined symbol (e.g. a universe-polymorphic data type), which is a context worth preserving for error messages: telling the userl != l'is significantly less useful than telling themList {l} A != List {l'} B.Therefore, the call to
equalLevelinequalTerm'is guarded bynowConversionChecking. If an error happens while conversion-checking some levels, the mismatched terms will be replaced by the (normalised forms of) the entire levels that were being compared.On the other hand, conversion checking of partial elements involves nontrivial modifications to the context, and, more importantly, generally happens to terms which display quite terribly before these substitutions are applied, often involving eta-expanded extended lambdas and the primitive
primPOr. Subjectively, it's less useful to say that conversion checking failed for the hard-to-read system than it is to say that it failed for a particular face.For these reasons,
compareTermOnFace(really,forallFaceMaps) usescutConversionErrorsto turn any floating errors from conversion-checking the faces intoFinishederrors, which no longer accumulate context. Whatever context was collected inside the face comparison will be preserved, but we will not remember that (or where) the partial elements were being compared.
nowConversionChecking Source #
Arguments
| :: (MonadTCError m, HasBuiltins m) | |
| => Comparison | Equality or subtyping? |
| -> Term | See |
| -> Term | See |
| -> CompareAs | Will be converted to a |
| -> m a | Generally, a recursive call to a type-specific conversion checking function. |
| -> m a |
Replaces any floating ConversionErrors raised by the
continuation with the one generated (as per failConversion) from
the given arguments.
cutConversionErrors :: (MonadPretty m, MonadError TCErr m) => m a -> m a Source #
Freeze ConversionErrors thrown by the continuation.
This function should be placed on the inside of context updates.
Types
data ConversionError Source #
A conversion checking failure.
A conversion checking error can be in two states (according to its
convErrCtx): it is either Finished or
Floating.
A Finished conversion-checking error packages a pair of unequal
terms, which are well-typed in the context that the error was raised
in, with sufficient information for printing an informative error
message. Finished errors will not accumulate further call stack
information.
A Floating conversion-checking
error is subject to be modified as the conversion checker's call
stack unwinds, by appending to its ConversionZipper. Some frames in
a ConversionZipper alter the context in which the terms
convErrLhs and convErrRhs should be interpreted. Floating errors
can be re-raised as Finished errors using cutConversionErrors.
This means that any code which catches those errors will have types
valid directly in the TypeError closure, but no more context will
be accumulated for them.
Constructors
| ConversionError | |
Fields
| |
Instances
data ConversionZipper Source #
A "zipper-like" representation of the edges between comparing a normal form and comparing one of its immediate subterms in the conversion checker's call graph.
Constructors
| ConvStop | Thrown at the failing call. |
| ConvLam | A call to compare the body of a function-typed value. |
Fields
| |
| ConvDom | A call to compare the domain of a pair of pi types. |
| ConvCod | A call to compare the codomain of a pair of pi types. |
Fields
| |
| ConvApply | A call to compare an argument to a function. |
Fields
| |
Instances
| PrettyTCM ConversionZipper Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods prettyTCM :: MonadPretty m => ConversionZipper -> m Doc Source # | |||||
| NFData ConversionZipper Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods rnf :: ConversionZipper -> () # | |||||
| Generic ConversionZipper Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Associated Types
Methods from :: ConversionZipper -> Rep ConversionZipper x # to :: Rep ConversionZipper x -> ConversionZipper # | |||||
| Show ConversionZipper Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods showsPrec :: Int -> ConversionZipper -> ShowS # show :: ConversionZipper -> String # showList :: [ConversionZipper] -> ShowS # | |||||
| type Rep ConversionZipper Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors type Rep ConversionZipper = D1 ('MetaData "ConversionZipper" "Agda.TypeChecking.Conversion.Errors" "Agda-2.9.0-inplace" 'False) ((C1 ('MetaCons "ConvStop" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "ConvLam" 'PrefixI 'False) ((S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Dom Type)) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Abs ()))) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ArgName) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ConversionZipper)))) :+: (C1 ('MetaCons "ConvDom" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Dom ConversionZipper)) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Abs Type)) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Abs Type)))) :+: (C1 ('MetaCons "ConvCod" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Dom Type)) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ArgName) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ConversionZipper))) :+: C1 ('MetaCons "ConvApply" 'PrefixI 'False) ((S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Term) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Abs Type))) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Arg ConversionZipper)) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 [Elim]) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 [Elim]))))))) | |||||
data ConversionErrorContext Source #
Context for a conversion checking error.
Constructors
| Floating ConversionZipper | It still makes sense to collect call stack information for this error. |
| Finished HereOrThere (Maybe HeadMismatch) | We can not, or do not want to, keep collecting call stack information for this error. Stores "crystallised" information about the actual failing comparison to use as context in error rendering. |
Instances
| NFData ConversionErrorContext Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods rnf :: ConversionErrorContext -> () # | |||||
| Generic ConversionErrorContext Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Associated Types
Methods from :: ConversionErrorContext -> Rep ConversionErrorContext x # to :: Rep ConversionErrorContext x -> ConversionErrorContext # | |||||
| Show ConversionErrorContext Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods showsPrec :: Int -> ConversionErrorContext -> ShowS # show :: ConversionErrorContext -> String # showList :: [ConversionErrorContext] -> ShowS # | |||||
| type Rep ConversionErrorContext Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors | |||||
data FailedCompareAs Source #
The failing version of CompareAs.
Constructors
| FailAsTermsOf Type Type | The conversion checker failed in a typed context. While the conversion checker is homogeneous (so |
| FailAsTypes | The conversion checker failed in a type-insensitive context. |
Instances
| PrettyTCM FailedCompareAs Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods prettyTCM :: MonadPretty m => FailedCompareAs -> m Doc Source # | |||||
| NFData FailedCompareAs Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods rnf :: FailedCompareAs -> () # | |||||
| Generic FailedCompareAs Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Associated Types
Methods from :: FailedCompareAs -> Rep FailedCompareAs x # to :: Rep FailedCompareAs x -> FailedCompareAs # | |||||
| Show FailedCompareAs Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors Methods showsPrec :: Int -> FailedCompareAs -> ShowS # show :: FailedCompareAs -> String # showList :: [FailedCompareAs] -> ShowS # | |||||
| type Rep FailedCompareAs Source # | |||||
Defined in Agda.TypeChecking.Conversion.Errors type Rep FailedCompareAs = D1 ('MetaData "FailedCompareAs" "Agda.TypeChecking.Conversion.Errors" "Agda-2.9.0-inplace" 'False) (C1 ('MetaCons "FailAsTermsOf" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Type) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Type)) :+: C1 ('MetaCons "FailAsTypes" 'PrefixI 'False) (U1 :: Type -> Type)) | |||||