fix: distinguish content value from content type (#1482)

* fix: distinguish content value from content type

* docs: add comments

* fix: repr
This commit is contained in:
Myriad-Dreamin 2025-03-10 22:53:38 +08:00 committed by GitHub
parent 62815ae028
commit be9c0478f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 154 additions and 79 deletions

View file

@ -164,7 +164,7 @@ impl FnCompletionFeat {
BuiltinTy::TypeType(..) => {}
BuiltinTy::Clause
| BuiltinTy::Undef
| BuiltinTy::Content
| BuiltinTy::Content(..)
| BuiltinTy::Space
| BuiltinTy::None
| BuiltinTy::Break

View file

@ -279,7 +279,7 @@ impl IfaceChecker for CompletionScopeChecker<'_> {
self.defines.insert(name.clone().into(), term);
}
}
Iface::Element { val, .. } if self.is_field_access() => {
Iface::Content { val, .. } if self.is_field_access() => {
// 255 is the magic "label"
let styles = StyleChain::default();
for field_id in 0u8..254u8 {
@ -326,7 +326,7 @@ impl IfaceChecker for CompletionScopeChecker<'_> {
Iface::Dict { .. } if self.is_field_access() => {
self.type_methods(Some(iface.to_type()), Type::of::<Dict>());
}
Iface::Element { val, .. } => {
Iface::Content { val, .. } => {
self.defines.insert_scope(val.scope());
}
// todo: distingusish TypeType and Type

View file

@ -148,7 +148,7 @@ impl TypeCompletionWorker<'_, '_, '_, '_> {
BuiltinTy::Space => return None,
BuiltinTy::Break => return None,
BuiltinTy::Continue => return None,
BuiltinTy::Content => return None,
BuiltinTy::Content(..) => return None,
BuiltinTy::Infer => return None,
BuiltinTy::FlowNone => return None,
BuiltinTy::Tag(..) => return None,

View file

@ -289,7 +289,7 @@ impl TypeChecker<'_> {
self.check(content);
}
Ty::Builtin(BuiltinTy::Element(element.elem))
Ty::Builtin(BuiltinTy::Content(Some(element.elem)))
}
fn check_unary(&mut self, unary: &Interned<UnExpr>) -> Ty {
@ -452,7 +452,7 @@ impl TypeChecker<'_> {
let selected = match selector {
Some(selector) => Self::content_by_selector(selector)?,
None => Ty::Builtin(BuiltinTy::Content),
None => Ty::Builtin(BuiltinTy::Content(None)),
};
let show_fact = Ty::Func(SigTy::unary(selected, Ty::Any));
@ -463,33 +463,38 @@ impl TypeChecker<'_> {
}
fn content_by_selector(selector: Ty) -> Option<Ty> {
#[inline(always)]
fn text_type() -> Ty {
Ty::Builtin(BuiltinTy::Content(Some(
Element::of::<typst::text::TextElem>(),
)))
}
crate::log_debug_ct!("check selector {selector:?}");
Some(match selector {
Ty::With(with) => return Self::content_by_selector(with.sig.as_ref().clone()),
Ty::Builtin(BuiltinTy::Type(ty)) => {
if ty == Type::of::<typst::foundations::Regex>() {
Ty::Builtin(BuiltinTy::Element(Element::of::<typst::text::TextElem>()))
text_type()
} else {
return None;
}
}
Ty::Builtin(BuiltinTy::Element(..)) => selector,
Ty::Builtin(BuiltinTy::Element(ty)) => Ty::Builtin(BuiltinTy::Content(Some(ty))),
Ty::Value(ins_ty) => match &ins_ty.val {
Value::Str(..) => {
Ty::Builtin(BuiltinTy::Element(Element::of::<typst::text::TextElem>()))
}
Value::Content(c) => Ty::Builtin(BuiltinTy::Element(c.elem())),
Value::Str(..) => text_type(),
Value::Content(c) => Ty::Builtin(BuiltinTy::Content(Some(c.elem()))),
Value::Func(f) => {
if let Some(elem) = f.element() {
Ty::Builtin(BuiltinTy::Element(elem))
Ty::Builtin(BuiltinTy::Content(Some(elem)))
} else {
return None;
}
}
Value::Dyn(value) => {
if value.ty() == Type::of::<typst::foundations::Regex>() {
Ty::Builtin(BuiltinTy::Element(Element::of::<typst::text::TextElem>()))
text_type()
} else {
return None;
}
@ -540,7 +545,7 @@ impl TypeChecker<'_> {
if let Some(body) = content_ref.body.as_ref() {
self.check(body);
}
Ty::Builtin(BuiltinTy::Content)
Ty::Builtin(BuiltinTy::Content(None))
}
fn check_import(&mut self, import: &Interned<ImportExpr>) -> Ty {
@ -549,7 +554,7 @@ impl TypeChecker<'_> {
}
fn check_include(&mut self, _include: &Interned<IncludeExpr>) -> Ty {
Ty::Builtin(BuiltinTy::Content)
Ty::Builtin(BuiltinTy::Content(None))
}
fn check_contextual(&mut self, expr: &Interned<Expr>) -> Ty {

View file

@ -0,0 +1,6 @@
/// contains: add
#let add = math.op("+")
#let ct = []
#ct.a/* range 0..1 */

View file

@ -0,0 +1,12 @@
---
source: crates/tinymist-query/src/completion.rs
description: Completion on / (67..68)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/math_op.typ
---
[
{
"isIncomplete": false,
"items": []
}
]

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/set_in_show.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "054",
"sortText": "053",
"textEdit": {
"newText": "raw(${1:})",
"range": {

View file

@ -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: (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: (content) => item | 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\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: (content) => item | 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: (content) => item | any = (body-indent: length, indent: length, marker: array | content | function, spacing: auto | length, tight: bool, ..: content) => list.item,\n w07: text = 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\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: (content) => item | any\n```\n\n\n\n## w07 (named)\n\n```typc\ntype: text\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"
}

View file

@ -2,20 +2,19 @@
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/bug_cite_func_infer.typ
snapshot_kind: text
---
"cite_prose" = (RefLabel) => Element(ref)
"cite_prose" = (RefLabel) => Content(ref)
"labl" = Any
"cite_prose_different_name" = (RefLabel) => Element(ref)
"cite_prose_different_name" = (RefLabel) => Content(ref)
"labl" = Any
=====
5..15 -> @cite_prose
16..20 -> @labl
24..27 -> Func(ref)
24..33 -> Element(ref)
24..33 -> Content(ref)
28..32 -> @labl
39..64 -> @cite_prose_different_name
65..69 -> @labl
73..76 -> Func(ref)
73..82 -> Element(ref)
73..82 -> Content(ref)
77..81 -> @labl

View file

@ -2,11 +2,10 @@
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/infer.typ
snapshot_kind: text
---
=====
1..6 -> Func(image)
1..18 -> Element(image)
1..18 -> Content(image)
21..25 -> Func(read)
21..37 -> (Type(bytes) | Type(str))
40..44 -> Func(json)

View file

@ -5,48 +5,48 @@ input_file: crates/tinymist-query/src/fixtures/type_check/infer2.typ
---
=====
1..5 -> Func(text)
1..52 -> Element(text)
1..52 -> Content(text)
23..25 -> ()
46..49 -> Rgb(1, 0.254902, 0.211765, 1)
54..58 -> Func(path)
54..82 -> Element(path)
54..82 -> Content(path)
65..68 -> Rgb(1, 0.254902, 0.211765, 1)
78..81 -> Rgb(1, 0.254902, 0.211765, 1)
84..88 -> Func(line)
84..127 -> Element(line)
84..127 -> Content(line)
123..126 -> Rgb(1, 0.254902, 0.211765, 1)
129..133 -> Func(rect)
129..220 -> Element(rect)
129..220 -> Content(rect)
165..168 -> Rgb(1, 0.254902, 0.211765, 1)
178..181 -> Rgb(1, 0.254902, 0.211765, 1)
222..229 -> Func(ellipse)
222..253 -> Element(ellipse)
222..253 -> Content(ellipse)
236..239 -> Rgb(1, 0.254902, 0.211765, 1)
249..252 -> Rgb(1, 0.254902, 0.211765, 1)
255..261 -> Func(circle)
255..285 -> Element(circle)
255..285 -> Content(circle)
268..271 -> Rgb(1, 0.254902, 0.211765, 1)
281..284 -> Rgb(1, 0.254902, 0.211765, 1)
287..290 -> Func(box)
287..314 -> Element(box)
287..314 -> Content(box)
297..300 -> Rgb(1, 0.254902, 0.211765, 1)
310..313 -> Rgb(1, 0.254902, 0.211765, 1)
316..321 -> Func(block)
316..345 -> Element(block)
316..345 -> Content(block)
328..331 -> Rgb(1, 0.254902, 0.211765, 1)
341..344 -> Rgb(1, 0.254902, 0.211765, 1)
347..352 -> Func(table)
347..439 -> Element(table)
347..439 -> Content(table)
362..365 -> Rgb(1, 0.254902, 0.211765, 1)
377..380 -> Rgb(1, 0.254902, 0.211765, 1)
384..389 -> Func(table)
384..395 -> (Func(hline) | (Func(hline) | Func(table).hline))
384..408 -> Element(hline)
384..408 -> Content(hline)
404..407 -> Rgb(1, 0.254902, 0.211765, 1)
412..417 -> Func(table)
412..423 -> (Func(vline) | (Func(vline) | Func(table).vline))
412..436 -> Element(vline)
412..436 -> Content(vline)
432..435 -> Rgb(1, 0.254902, 0.211765, 1)
441..445 -> Func(text)
441..457 -> Element(text)
441..457 -> Content(text)
454..456 -> ()

View file

@ -5,6 +5,6 @@ input_file: crates/tinymist-query/src/fixtures/type_check/infer_stroke_dict.typ
---
=====
1..5 -> Func(text)
1..54 -> Element(text)
1..54 -> Content(text)
14..51 -> {"paint": Luma(0, 1), "thickness": 1.0pt}
25..30 -> Luma(0, 1)

View file

@ -2,10 +2,9 @@
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/show.typ
snapshot_kind: text
---
"" = (Any) => Any.it
"it" = Element(text)
"it" = Content(text)
=====
26..31 -> Type(regex)
26..40 -> Type(regex)

View file

@ -2,10 +2,9 @@
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/show_raw.typ
snapshot_kind: text
---
"" = (Any) => Any.it
"it" = Element(raw)
"it" = Content(raw)
=====
26..29 -> Func(raw)
31..33 -> @it

View file

@ -2,10 +2,9 @@
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/show_raw_where.typ
snapshot_kind: text
---
"" = (Any) => Any.it
"it" = Element(raw)
"it" = Content(raw)
=====
26..29 -> Func(raw)
26..35 -> (Func(raw) | Func(raw).where)

View file

@ -7,19 +7,19 @@ input_file: crates/tinymist-query/src/fixtures/type_check/text_font.typ
"y" = ("Test", )
=====
1..5 -> Func(text)
1..21 -> Element(text)
1..21 -> Content(text)
23..27 -> Func(text)
23..39 -> Element(text)
23..39 -> Content(text)
34..36 -> ()
41..45 -> Func(text)
41..64 -> Element(text)
41..64 -> Content(text)
52..61 -> ("Test", )
70..71 -> @x
82..86 -> Func(text)
82..97 -> Element(text)
82..97 -> Content(text)
93..94 -> @x
103..104 -> @y
107..116 -> ("Test", )
118..122 -> Func(text)
118..133 -> Element(text)
118..133 -> Content(text)
129..130 -> @y

View file

@ -6,9 +6,10 @@ use rustc_hash::FxHashMap;
use std::ops::Deref;
use tinymist_std::hash::hash128;
use typst::{
foundations::{Element, NativeElement, Value},
model::{EmphElem, EnumElem, HeadingElem, ListElem, StrongElem, TermsElem},
syntax::{Span, SyntaxNode},
foundations::{Element, NativeElement, Type, Value},
model::{EmphElem, EnumElem, HeadingElem, ListElem, ParbreakElem, StrongElem, TermsElem},
syntax::{ast::MathTextKind, Span, SyntaxNode},
text::LinebreakElem,
utils::LazyHash,
};
@ -370,16 +371,37 @@ impl ExprWorker<'_> {
.map_or_else(none_expr, |body| self.check(body)),
)),
Text(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
MathText(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
Raw(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
Link(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
Text(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
typst::text::TextElem,
>())))),
MathText(t) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some({
match t.get() {
MathTextKind::Character(..) => Element::of::<typst::foundations::SymbolElem>(),
MathTextKind::Number(..) => Element::of::<typst::foundations::SymbolElem>(),
}
})))),
Raw(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
typst::text::RawElem,
>())))),
Link(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
typst::model::LinkElem,
>())))),
Space(..) => Expr::Type(Ty::Builtin(BuiltinTy::Space)),
Linebreak(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
Parbreak(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
Escape(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
Shorthand(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
SmartQuote(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
Linebreak(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
LinebreakElem,
>())))),
Parbreak(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
ParbreakElem,
>())))),
Escape(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
typst::text::TextElem,
>())))),
Shorthand(..) => Expr::Type(Ty::Builtin(BuiltinTy::Type(Type::of::<
typst::foundations::Symbol,
>()))),
SmartQuote(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
typst::text::SmartQuoteElem,
>())))),
Strong(strong) => {
let body = self.check_inline_markup(strong.body());
@ -407,8 +429,13 @@ impl ExprWorker<'_> {
self.check_element::<TermsElem>(eco_vec![term, description])
}
MathAlignPoint(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
MathShorthand(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content)),
MathAlignPoint(..) => Expr::Type(Ty::Builtin(BuiltinTy::Content(Some(Element::of::<
typst::math::AlignPointElem,
>(
))))),
MathShorthand(..) => Expr::Type(Ty::Builtin(BuiltinTy::Type(Type::of::<
typst::foundations::Symbol,
>()))),
MathDelimited(math_delimited) => {
self.check_math(math_delimited.body().to_untyped().children())
}

View file

@ -136,7 +136,7 @@ impl Ty {
pub(crate) fn from_return_site(func: &Func, ty: &'_ CastInfo) -> Self {
use typst::foundations::func::Repr;
match func.inner() {
Repr::Element(elem) => return Ty::Builtin(BuiltinTy::Element(*elem)),
Repr::Element(elem) => return Ty::Builtin(BuiltinTy::Content(Some(*elem))),
Repr::Closure(_) | Repr::Plugin(_) => {}
Repr::With(w) => return Ty::from_return_site(&w.0, ty),
Repr::Native(_) => {}
@ -208,7 +208,6 @@ impl TryFrom<FileId> for PackageId {
pub enum BuiltinTy {
Clause,
Undef,
Content,
Space,
None,
Break,
@ -239,9 +238,16 @@ pub enum BuiltinTy {
Radius,
Tag(Box<(StrRef, Option<Interned<PackageId>>)>),
/// A value having a specific type.
Type(typst::foundations::Type),
/// A value of some type.
TypeType(typst::foundations::Type),
/// A content having a specific element type.
Content(Option<typst::foundations::Element>),
/// A value of some element type.
Element(typst::foundations::Element),
Module(Interned<Decl>),
Path(PathPreference),
}
@ -251,7 +257,13 @@ impl fmt::Debug for BuiltinTy {
match self {
BuiltinTy::Clause => f.write_str("Clause"),
BuiltinTy::Undef => f.write_str("Undef"),
BuiltinTy::Content => f.write_str("Content"),
BuiltinTy::Content(ty) => {
if let Some(ty) = ty {
write!(f, "Content({})", ty.name())
} else {
f.write_str("Content")
}
}
BuiltinTy::Space => f.write_str("Space"),
BuiltinTy::None => f.write_str("None"),
BuiltinTy::Break => f.write_str("Break"),
@ -324,7 +336,7 @@ impl BuiltinTy {
return Length.literally();
}
if builtin == Type::of::<Content>() {
return Ty::Builtin(BuiltinTy::Content);
return Ty::Builtin(BuiltinTy::Content(Option::None));
}
BuiltinTy::Type(builtin).literally()
@ -334,7 +346,13 @@ impl BuiltinTy {
let res = match self {
BuiltinTy::Clause => "any",
BuiltinTy::Undef => "any",
BuiltinTy::Content => "content",
BuiltinTy::Content(ty) => {
return if let Some(ty) = ty {
eco_format!("content({})", ty.name())
} else {
"content".into()
};
}
BuiltinTy::Space => "content",
BuiltinTy::None => "none",
BuiltinTy::Break => "break",

View file

@ -220,7 +220,7 @@ impl Ty {
}
}
/// Get the type of the type
/// Get as element type
pub fn element(&self) -> Option<Element> {
match self {
Ty::Value(ins_ty) => match &ins_ty.val {
@ -242,7 +242,7 @@ impl Ty {
res = res || {
match ty {
Ty::Value(v) => is_content_builtin_type(&v.val.ty()),
Ty::Builtin(BuiltinTy::Content | BuiltinTy::Element(..)) => true,
Ty::Builtin(BuiltinTy::Content(..)) => true,
Ty::Builtin(BuiltinTy::Type(v)) => is_content_builtin_type(v),
_ => false,
}

View file

@ -170,7 +170,10 @@ impl TypeDescriber {
Ty::With(w) => {
return self.describe(&w.sig);
}
Ty::Builtin(BuiltinTy::Content | BuiltinTy::Space) => {
Ty::Builtin(BuiltinTy::Content(Some(elem))) => {
return elem.name().into();
}
Ty::Builtin(BuiltinTy::Content(None) | BuiltinTy::Space) => {
return "content".into();
}
// Doesn't provide any information, hence we doesn't describe it intermediately here.

View file

@ -1,4 +1,4 @@
use typst::foundations::{Dict, Module, Scope, Type};
use typst::foundations::{Dict, Func, Module, Scope, Type};
use typst::syntax::FileId;
use super::BoundChecker;
@ -9,7 +9,7 @@ pub enum Iface<'a> {
Array(&'a Interned<Ty>),
Tuple(&'a Interned<Vec<Ty>>),
Dict(&'a Interned<RecordTy>),
Element {
Content {
val: &'a typst::foundations::Element,
at: &'a Ty,
},
@ -45,7 +45,7 @@ impl Iface<'_> {
Iface::Array(ty) => Ty::Array(ty.clone()),
Iface::Tuple(tys) => Ty::Tuple(tys.clone()),
Iface::Dict(dict) => Ty::Dict(dict.clone()),
Iface::Element { at, .. }
Iface::Content { at, .. }
| Iface::TypeType { at, .. }
| Iface::Type { at, .. }
| Iface::Func { at, .. }
@ -62,7 +62,7 @@ impl Iface<'_> {
match self {
Iface::Array(..) | Iface::Tuple(..) => None,
Iface::Dict(dict) => dict.field_by_name(key).cloned(),
Iface::Element { val, .. } => select_scope(Some(val.scope()), key),
Iface::Content { val, .. } => select_scope(Some(val.scope()), key),
// todo: distinguish TypeType and Type
Iface::TypeType { val, .. } | Iface::Type { val, .. } => {
select_scope(Some(val.scope()), key)
@ -196,7 +196,11 @@ impl IfaceCheckDriver<'_> {
}
}
// todo: more builtin types to check
Ty::Builtin(BuiltinTy::Content) if self.value_as_iface() => {
Ty::Builtin(BuiltinTy::Content(Some(elem))) if self.value_as_iface() => {
self.checker
.check(Iface::Content { val: elem, at }, &mut self.ctx, pol);
}
Ty::Builtin(BuiltinTy::Content(..)) if self.value_as_iface() => {
let ty = Type::of::<typst::foundations::Content>();
self.checker
.check(Iface::Type { val: &ty, at }, &mut self.ctx, pol);
@ -207,8 +211,14 @@ impl IfaceCheckDriver<'_> {
.check(Iface::Type { val: ty, at }, &mut self.ctx, pol);
}
Ty::Builtin(BuiltinTy::Element(elem)) if self.value_as_iface() => {
self.checker
.check(Iface::Element { val: elem, at }, &mut self.ctx, pol);
self.checker.check(
Iface::Func {
val: &Func::from(*elem),
at,
},
&mut self.ctx,
pol,
);
}
Ty::Builtin(BuiltinTy::Module(module)) => {
if let Decl::Module(m) = module.as_ref() {