Language-neutral type inference and checking for Morphir IR
let filled = @typing.infer(file, deps, Fill) catch {
InferenceFailed(problems) => ...
}| Mode | Result |
|---|---|
| Fill | The file with an inferred_type on every Value and Pattern of every body that inference walks. Each signature type that has a marked variable is replaced by its solution. |
| Check | The input file, unchanged. Use it to check the types that a file already has. |
let deps = Map::from_array([
(@sdk_spec.sdk_package_name(), @sdk_spec.sdk_specification()),
])| Literal | Type |
|---|---|
| Integer | A fresh number variable |
| Float | Float |
| Decimal | decimal#decimal |
| String | String |
| Char | Char |
| Bool | Bool |
| Document | morphir/SDK:document#document when that type is known, otherwise unsupported |
| Class | Satisfied by |
|---|---|
| number | Int, Float |
| comparable | Int, Float, Char, String, List c, tuples of 2 or 3 comparables |
| appendable | String, List a |
| compappend | String, List c |
| Value | Type rule |
|---|---|
| Field(v, f) | v : { r \| f : t }, and the result is t |
| FieldFunction f | { r \| f : t } -> t |
| UpdateRecord | The result has its target's type. Each field that it sets must exist with the new value's type. |
| Record literal | Closed: it has exactly its fields |
| Code | Meaning | Example message |
|---|---|---|
| type_mismatch | Two types do not unify | expected Int, found String |
| occurs | The type would be infinite | the type would be infinite: a occurs in List a |
| rigid_variable | A body narrows an annotated variable | the variable a is annotated as any type, but the body needs number |
| no_instance | No type satisfies the constraint class | the type String is not a number |
| missing_field | The record has no such field | the record has no field count |
| unknown_reference | The name is not defined, but its package is known | x is not defined |
| missing_dependency | No specification for the package of the name | there is no specification for the package of x |
| arity | A non-function is applied, or a constructor pattern has the wrong number of arguments | the type Int is not a function, so it cannot take an argument |
| annotation_mismatch | An existing inferred_type disagrees with inference | the node has the type Int, but inference gives String |
| unsupported | A construct that inference does not handle | inference does not support x |
| Child | Steps |
|---|---|
| A declaration's body | /body |
| Apply | /function, /argument |
| Lambda | /pattern, /body |
| LetDefinition | /definition/body, /in |
| LetRecursion | /definitions/<name>/body, /in |
| Destructure | /pattern, /value, /in |
| IfThenElse | /condition, /then, /else |
| PatternMatch | /subject, /cases/<i>/pattern, /cases/<i>/body |
| Tuple, List | /items/<i> |
| Record | /fields/<name> |
| Field | /record |
| UpdateRecord | /record, /fields/<name> |
| AsPattern | /pattern |
| TuplePattern | /items/<i> |
| ConstructorPattern | /args/<i> |
| HeadTailPattern | /head, /tail |
pub(all) struct InferenceProblem {
code : String
node : String
message : String
expected : Type?
found : Type?
source : SourceLocation?
} derive(Eq, Debug)pub struct TypeContext {
// private fields
}pub struct TypeScope {
// private fields
}fn infer(file : IRFile, deps : Map[Path, PackageSpecification], mode : Mode) -> IRFile raise InferenceFailed