mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 17:58:17 +00:00
dev: introduce TypeType
and Module
type (#843)
* dev: introduce `TypeType` and `Module` type g * test: update snapshot * test: update snapshot
This commit is contained in:
parent
c551950a85
commit
a9800bc802
21 changed files with 150 additions and 96 deletions
|
@ -720,7 +720,7 @@ impl SharedContext {
|
|||
return cached;
|
||||
}
|
||||
|
||||
let res = crate::analysis::term_value(self, val);
|
||||
let res = crate::analysis::term_value(val);
|
||||
|
||||
self.analysis
|
||||
.caches
|
||||
|
|
|
@ -464,6 +464,12 @@ fn analyze_dyn_signature(
|
|||
SignatureTarget::Convert(func) | SignatureTarget::Runtime(func) => func.clone(),
|
||||
};
|
||||
|
||||
Some(func_signature(func))
|
||||
}
|
||||
|
||||
/// Gets the signature of a function.
|
||||
#[comemo::memoize]
|
||||
pub fn func_signature(func: Func) -> Signature {
|
||||
use typst::foundations::func::Repr;
|
||||
let mut with_stack = eco_vec![];
|
||||
let mut func = func;
|
||||
|
@ -482,19 +488,6 @@ fn analyze_dyn_signature(
|
|||
func = f.0.clone();
|
||||
}
|
||||
|
||||
let signature = analyze_dyn_signature_inner(func);
|
||||
log::trace!("got signature {signature:?}");
|
||||
|
||||
if with_stack.is_empty() {
|
||||
return Some(Signature::Primary(signature));
|
||||
}
|
||||
Some(Signature::Partial(Arc::new(PartialSignature {
|
||||
signature,
|
||||
with_stack,
|
||||
})))
|
||||
}
|
||||
|
||||
fn analyze_dyn_signature_inner(func: Func) -> Arc<PrimarySignature> {
|
||||
let mut pos_tys = vec![];
|
||||
let mut named_tys = Vec::new();
|
||||
let mut rest_ty = None;
|
||||
|
@ -530,7 +523,6 @@ fn analyze_dyn_signature_inner(func: Func) -> Arc<PrimarySignature> {
|
|||
}
|
||||
};
|
||||
|
||||
use typst::foundations::func::Repr;
|
||||
let ret_ty = match func.inner() {
|
||||
Repr::With(..) => unreachable!(),
|
||||
Repr::Closure(c) => {
|
||||
|
@ -561,13 +553,24 @@ fn analyze_dyn_signature_inner(func: Func) -> Arc<PrimarySignature> {
|
|||
param_specs.push(doc);
|
||||
}
|
||||
|
||||
Arc::new(PrimarySignature {
|
||||
let signature = Arc::new(PrimarySignature {
|
||||
docs: func.docs().map(From::from),
|
||||
param_specs,
|
||||
has_fill_or_size_or_stroke,
|
||||
sig_ty: sig_ty.into(),
|
||||
_broken: broken,
|
||||
})
|
||||
});
|
||||
|
||||
log::trace!("got signature {signature:?}");
|
||||
|
||||
if with_stack.is_empty() {
|
||||
return Signature::Primary(signature);
|
||||
}
|
||||
|
||||
Signature::Partial(Arc::new(PartialSignature {
|
||||
signature,
|
||||
with_stack,
|
||||
}))
|
||||
}
|
||||
|
||||
fn analyze_closure_signature(
|
||||
|
|
|
@ -31,6 +31,7 @@ pub(crate) fn type_check(
|
|||
route: &mut TypeEnv,
|
||||
) -> Arc<TypeScheme> {
|
||||
let mut info = TypeScheme::default();
|
||||
info.valid = true;
|
||||
info.revision = ei.revision;
|
||||
|
||||
route.insert(ei.fid, Arc::new(TypeScheme::default()));
|
||||
|
@ -48,6 +49,16 @@ pub(crate) fn type_check(
|
|||
let type_check_start = std::time::Instant::now();
|
||||
|
||||
checker.check(&root);
|
||||
|
||||
let exports = checker
|
||||
.ei
|
||||
.exports
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k.clone(), checker.check(v)))
|
||||
.collect();
|
||||
checker.info.exports = exports;
|
||||
|
||||
let elapsed = type_check_start.elapsed();
|
||||
log::debug!("Type checking on {:?} took {elapsed:?}", checker.ei.fid);
|
||||
|
||||
|
@ -99,14 +110,7 @@ impl<'a> TyCtxMut for TypeChecker<'a> {
|
|||
|
||||
fn check_module_item(&mut self, fid: TypstFileId, k: &StrRef) -> Option<Ty> {
|
||||
let ei = self.ctx.expr_stage_by_id(fid)?;
|
||||
let item = ei.exports.get(k)?;
|
||||
match item {
|
||||
Expr::Decl(decl) => Some(self.check_decl(decl)),
|
||||
Expr::Ref(r) => r.root.clone().map(|r| self.check(&r)),
|
||||
_ => {
|
||||
panic!("unexpected module item: {item:?}");
|
||||
}
|
||||
}
|
||||
Some(self.check(ei.exports.get(k)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,39 @@
|
|||
use crate::analysis::func_signature;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn term_value(ctx: &Arc<SharedContext>, value: &Value) -> Ty {
|
||||
pub fn is_plain_value(value: &Value) -> bool {
|
||||
matches!(
|
||||
value,
|
||||
Value::Label(..)
|
||||
| Value::None
|
||||
| Value::Auto
|
||||
| Value::Bool(..)
|
||||
| Value::Int(..)
|
||||
| Value::Float(..)
|
||||
| Value::Decimal(..)
|
||||
| Value::Length(..)
|
||||
| Value::Angle(..)
|
||||
| Value::Ratio(..)
|
||||
| Value::Relative(..)
|
||||
| Value::Fraction(..)
|
||||
| Value::Color(..)
|
||||
| Value::Gradient(..)
|
||||
| Value::Pattern(..)
|
||||
| Value::Symbol(..)
|
||||
| Value::Version(..)
|
||||
| Value::Str(..)
|
||||
| Value::Bytes(..)
|
||||
| Value::Datetime(..)
|
||||
| Value::Duration(..)
|
||||
| Value::Content(..)
|
||||
| Value::Styles(..)
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets the type of a value.
|
||||
#[comemo::memoize]
|
||||
pub fn term_value(value: &Value) -> Ty {
|
||||
match value {
|
||||
Value::Array(a) => {
|
||||
let values = a
|
||||
|
@ -34,38 +67,17 @@ pub fn term_value(ctx: &Arc<SharedContext>, value: &Value) -> Ty {
|
|||
.collect();
|
||||
Ty::Dict(RecordTy::new(values))
|
||||
}
|
||||
Value::Type(ty) => Ty::Builtin(BuiltinTy::Type(*ty)),
|
||||
Value::Type(ty) => Ty::Builtin(BuiltinTy::TypeType(*ty)),
|
||||
Value::Dyn(v) => Ty::Builtin(BuiltinTy::Type(v.ty())),
|
||||
Value::Func(func) => Ty::Func(ctx.type_of_func(func.clone()).type_sig()),
|
||||
Value::Label(..)
|
||||
| Value::None
|
||||
| Value::Auto
|
||||
| Value::Bool(..)
|
||||
| Value::Int(..)
|
||||
| Value::Float(..)
|
||||
| Value::Decimal(..)
|
||||
| Value::Length(..)
|
||||
| Value::Angle(..)
|
||||
| Value::Ratio(..)
|
||||
| Value::Relative(..)
|
||||
| Value::Fraction(..)
|
||||
| Value::Color(..)
|
||||
| Value::Gradient(..)
|
||||
| Value::Pattern(..)
|
||||
| Value::Symbol(..)
|
||||
| Value::Version(..)
|
||||
| Value::Str(..)
|
||||
| Value::Bytes(..)
|
||||
| Value::Datetime(..)
|
||||
| Value::Duration(..)
|
||||
| Value::Content(..)
|
||||
| Value::Styles(..) => Ty::Value(InsTy::new(value.clone())),
|
||||
Value::Func(func) => Ty::Func(func_signature(func.clone()).type_sig()),
|
||||
_ if is_plain_value(value) => Ty::Value(InsTy::new(value.clone())),
|
||||
_ => Ty::Any,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn term_value_rec(value: &Value, s: Span) -> Ty {
|
||||
match value {
|
||||
Value::Type(ty) => Ty::Builtin(BuiltinTy::Type(*ty)),
|
||||
Value::Type(ty) => Ty::Builtin(BuiltinTy::TypeType(*ty)),
|
||||
Value::Dyn(v) => Ty::Builtin(BuiltinTy::Type(v.ty())),
|
||||
Value::None
|
||||
| Value::Auto
|
||||
|
|
|
@ -484,7 +484,8 @@ impl<'a> TypeChecker<'a> {
|
|||
Ty::Builtin(BuiltinTy::Content)
|
||||
}
|
||||
|
||||
fn check_import(&mut self, _import: &Interned<ImportExpr>) -> Ty {
|
||||
fn check_import(&mut self, import: &Interned<ImportExpr>) -> Ty {
|
||||
self.check_ref(&import.decl);
|
||||
Ty::Builtin(BuiltinTy::None)
|
||||
}
|
||||
|
||||
|
@ -527,8 +528,21 @@ impl<'a> TypeChecker<'a> {
|
|||
|
||||
pub(crate) fn check_decl(&mut self, decl: &Interned<Decl>) -> Ty {
|
||||
let v = Ty::Var(self.get_var(decl));
|
||||
if let Decl::Label(..) = decl.as_ref() {
|
||||
self.constrain(&v, &Ty::Builtin(BuiltinTy::Label));
|
||||
match decl.kind() {
|
||||
DefKind::Reference => {
|
||||
self.constrain(&v, &Ty::Builtin(BuiltinTy::Label));
|
||||
}
|
||||
DefKind::Module => {
|
||||
let ty = if decl.is_def() {
|
||||
Some(Ty::Builtin(BuiltinTy::Module(decl.clone())))
|
||||
} else {
|
||||
self.ei.get_def(decl).map(|e| self.check(&e))
|
||||
};
|
||||
if let Some(ty) = ty {
|
||||
self.constrain(&v, &ty);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
v
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/completion.rs
|
||||
description: Completion on c( (84..86)
|
||||
description: Completion on c( (85..87)
|
||||
expression: "JsonRepr::new_pure(results)"
|
||||
input_file: crates/tinymist-query/src/fixtures/completion/import_self3.typ
|
||||
---
|
||||
|
@ -12,7 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/import_self3.typ
|
|||
"kind": 9,
|
||||
"label": "baz",
|
||||
"labelDetails": {
|
||||
"description": "base.typ"
|
||||
"description": "module(base)"
|
||||
},
|
||||
"textEdit": {
|
||||
"newText": "baz",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/completion.rs
|
||||
description: Completion on c( (87..89)
|
||||
description: Completion on c( (88..90)
|
||||
expression: "JsonRepr::new_pure(results)"
|
||||
input_file: crates/tinymist-query/src/fixtures/completion/import_self4.typ
|
||||
---
|
||||
|
@ -12,7 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/import_self4.typ
|
|||
"kind": 9,
|
||||
"label": "baz",
|
||||
"labelDetails": {
|
||||
"description": "base.typ"
|
||||
"description": "module(base)"
|
||||
},
|
||||
"textEdit": {
|
||||
"newText": "baz",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2,9 +2,8 @@
|
|||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/value_repr.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"contents": "```typc\nlet f(\n x: any,\n y: any,\n z: any,\n w01: int = 1,\n w02: str = \"test\",\n w03: any = 1 + 2,\n w04: any = Label(test),\n w05: function = box,\n w06: any = list.item,\n w07: content = Expr(..),\n w08: any = Expr(..),\n w09: any = 1 + 2,\n w10: array = (\n 1,\n 2,\n ),\n w11: array = (),\n w12: dictionary = (:),\n w13: dictionary = (a: 1),\n w14: dictionary = (a: box),\n w15: dictionary = (a: list.item),\n) = int;\n```\n\n---\n\n\n# Positional Parameters\n\n## x\n\n```typc\ntype: \n```\n\n\n\n## y (positional)\n\n```typc\ntype: \n```\n\n\n\n## z (positional)\n\n```typc\ntype: \n```\n\n\n\n# Named Parameters\n\n## w01\n\n```typc\ntype: 1\n```\n\n\n\n## w02 (named)\n\n```typc\ntype: \"test\"\n```\n\n\n\n## w03 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w04 (named)\n\n```typc\ntype: \n```\n\n\n\n## w05 (named)\n\n```typc\ntype: box\n```\n\n\n\n## w06 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w07 (named)\n\n```typc\ntype: content\n```\n\n\n\n## w08 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w09 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w10 (named)\n\n```typc\ntype: array\n```\n\n\n\n## w11 (named)\n\n```typc\ntype: array\n```\n\n\n\n## w12 (named)\n\n```typc\ntype: dictionary\n```\n\n\n\n## w13 (named)\n\n```typc\ntype: dictionary\n```\n\n\n\n## w14 (named)\n\n```typc\ntype: dictionary\n```\n\n\n\n## w15 (named)\n\n```typc\ntype: dictionary\n```\n\n",
|
||||
"contents": "```typc\nlet f(\n x: any,\n y: any,\n z: any,\n w01: int = 1,\n w02: str = \"test\",\n w03: any = 1 + 2,\n w04: any = Label(test),\n w05: (content | none, baseline: relative, clip: bool, fill: color, height: auto | relative, inset: inset, outset: outset, radius: radius, stroke: stroke, width: auto | fraction | relative) => box = (content | none, baseline: relative, clip: bool, fill: color, height: auto | relative, inset: inset, outset: outset, radius: radius, stroke: stroke, width: auto | fraction | relative) => box,\n w06: any = (body-indent: length, indent: length, marker: array | content | function, spacing: auto | length, tight: bool, ..: content) => list.item,\n w07: content = Expr(..),\n w08: any = Expr(..),\n w09: any = 1 + 2,\n w10: array = (\n 1,\n 2,\n ),\n w11: array = (),\n w12: dictionary = (:),\n w13: dictionary = (a: 1),\n w14: dictionary = (a: (content | none, baseline: relative, clip: bool, fill: color, height: auto | relative, inset: inset, outset: outset, radius: radius, stroke: stroke, width: auto | fraction | relative) => box),\n w15: dictionary = (a: (body-indent: length, indent: length, marker: array | content | function, spacing: auto | length, tight: bool, ..: content) => list.item),\n) = int;\n```\n\n---\n\n\n# Positional Parameters\n\n## x\n\n```typc\ntype: \n```\n\n\n\n## y (positional)\n\n```typc\ntype: \n```\n\n\n\n## z (positional)\n\n```typc\ntype: \n```\n\n\n\n# Named Parameters\n\n## w01\n\n```typc\ntype: 1\n```\n\n\n\n## w02 (named)\n\n```typc\ntype: \"test\"\n```\n\n\n\n## w03 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w04 (named)\n\n```typc\ntype: \n```\n\n\n\n## w05 (named)\n\n```typc\ntype: (content | none, baseline: relative, clip: bool, fill: color, height: auto | relative, inset: inset, outset: outset, radius: radius, stroke: stroke, width: auto | fraction | relative) => box\n```\n\n\n\n## w06 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w07 (named)\n\n```typc\ntype: content\n```\n\n\n\n## w08 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w09 (named)\n\n```typc\ntype: any\n```\n\n\n\n## w10 (named)\n\n```typc\ntype: array\n```\n\n\n\n## w11 (named)\n\n```typc\ntype: array\n```\n\n\n\n## w12 (named)\n\n```typc\ntype: dictionary\n```\n\n\n\n## w13 (named)\n\n```typc\ntype: dictionary\n```\n\n\n\n## w14 (named)\n\n```typc\ntype: dictionary\n```\n\n\n\n## w15 (named)\n\n```typc\ntype: dictionary\n```\n\n",
|
||||
"range": "23:20:23:21"
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
source: crates/tinymist-query/src/analysis.rs
|
||||
expression: result
|
||||
input_file: crates/tinymist-query/src/fixtures/type_check/external.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
"base" = Any
|
||||
"bad-instantiate" = Any
|
||||
"prefix" = (("title": ( ⪯ Any)) => TypeBinary { operands: (TypeBinary { operands: (TypeBinary { operands: (Any, None), op: Add }, None), op: Add }, None), op: Add }).with(..("title": None) => any)
|
||||
"title" = None
|
||||
---
|
||||
0..0 -> @bad-instantiate
|
||||
1..21 -> @base
|
||||
27..33 -> @prefix
|
||||
34..39 -> @title
|
||||
53..68 -> @bad-instantiate
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
source: crates/tinymist-query/src/analysis.rs
|
||||
expression: result
|
||||
input_file: crates/tinymist-query/src/fixtures/type_check/recursive.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
"base" = Any
|
||||
"a" = Any
|
||||
"f" = () => Any
|
||||
---
|
||||
0..0 -> @a
|
||||
1..21 -> @base
|
||||
27..28 -> @f
|
||||
33..34 -> @a
|
||||
33..36 -> Any
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
source: crates/tinymist-query/src/analysis.rs
|
||||
expression: result
|
||||
input_file: crates/tinymist-query/src/fixtures/type_check/recursive_use.typ
|
||||
snapshot_kind: text
|
||||
---
|
||||
"base" = Any
|
||||
"a" = Any
|
||||
"f" = () => Any
|
||||
---
|
||||
0..0 -> @a
|
||||
1..21 -> @base
|
||||
27..28 -> @f
|
||||
33..34 -> @a
|
||||
33..37 -> Any
|
||||
|
|
|
@ -737,7 +737,7 @@ pub struct SetExpr {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ImportExpr {
|
||||
pub decl: DeclExpr,
|
||||
pub decl: Interned<RefExpr>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -161,6 +161,14 @@ impl std::hash::Hash for ExprInfo {
|
|||
}
|
||||
|
||||
impl ExprInfo {
|
||||
pub fn get_def(&self, decl: &Interned<Decl>) -> Option<Expr> {
|
||||
if decl.is_def() {
|
||||
return Some(Expr::Decl(decl.clone()));
|
||||
}
|
||||
let resolved = self.resolves.get(&decl.span())?;
|
||||
Some(Expr::Ref(resolved.clone()))
|
||||
}
|
||||
|
||||
pub fn get_refs(
|
||||
&self,
|
||||
decl: Interned<Decl>,
|
||||
|
@ -612,7 +620,7 @@ impl<'a> ExprWorker<'a> {
|
|||
.insert_mut(decl.name().clone(), Expr::Ref(mod_ref.clone()));
|
||||
}
|
||||
|
||||
self.resolve_as(mod_ref);
|
||||
self.resolve_as(mod_ref.clone());
|
||||
|
||||
let fid = mod_expr.as_ref().and_then(|mod_expr| match mod_expr {
|
||||
Expr::Type(Ty::Value(v)) => match &v.val {
|
||||
|
@ -678,7 +686,7 @@ impl<'a> ExprWorker<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
Expr::Import(ImportExpr { decl }.into())
|
||||
Expr::Import(ImportExpr { decl: mod_ref }.into())
|
||||
}
|
||||
|
||||
fn check_import(&mut self, source: ast::Expr, is_import: bool) -> Option<Expr> {
|
||||
|
|
|
@ -274,7 +274,7 @@ impl<'a, T: fmt::Write> ExprPrinter<'a, T> {
|
|||
|
||||
fn write_import(&mut self, i: &Interned<ImportExpr>) -> fmt::Result {
|
||||
self.f.write_str("import(")?;
|
||||
self.write_decl(&i.decl)?;
|
||||
self.write_decl(&i.decl.decl)?;
|
||||
self.f.write_str(")")
|
||||
}
|
||||
|
||||
|
@ -589,7 +589,7 @@ impl<'a, T: fmt::Write> ExprDescriber<'a, T> {
|
|||
|
||||
fn write_import(&mut self, i: &Interned<ImportExpr>) -> fmt::Result {
|
||||
self.f.write_str("import(")?;
|
||||
self.write_decl(&i.decl)?;
|
||||
self.write_decl(&i.decl.decl)?;
|
||||
self.f.write_str(")")
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use typst::{
|
|||
layout::Length,
|
||||
};
|
||||
|
||||
use crate::syntax::Decl;
|
||||
use crate::ty::*;
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, EnumIter)]
|
||||
|
@ -228,7 +229,9 @@ pub enum BuiltinTy {
|
|||
|
||||
Tag(Box<(StrRef, Option<Interned<PackageId>>)>),
|
||||
Type(typst::foundations::Type),
|
||||
TypeType(typst::foundations::Type),
|
||||
Element(typst::foundations::Element),
|
||||
Module(Interned<Decl>),
|
||||
Path(PathPreference),
|
||||
}
|
||||
|
||||
|
@ -263,6 +266,7 @@ impl fmt::Debug for BuiltinTy {
|
|||
BuiltinTy::Inset => write!(f, "Inset"),
|
||||
BuiltinTy::Outset => write!(f, "Outset"),
|
||||
BuiltinTy::Radius => write!(f, "Radius"),
|
||||
BuiltinTy::TypeType(ty) => write!(f, "TypeType({})", ty.short_name()),
|
||||
BuiltinTy::Type(ty) => write!(f, "Type({})", ty.short_name()),
|
||||
BuiltinTy::Element(e) => e.fmt(f),
|
||||
BuiltinTy::Tag(tag) => {
|
||||
|
@ -273,6 +277,7 @@ impl fmt::Debug for BuiltinTy {
|
|||
write!(f, "Tag({name:?})")
|
||||
}
|
||||
}
|
||||
BuiltinTy::Module(m) => write!(f, "{m:?}"),
|
||||
BuiltinTy::Path(p) => write!(f, "Path({p:?})"),
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +348,7 @@ impl BuiltinTy {
|
|||
BuiltinTy::Inset => "inset",
|
||||
BuiltinTy::Outset => "outset",
|
||||
BuiltinTy::Radius => "radius",
|
||||
BuiltinTy::TypeType(..) => "type",
|
||||
BuiltinTy::Type(ty) => ty.short_name(),
|
||||
BuiltinTy::Element(ty) => ty.name(),
|
||||
BuiltinTy::Tag(tag) => {
|
||||
|
@ -353,6 +359,7 @@ impl BuiltinTy {
|
|||
eco_format!("tag {name}")
|
||||
};
|
||||
}
|
||||
BuiltinTy::Module(m) => return eco_format!("module({})", m.name()),
|
||||
BuiltinTy::Path(s) => match s {
|
||||
PathPreference::None => "[any]",
|
||||
PathPreference::Special => "[any]",
|
||||
|
|
|
@ -182,6 +182,7 @@ impl Ty {
|
|||
pub fn name(&self) -> Interned<str> {
|
||||
match self {
|
||||
Ty::Var(v) => v.name.clone(),
|
||||
Ty::Builtin(BuiltinTy::Module(m)) => m.name().clone(),
|
||||
ty => ty
|
||||
.value()
|
||||
.and_then(|v| Some(Interned::new_str(v.name()?)))
|
||||
|
@ -1085,8 +1086,12 @@ impl IfTy {
|
|||
/// A type scheme on a group of syntax structures (typing)
|
||||
#[derive(Default)]
|
||||
pub struct TypeScheme {
|
||||
/// Whether the typing is valid
|
||||
pub valid: bool,
|
||||
/// The revision used
|
||||
pub revision: usize,
|
||||
/// The exported types
|
||||
pub exports: FxHashMap<StrRef, Ty>,
|
||||
/// The typing on definitions
|
||||
pub vars: FxHashMap<DeclExpr, TypeVarBounds>,
|
||||
/// The checked documentation of definitions
|
||||
|
|
|
@ -2,15 +2,11 @@ use ecow::{eco_format, EcoString};
|
|||
use reflexo::hash::hash128;
|
||||
use typst::foundations::Repr;
|
||||
|
||||
use crate::{ty::prelude::*, upstream::truncated_repr_};
|
||||
|
||||
impl TypeScheme {
|
||||
/// Describe the given type with the given type scheme.
|
||||
pub fn describe(&self, ty: &Ty) -> Option<EcoString> {
|
||||
let mut worker: TypeDescriber = TypeDescriber::default();
|
||||
worker.describe_root(ty)
|
||||
}
|
||||
}
|
||||
use crate::{
|
||||
analysis::{is_plain_value, term_value},
|
||||
ty::prelude::*,
|
||||
upstream::truncated_repr_,
|
||||
};
|
||||
|
||||
impl Ty {
|
||||
/// Describe the given type.
|
||||
|
@ -196,6 +192,13 @@ impl TypeDescriber {
|
|||
Ty::Builtin(b) => {
|
||||
return b.describe();
|
||||
}
|
||||
Ty::Value(v) if matches!(v.val, Value::Module(..)) => {
|
||||
let Value::Module(m) = &v.val else {
|
||||
return "module".into();
|
||||
};
|
||||
return eco_format!("module({})", m.name());
|
||||
}
|
||||
Ty::Value(v) if !is_plain_value(&v.val) => return self.describe(&term_value(&v.val)),
|
||||
Ty::Value(v) if self.value => return truncated_repr_::<181>(&v.val),
|
||||
Ty::Value(v) if self.repr => return v.val.ty().short_name().into(),
|
||||
Ty::Value(v) => return v.val.repr(),
|
||||
|
|
|
@ -60,10 +60,7 @@ impl Ty {
|
|||
// iface_kind: IfaceSurfaceKind,
|
||||
checker: &mut impl IfaceChecker,
|
||||
) {
|
||||
let context = IfaceCheckContext {
|
||||
args: Vec::new(),
|
||||
at: TyRef::new(Ty::Any),
|
||||
};
|
||||
let context = IfaceCheckContext { args: Vec::new() };
|
||||
let mut worker = IfaceCheckDriver {
|
||||
ctx: context,
|
||||
checker,
|
||||
|
@ -75,7 +72,6 @@ impl Ty {
|
|||
|
||||
pub struct IfaceCheckContext {
|
||||
pub args: Vec<Interned<SigTy>>,
|
||||
pub at: TyRef,
|
||||
}
|
||||
|
||||
#[derive(BindTyCtx)]
|
||||
|
@ -161,6 +157,12 @@ impl<'a> IfaceCheckDriver<'a> {
|
|||
self.checker
|
||||
.check(Iface::Element { val: e, at: ty }, &mut self.ctx, pol);
|
||||
}
|
||||
Ty::Builtin(BuiltinTy::Module(e)) => {
|
||||
if let Decl::Module(m) = e.as_ref() {
|
||||
self.checker
|
||||
.check(Iface::Module { val: m.fid, at: ty }, &mut self.ctx, pol);
|
||||
}
|
||||
}
|
||||
// Ty::Func(sig) if self.value_as_iface() => {
|
||||
// self.checker.check(Iface::Type(sig), &mut self.ctx, pol);
|
||||
// }
|
||||
|
@ -174,13 +176,7 @@ impl<'a> IfaceCheckDriver<'a> {
|
|||
// self.check_dict_signature(sig, pol, self.checker);
|
||||
self.checker.check(Iface::Dict(sig), &mut self.ctx, pol);
|
||||
}
|
||||
Ty::Var(v) => match v.def.as_ref() {
|
||||
Decl::Module(m) => {
|
||||
self.checker
|
||||
.check(Iface::Module { val: m.fid, at: ty }, &mut self.ctx, pol);
|
||||
}
|
||||
_ => ty.bounds(pol, self),
|
||||
},
|
||||
Ty::Var(..) => ty.bounds(pol, self),
|
||||
_ if ty.has_bounds() => ty.bounds(pol, self),
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -287,7 +287,7 @@ impl<'a> CompletionContext<'a> {
|
|||
.and_then(|types| {
|
||||
let ty = types.type_of_span(span)?;
|
||||
let ty = types.simplify(ty, false);
|
||||
types.describe(&ty).map(From::from)
|
||||
ty.describe().map(From::from)
|
||||
})
|
||||
.or_else(|| {
|
||||
if let DefKind::Instance(_, v) = &def_kind {
|
||||
|
@ -767,6 +767,7 @@ fn type_completion(
|
|||
BuiltinTy::Infer => return None,
|
||||
BuiltinTy::FlowNone => return None,
|
||||
BuiltinTy::Tag(..) => return None,
|
||||
BuiltinTy::Module(..) => return None,
|
||||
|
||||
BuiltinTy::Path(p) => {
|
||||
let source = ctx.ctx.source_by_id(ctx.root.span().id()?).ok()?;
|
||||
|
@ -896,7 +897,7 @@ fn type_completion(
|
|||
BuiltinTy::RefLabel => {
|
||||
ctx.ref_completions();
|
||||
}
|
||||
BuiltinTy::Type(ty) => {
|
||||
BuiltinTy::TypeType(ty) | BuiltinTy::Type(ty) => {
|
||||
if *ty == Type::of::<NoneValue>() {
|
||||
let docs = docs.or(Some("Nothing."));
|
||||
type_completion(ctx, &Ty::Builtin(BuiltinTy::None), docs);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue