tinymist_analysis/ty/
mod.rs1mod apply;
4mod bound;
5mod builtin;
6mod convert;
7mod def;
8mod describe;
9mod iface;
10mod mutate;
11mod prelude;
12mod select;
13mod sig;
14mod simplify;
15mod subst;
16
17pub use apply::*;
18pub use bound::*;
19pub use builtin::*;
20pub use convert::*;
21pub use def::*;
22pub use iface::*;
23pub use mutate::*;
24pub use select::*;
25pub use sig::*;
26
27use typst::foundations::{self, Func, Module, Value};
28use typst::syntax::FileId;
29
30pub trait TyCtx {
32 fn local_bind_of(&self, _var: &Interned<TypeVar>) -> Option<Ty>;
34 fn global_bounds(&self, _var: &Interned<TypeVar>, _pol: bool) -> Option<DynTypeBounds>;
36}
37
38impl TyCtx for () {
39 fn local_bind_of(&self, _var: &Interned<TypeVar>) -> Option<Ty> {
40 None
41 }
42
43 fn global_bounds(&self, _var: &Interned<TypeVar>, _pol: bool) -> Option<DynTypeBounds> {
44 None
45 }
46}
47
48pub trait TyCtxMut: TyCtx {
50 type Snap;
52
53 #[must_use]
55 fn start_scope(&mut self) -> Self::Snap;
56 fn end_scope(&mut self, snap: Self::Snap);
58 fn with_scope<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
60 let snap = self.start_scope();
61 let res = f(self);
62 self.end_scope(snap);
63 res
64 }
65
66 fn bind_local(&mut self, var: &Interned<TypeVar>, ty: Ty);
68 fn type_of_func(&mut self, func: &Func) -> Option<Interned<SigTy>>;
70 fn type_of_value(&mut self, val: &Value) -> Ty;
72 fn type_of_dict(&mut self, dict: &foundations::Dict) -> Interned<RecordTy> {
74 let ty = self.type_of_value(&Value::Dict(dict.clone()));
75 let Ty::Dict(ty) = ty else {
76 panic!("expected dict type, found {ty:?}");
77 };
78 ty
79 }
80 fn type_of_module(&mut self, module: &Module) -> Interned<RecordTy> {
82 let ty = self.type_of_value(&Value::Module(module.clone()));
83 let Ty::Dict(ty) = ty else {
84 panic!("expected dict type, found {ty:?}");
85 };
86 ty
87 }
88 fn check_module_item(&mut self, module: FileId, key: &StrRef) -> Option<Ty>;
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use crate::adt::interner::Interned;
96 use crate::syntax::Decl;
97
98 pub fn var_ins(s: &str) -> Ty {
99 Ty::Var(TypeVar::new(s.into(), Decl::lit(s).into()))
100 }
101
102 pub fn str_sig(
103 pos: &[&str],
104 named: &[(&str, &str)],
105 rest: Option<&str>,
106 ret: Option<&str>,
107 ) -> Interned<SigTy> {
108 let pos = pos.iter().map(|s| var_ins(s));
109 let named = named.iter().map(|(n, t)| ((*n).into(), var_ins(t)));
110 let rest = rest.map(var_ins);
111 let ret = ret.map(var_ins);
112 SigTy::new(pos, named, None, rest, ret).into()
113 }
114
115 macro_rules! literal_sig {
117 ($($pos:ident),* $(!$named:ident: $named_ty:ident),* $(,)? ...$rest:ident -> $ret:ident) => {
118 str_sig(&[$(stringify!($pos)),*], &[$((stringify!($named), stringify!($named_ty))),*], Some(stringify!($rest)), Some(stringify!($ret)))
119 };
120 ($($pos:ident),* $(!$named:ident: $named_ty:ident),* $(,)? -> $ret:ident) => {
121 str_sig(&[$(stringify!($pos)),*], &[$((stringify!($named), stringify!($named_ty))),*], None, Some(stringify!($ret)))
122 };
123 ($($pos:ident),* $(!$named:ident: $named_ty:ident),* $(,)? ...$rest:ident) => {
124 str_sig(&[$(stringify!($pos)),*], &[$((stringify!($named), stringify!($named_ty))),*], Some(stringify!($rest)), None)
125 };
126 ($($pos:ident),* $(!$named:ident: $named_ty:ident),* $(,)?) => {
127 str_sig(&[$(stringify!($pos)),*], &[$((stringify!($named), stringify!($named_ty))),*], None, None)
128 };
129 }
130
131 pub(crate) use literal_sig;
132 pub(crate) use literal_sig as literal_args;
133}