TypR is a work-in-progress static type-checker for R. For more information, you can take a look at the poster we presented at the conference useR! 2026.
TypR is not quite ready to be tested on real R codebases yet, but you can star this repository if you want to stay updated!
TypR is composed of several components:
| Component | Description | State of advancement |
|---|---|---|
| TypR | Orchestrator. Parses R files and native libraries, resolve dependencies, and call the type-checkers. | Not testable yet |
| Rsem | Gradual type-checker for R functions. | Not testable yet (only works on basic examples) |
| NativeSem | Type inference for library functions in C (support for Fortran is planned). | Tested on several libraries, see dashboard |
| RSTT | Set-theoretic type algebra for the R language. Defines the type parser and printer, and the operations on types (e.g. subtyping, substitution, constraint solving). | The main R data-structures are supported (atomic vectors, lists, functions, attributes and classes, etc.) |
Other external dependencies:
| Component | Description | State of advancement |
|---|---|---|
| MLsem | A typing library for dynamic languages used by our type-checkers (both for R and C code). | Released |
| SSTT | A set-theoretic type library used to encode the R type algebra. | Released |
TypR drives Rsem and NativeSem as libraries, and all four projects -- TypR, Rsem, NativeSem and RSTT -- are built together as a single dune workspace. The three others are submodules, so the versions TypR is known to work with are pinned here:
git submodule update --init --recursive
make build
make testmake sources nativesem/setup-env.sh, which locates tree-sitter in a
checkout of r-parser that has been built
(make update && make setup && make, then opam pin add tree-sitter core/).
It is looked up at r-parser and then ../r-parser; set R_PARSER_PATH if
yours lives elsewhere. It is deliberately not a submodule: what the build needs
from it is core/tree-sitter, which its own make setup produces rather than
something a checkout provides. Everything else comes from the opam switch
(opam install . --deps-only).
# Report the dependencies TypR resolved, without type-checking
dune exec typr -- --deps path/to/package
# Type-check the package: native sources first, then the R sources
dune exec typr -- path/to/package
# Signatures of the functions the package builds upon (base R, imports)
dune exec typr -- --prelude base.R path/to/package- Discovery (
lib/pkg.ml) — the R sources underR/, the C sources undersrc/, and the.fixesprefix declared byuseDynLibinNAMESPACE. - Parsing — each file is parsed exactly once, with the parser of the
checker that owns the language:
Lang.Driver.parsefor R,R_c_typing.Runner.parse_filesfor C. The resulting ASTs are what gets handed to the type-checkers, so nothing is parsed twice. - Dependency resolution (
lib/r_deps.ml) — walking the R AST gives, per top-level definition, the names it uses and the native routines it reaches through.Call/.C/.Fortran/.External. This replaces the regex scan NativeSem used to locate a package's entry points. - Native side — NativeSem types the C sources, using those entry points as the roots of its own call graph.
- Linking (
lib/link.ml) — a routine's C type is a function over an argument tuple; the corresponding R binding is a closure over an R argument record. TypR converts the type, binds it under the R-visible (prefixed) name, and rewrites.Call(sym, a, b)intosym(a, b)so that the R checker uses it. Only.Callis rewritten:.Cand.Externaldo not pass their arguments through unchanged, so the C type is not the type of the call. - R side — the R files are type-checked in dependency order, and so are the definitions inside each file: a function definition is checked after whatever its body uses, wherever that is written, while a top-level statement is evaluated on the spot and so may only rely on what precedes it. Mutually recursive top-level definitions are a cycle no order satisfies, and one of them is still reported as unbound.
We run a benchmark with typing performance and effectiveness with a dashboard automatically updated on each update on several R packages from CRAN that you can find in this repo: r-typing.
This work is supported by the Czech Ministry of Education, Youth and Sports under program ERC-CZ, grant agreement LL2325, as well as by the Czech Science Foundation Grant No. 23-07580X.