futhark
Safe HaskellNone
LanguageGHC2021

Language.Futhark.TypeChecker.Unify

Description

Implementation of unification and other core type system building blocks.

Synopsis

Documentation

data Constraint Source #

A constraint on a yet-ambiguous size variable, or information about a rigid type parameter or size.

Constructors

ParamSize Loc 
Size (Maybe Exp) Usage

Is not actually a type, but a term-level size, possibly already set to something specific.

UnknownSize Loc RigidSource

A size that does not unify with anything - created from the result of applying a function whose return size is existential, or otherwise hiding a size.

InstSize Liftedness Usage

A size arising from instantiating a type parameter (of the given liftedness) with a type whose sizes are not yet known. In contrast to an ordinary Size, unification may determine that this size is actually existential (unless the type parameter is unlifted), in which case the constraint is replaced with ExistentialSize. See Note [Size Inference] in Language.Futhark.TypeChecker.Terms.

CopySize VName Int Usage

Another occurrence of the instantiated size denoted by the given canonical size variable (an InstSize). Kept distinct from the canonical variable because if the size turns out to be existential, every occurrence must be a distinct existential. The integer identifies the occurrence of the instantiated type parameter that this size is part of; copies from the same occurrence absorbed from the same source denote the same existential size.

ExistentialSize (Maybe VName) (Maybe Loc) Usage

An instantiated size that unification has determined to correspond to an existential size, possibly with the variable it was unified with (used to identify existentials with the same origin). Each variable constrained by this (or a CopySize pointing to it) is turned into a rigid size when the enclosing function application is complete. The second field, when present, means that a *rigid* unknown size was absorbed: the existential then stands for a size that is actually computed at that location, and if it cannot be bound anywhere, it becomes a rigid unknown size there (see bindExistentialInsts), subjecting it to the causality check.

Instances

Instances details
Show Constraint Source # 
Instance details

Defined in Language.Futhark.TypeChecker.Unify

Located Constraint Source # 
Instance details

Defined in Language.Futhark.TypeChecker.Unify

data Usage Source #

A usage that caused a type constraint.

Constructors

Usage (Maybe Text) Loc 

Instances

Instances details
Show Usage Source # 
Instance details

Defined in Language.Futhark.TypeChecker.Unify

Methods

showsPrec :: Int -> Usage -> ShowS #

show :: Usage -> String #

showList :: [Usage] -> ShowS #

Pretty Usage Source # 
Instance details

Defined in Language.Futhark.TypeChecker.Unify

Methods

pretty :: Usage -> Doc ann #

prettyList :: [Usage] -> Doc ann #

Located Usage Source # 
Instance details

Defined in Language.Futhark.TypeChecker.Unify

Methods

locOf :: Usage -> Loc #

locOfList :: [Usage] -> Loc #

mkUsage :: Located a => a -> Text -> Usage Source #

Construct a Usage from a location and a description.

mkUsage' :: Located a => a -> Usage Source #

Construct a Usage that has just a location, but no particular description.

type Level = Int Source #

The level at which a type variable is bound. Higher means deeper. We can only unify a type variable at level i with a type t if all type names that occur in t are at most at level i.

type Constraints = Map VName (Level, Constraint) Source #

Mapping from fresh type variables, instantiated from the type schemes of polymorphic functions, to (possibly) specific types as determined on application and the location of that application, or a partial constraint on their type.

class Monad m => MonadUnify (m :: Type -> Type) where Source #

Monads that which to perform unification must implement this type class.

data Rigidity Source #

The ridigity of a size variable. All rigid sizes are tagged with information about how they were generated.

Constructors

Rigid RigidSource 
Nonrigid 

data RigidSource Source #

The source of a rigid size.

Constructors

RigidArg (Maybe (QualName VName)) Text

A function argument that is not a constant or variable name.

RigidRet (Maybe (QualName VName))

An existential return size.

RigidLoop

Similarly to RigidRet, but produce by a loop.

RigidSlice (Maybe Size) Text

Produced by a complicated slice expression.

RigidRange

Produced by a complicated range expression.

RigidCond StructType StructType

Mismatch in branches.

RigidUnify

Invented during unification.

RigidOutOfScope Loc VName

A name used in a size went out of scope.

data BreadCrumbs Source #

Unification failures can occur deep down inside complicated types (consider nested records). We leave breadcrumbs behind us so we can report the path we took to find the mismatch. When combining breadcrumbs with the Semigroup instance, put the innermost breadcrumbs to the left.

allDimsFreshInType :: MonadUnify m => Usage -> Rigidity -> Name -> TypeBase d o -> m (TypeBase Size o, Map VName d) Source #

Replace *all* dimensions with distinct fresh size variables.

dimNotes :: (Located a, MonadUnify m) => a -> Exp -> m Notes Source #

Retrieve notes describing the purpose or origin of the given Size. The location is used as the *current* location, for the purpose of reporting relative locations.

normTypeFully :: (Substitutable a, MonadUnify m) => a -> m a Source #

Replace all type variables with their substitution.

unify :: MonadUnify m => Usage -> StructType -> StructType -> m () Source #

Unifies two types.

unifyMostCommon :: MonadUnify m => Usage -> StructType -> StructType -> m (StructType, [VName]) Source #

Like unification, but creates new size variables where mismatches occur. Returns the new dimensions thus created.

doUnification :: Loc -> [TypeParam] -> [TypeParam] -> StructType -> StructType -> Either TypeError () Source #

Check that two types match, instantiating the nonrigid type parameters of the second type as necessary. This is used when matching a value or type in a module against a specification.

This works in two phases. First the types are checked while disregarding sizes entirely, using the same constraint solver as the unsized type checker. This also determines the instantiation of the nonrigid type parameters, up to sizes. Then the instantiations, given fresh size variables, are substituted into the second type, and the sizes are checked with ordinary (size-only) unification.