conlang: add lang items, remove Empty, and shuffle typeck
This commit is contained in:
@@ -205,4 +205,8 @@ impl<'t, 'a> EntryMut<'t, 'a> {
|
||||
pub fn mark_impl_item(&mut self) {
|
||||
self.table.mark_impl_item(self.id)
|
||||
}
|
||||
|
||||
pub fn mark_lang_item(&mut self, lang_item: &'static str) {
|
||||
self.table.mark_lang_item(lang_item, self.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,6 @@ impl fmt::Display for Entry<'_, '_> {
|
||||
write!(f, "fn {} -> ", self.with_id(*args))?;
|
||||
write_name_or(self.with_id(*rety), f)
|
||||
}
|
||||
TypeKind::Empty => write!(f, "()"),
|
||||
TypeKind::Never => write!(f, "!"),
|
||||
TypeKind::Module => write!(f, "module?"),
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -17,8 +17,6 @@ pub fn categorize(table: &mut Table, node: Handle) -> CatResult<()> {
|
||||
};
|
||||
|
||||
match source {
|
||||
Source::Alias(a) => cat_alias(table, node, a)?,
|
||||
Source::Enum(e) => cat_enum(table, node, e)?,
|
||||
Source::Variant(v) => cat_variant(table, node, v)?,
|
||||
Source::Struct(s) => cat_struct(table, node, s)?,
|
||||
Source::Const(c) => cat_const(table, node, c)?,
|
||||
@@ -26,21 +24,8 @@ pub fn categorize(table: &mut Table, node: Handle) -> CatResult<()> {
|
||||
Source::Function(f) => cat_function(table, node, f)?,
|
||||
Source::Local(l) => cat_local(table, node, l)?,
|
||||
Source::Impl(i) => cat_impl(table, node, i)?,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(meta) = table.meta(node) {
|
||||
for meta @ Meta { name, kind } in meta {
|
||||
if let ("lang", MetaKind::Equals(Literal::String(s))) = (&**name, kind) {
|
||||
if let Ok(prim) = s.parse() {
|
||||
table.set_ty(node, TypeKind::Primitive(prim));
|
||||
} else {
|
||||
table.mark_lang_item(s.into(), node);
|
||||
continue;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
// Source::Alias(_) => {table.mark_unchecked(node)},
|
||||
_ => return Ok(()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -49,20 +34,6 @@ fn parent(table: &Table, node: Handle) -> Handle {
|
||||
table.parent(node).copied().unwrap_or(node)
|
||||
}
|
||||
|
||||
fn cat_alias(table: &mut Table, node: Handle, a: &Alias) -> CatResult<()> {
|
||||
let parent = parent(table, node);
|
||||
let kind = match &a.from {
|
||||
Some(ty) => TypeKind::Instance(
|
||||
ty.evaluate(table, parent)
|
||||
.map_err(|e| Error::TypeEval(e, " while categorizing an alias"))?,
|
||||
),
|
||||
None => TypeKind::Empty,
|
||||
};
|
||||
table.set_ty(node, kind);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cat_struct(table: &mut Table, node: Handle, s: &Struct) -> CatResult<()> {
|
||||
let Struct { name: _, gens: _, kind } = s;
|
||||
// TODO: Generics
|
||||
@@ -99,7 +70,6 @@ fn cat_member(
|
||||
|
||||
fn cat_enum<'a>(_table: &mut Table<'a>, _node: Handle, e: &'a Enum) -> CatResult<()> {
|
||||
let Enum { name: _, gens: _, variants: _ } = e;
|
||||
|
||||
// table.set_ty(node, kind);
|
||||
Ok(())
|
||||
}
|
||||
@@ -107,17 +77,10 @@ fn cat_enum<'a>(_table: &mut Table<'a>, _node: Handle, e: &'a Enum) -> CatResult
|
||||
fn cat_variant<'a>(table: &mut Table<'a>, node: Handle, v: &'a Variant) -> CatResult<()> {
|
||||
let Variant { name, kind, body } = v;
|
||||
let parent = table.parent(node).copied().unwrap_or(table.root());
|
||||
match (kind, body) {
|
||||
(StructKind::Empty, None) => {
|
||||
table.set_ty(node, TypeKind::Adt(Adt::UnitStruct));
|
||||
Ok(())
|
||||
}
|
||||
(StructKind::Empty, Some(c)) => {
|
||||
table.set_body(node, c);
|
||||
table.set_ty(node, TypeKind::Adt(Adt::UnitStruct));
|
||||
Ok(())
|
||||
}
|
||||
(StructKind::Tuple(ty), None) => {
|
||||
match (kind) {
|
||||
(StructKind::Empty) => Ok(()),
|
||||
(StructKind::Empty) => Ok(()),
|
||||
(StructKind::Tuple(ty)) => {
|
||||
let ty = TypeKind::Adt(Adt::TupleStruct(
|
||||
ty.iter()
|
||||
.map(|ty| ty.evaluate(table, node).map(|ty| (Visibility::Public, ty)))
|
||||
@@ -126,7 +89,7 @@ fn cat_variant<'a>(table: &mut Table<'a>, node: Handle, v: &'a Variant) -> CatRe
|
||||
table.set_ty(node, ty);
|
||||
Ok(())
|
||||
}
|
||||
(StructKind::Struct(members), None) => {
|
||||
(StructKind::Struct(members)) => {
|
||||
let mut out = vec![];
|
||||
for StructMember { vis, name, ty } in members {
|
||||
let ty = ty.evaluate(table, node)?;
|
||||
@@ -144,9 +107,6 @@ fn cat_variant<'a>(table: &mut Table<'a>, node: Handle, v: &'a Variant) -> CatRe
|
||||
table.set_ty(node, TypeKind::Adt(Adt::Struct(out)));
|
||||
Ok(())
|
||||
}
|
||||
(_, Some(body)) => {
|
||||
panic!("Unexpected body `{body}` in enum variant `{v}`")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
Source::Module(v) => v.infer(&mut eng),
|
||||
Source::Alias(v) => v.infer(&mut eng),
|
||||
Source::Enum(v) => v.infer(&mut eng),
|
||||
Source::Variant(v) => v.infer(&mut eng),
|
||||
// Source::Variant(v) => v.infer(&mut eng),
|
||||
Source::Struct(v) => v.infer(&mut eng),
|
||||
Source::Const(v) => v.infer(&mut eng),
|
||||
Source::Static(v) => v.infer(&mut eng),
|
||||
@@ -221,42 +221,37 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
}
|
||||
|
||||
/// All primitives must be predefined in the standard library.
|
||||
pub fn primitive(&self, name: Sym) -> Option<Handle> {
|
||||
pub fn primitive(&self, name: &'static str) -> Handle {
|
||||
// TODO: keep a map of primitives in the table root
|
||||
self.table.get_by_sym(self.table.root(), &name)
|
||||
self.table.get_lang_item(name)
|
||||
}
|
||||
|
||||
pub fn never(&mut self) -> Handle {
|
||||
self.table.anon_type(TypeKind::Never)
|
||||
self.table.get_lang_item("never")
|
||||
}
|
||||
|
||||
pub fn empty(&mut self) -> Handle {
|
||||
self.table.anon_type(TypeKind::Empty)
|
||||
self.table.anon_type(TypeKind::Tuple(vec![]))
|
||||
}
|
||||
|
||||
pub fn bool(&self) -> Handle {
|
||||
self.primitive("bool".into())
|
||||
.expect("There should be a type named bool.")
|
||||
self.primitive("bool")
|
||||
}
|
||||
|
||||
pub fn char(&self) -> Handle {
|
||||
self.primitive("char".into())
|
||||
.expect("There should be a type named char.")
|
||||
self.primitive("char")
|
||||
}
|
||||
|
||||
pub fn str(&self) -> Handle {
|
||||
self.primitive("str".into())
|
||||
.expect("There should be a type named str.")
|
||||
self.primitive("str")
|
||||
}
|
||||
|
||||
pub fn u32(&self) -> Handle {
|
||||
self.primitive("u32".into())
|
||||
.expect("There should be a type named u32.")
|
||||
self.primitive("u32")
|
||||
}
|
||||
|
||||
pub fn usize(&self) -> Handle {
|
||||
self.primitive("usize".into())
|
||||
.expect("There should be a type named usize.")
|
||||
self.primitive("usize")
|
||||
}
|
||||
|
||||
/// Creates a new inferred-integer literal
|
||||
@@ -344,7 +339,7 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
&TypeKind::FnSig { args, rety } => {
|
||||
is_generic_rec(this, args, seen) || is_generic_rec(this, rety, seen)
|
||||
}
|
||||
TypeKind::Empty | TypeKind::Never | TypeKind::Module => false,
|
||||
TypeKind::Module => false,
|
||||
}
|
||||
}
|
||||
is_generic_rec(self, ty, &mut HashSet::new())
|
||||
@@ -358,12 +353,12 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
return ty;
|
||||
};
|
||||
let entry = self.table.entry(ty);
|
||||
let Some(ty) = entry.ty().cloned() else {
|
||||
let Some(tykind) = entry.ty().cloned() else {
|
||||
return ty;
|
||||
};
|
||||
|
||||
// TODO: Parent the deep clone into a new "monomorphs" branch of tree
|
||||
match ty {
|
||||
match tykind {
|
||||
TypeKind::Variable => self.new_inferred(),
|
||||
TypeKind::Array(h, s) => {
|
||||
let ty = self.deep_clone(h);
|
||||
@@ -405,6 +400,10 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
let ty = self.deep_clone(h);
|
||||
self.table.anon_type(TypeKind::Ref(ty))
|
||||
}
|
||||
TypeKind::Ptr(handle) => {
|
||||
let ty = self.deep_clone(handle);
|
||||
self.table.anon_type(TypeKind::Ptr(ty))
|
||||
}
|
||||
TypeKind::Slice(h) => {
|
||||
let ty = self.deep_clone(h);
|
||||
self.table.anon_type(TypeKind::Slice(ty))
|
||||
@@ -418,7 +417,7 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
let rety = self.deep_clone(rety);
|
||||
self.table.anon_type(TypeKind::FnSig { args, rety })
|
||||
}
|
||||
_ => self.table.anon_type(ty),
|
||||
_ => ty,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,8 +471,6 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
| TypeKind::Variable
|
||||
| TypeKind::Adt(Adt::UnitStruct)
|
||||
| TypeKind::Primitive(_)
|
||||
| TypeKind::Empty
|
||||
| TypeKind::Never
|
||||
| TypeKind::Module => false,
|
||||
}
|
||||
}
|
||||
@@ -490,6 +487,10 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
};
|
||||
|
||||
match (a, b) {
|
||||
(TypeKind::Variable, TypeKind::Variable) => {
|
||||
self.set_instance(ah, bh);
|
||||
Ok(())
|
||||
}
|
||||
(TypeKind::Inferred, _) => {
|
||||
self.set_instance(ah, bh);
|
||||
Ok(())
|
||||
@@ -602,12 +603,8 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
|
||||
self.unify(a1, a2)?;
|
||||
self.unify(r1, r2)
|
||||
}
|
||||
(TypeKind::Empty, TypeKind::Tuple(t)) | (TypeKind::Tuple(t), TypeKind::Empty)
|
||||
if t.is_empty() =>
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
(TypeKind::Never, _) | (_, TypeKind::Never) => Ok(()),
|
||||
(TypeKind::Primitive(Primitive::Never), _)
|
||||
| (_, TypeKind::Primitive(Primitive::Never)) => Ok(()),
|
||||
(a, b) if a == b => Ok(()),
|
||||
_ => Err(InferenceError::Mismatch(ah, bh)),
|
||||
}
|
||||
|
||||
@@ -78,16 +78,31 @@ impl<'a> Inference<'a> for Module {
|
||||
|
||||
impl<'a> Inference<'a> for Alias {
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
Ok(e.empty())
|
||||
let Self { name: _, from } = self;
|
||||
// let this = e.by_name(name)?;
|
||||
let alias = if let Some(from) = from {
|
||||
TypeKind::Instance(e.infer(from)?)
|
||||
} else {
|
||||
TypeKind::Tuple(vec![])
|
||||
};
|
||||
|
||||
// This node may be a lang item referring to a primitive.
|
||||
let mut entry = e.at.to_entry_mut(e.table);
|
||||
if entry.ty().is_some() {
|
||||
return Ok(e.empty());
|
||||
}
|
||||
entry.set_ty(alias);
|
||||
|
||||
Ok(entry.id())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Inference<'a> for Const {
|
||||
#[allow(unused)]
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
let Self { name, ty, init } = self;
|
||||
let Self { name: _, ty, init } = self;
|
||||
// Same as static
|
||||
let node = e.by_name(name)?;
|
||||
let node = e.at; //.by_name(name)?;
|
||||
let ty = e.infer(ty)?;
|
||||
let mut scope = e.at(node);
|
||||
// infer body
|
||||
@@ -103,7 +118,7 @@ impl<'a> Inference<'a> for Static {
|
||||
#[allow(unused)]
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
let Static { mutable, name, ty, init } = self;
|
||||
let node = e.by_name(name)?;
|
||||
let node = e.at; //e.by_name(name)?;
|
||||
let ty = e.infer(ty)?;
|
||||
let mut scope = e.at(node);
|
||||
// infer body
|
||||
@@ -120,7 +135,7 @@ impl<'a> Inference<'a> for Function {
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
let Self { name, gens, sign, bind, body } = self;
|
||||
// bind name to signature
|
||||
let node = e.by_name(name)?;
|
||||
let node = e.at; // e.by_name(name)?;
|
||||
let node = e.deep_clone(node);
|
||||
let fnty = e.by_name(sign)?;
|
||||
e.unify(node, fnty)?;
|
||||
@@ -154,14 +169,15 @@ impl<'a> Inference<'a> for Function {
|
||||
|
||||
impl<'a> Inference<'a> for Enum {
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
let Self { name, gens, variants } = self;
|
||||
let node = e.by_name(name)?;
|
||||
let Self { name: _, gens, variants } = self;
|
||||
let node = e.at; //e.by_name(name)?;
|
||||
let mut scope = e.at(node);
|
||||
|
||||
scope.infer(gens)?;
|
||||
for variant in variants {
|
||||
println!("Inferring {variant}");
|
||||
let var_ty = scope.infer(variant)?;
|
||||
scope.unify(var_ty, node)?;
|
||||
scope.unify(node, var_ty)?;
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
@@ -169,31 +185,46 @@ impl<'a> Inference<'a> for Enum {
|
||||
|
||||
impl<'a> Inference<'a> for Variant {
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
let Self { name: _, kind: _, body } = self;
|
||||
let ty = e.new_inferred();
|
||||
let Self { name, kind: _, body } = self;
|
||||
let node = e.by_name(name)?;
|
||||
|
||||
// TODO: evaluate kind
|
||||
|
||||
if let Some(body) = body {
|
||||
let value = body.infer(e)?;
|
||||
e.unify(ty, value)?;
|
||||
// TODO: this doesn't work when some variants have bodies and some don't
|
||||
if e.table.ty(node).is_some() {
|
||||
println!("{node} has ty!");
|
||||
return Ok(node);
|
||||
}
|
||||
|
||||
Ok(ty)
|
||||
match body {
|
||||
Some(body) => {
|
||||
let mut e = e.at(node);
|
||||
let value = e.infer(body)?;
|
||||
e.unify(node, value)?;
|
||||
}
|
||||
_ => {
|
||||
e.table.entry_mut(node).set_ty(TypeKind::Inferred);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Inference<'a> for Struct {
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
Ok(e.new_inferred())
|
||||
let Self { name, gens, kind: _ } = self;
|
||||
let node = e.by_name(name)?;
|
||||
let mut e = e.at(node);
|
||||
e.infer(gens)?;
|
||||
|
||||
Ok(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Inference<'a> for Impl {
|
||||
fn infer(&'a self, e: &mut InferenceEngine<'_, 'a>) -> IfResult {
|
||||
let Self { gens: _, target, body } = self;
|
||||
let Self { gens, target, body } = self;
|
||||
// TODO: match gens to target gens
|
||||
// gens.infer(e)?;
|
||||
gens.infer(e)?;
|
||||
let instance = target.infer(e)?;
|
||||
let instance = e.def_usage(instance);
|
||||
let mut scope = e.at(instance);
|
||||
@@ -527,8 +558,9 @@ impl<'a> Inference<'a> for Binary {
|
||||
e.unify(tail, bool)?;
|
||||
Ok(bool)
|
||||
}
|
||||
Bk::RangeExc => todo!("Ranges in the type checker"),
|
||||
Bk::RangeInc => todo!("Ranges in the type checker"),
|
||||
// TODO: Don't return the generic form wholesale.
|
||||
Bk::RangeExc => Ok(e.table.get_lang_item("range_exc")),
|
||||
Bk::RangeInc => Ok(e.table.get_lang_item("range_exc")),
|
||||
Bk::Shl | Bk::Shr => {
|
||||
let shift_amount = e.u32();
|
||||
e.unify(tail, shift_amount)?;
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
type_kind::TypeKind,
|
||||
};
|
||||
use cl_ast::{
|
||||
ItemKind, Sym,
|
||||
ItemKind, Literal, Meta, MetaKind, Sym,
|
||||
ast_visitor::{Visit, Walk},
|
||||
};
|
||||
|
||||
@@ -57,6 +57,15 @@ impl<'a> Visit<'a> for Populator<'_, 'a> {
|
||||
entry.inner.set_span(*span);
|
||||
entry.inner.set_meta(&attrs.meta);
|
||||
|
||||
for Meta { name, kind } in &attrs.meta {
|
||||
if let ("lang", MetaKind::Equals(Literal::String(s))) = (name.to_ref(), kind) {
|
||||
if let Ok(prim) = s.parse() {
|
||||
entry.inner.set_ty(TypeKind::Primitive(prim));
|
||||
}
|
||||
entry.inner.mark_lang_item(Sym::from(s).to_ref());
|
||||
}
|
||||
}
|
||||
|
||||
entry.visit_children(i);
|
||||
|
||||
if let (Some(name), child) = (entry.name, entry.inner.id()) {
|
||||
@@ -158,8 +167,16 @@ impl<'a> Visit<'a> for Populator<'_, 'a> {
|
||||
self.inner.set_source(Source::Variant(value));
|
||||
self.set_name(*name);
|
||||
self.visit(kind);
|
||||
if let Some(body) = body {
|
||||
self.inner.set_body(body);
|
||||
match (kind, body) {
|
||||
(cl_ast::StructKind::Empty, None) => {
|
||||
self.inner.set_ty(TypeKind::Inferred);
|
||||
}
|
||||
(cl_ast::StructKind::Empty, Some(body)) => {
|
||||
self.inner.set_body(body);
|
||||
}
|
||||
(cl_ast::StructKind::Tuple(_items), None) => {}
|
||||
(cl_ast::StructKind::Struct(_struct_members), None) => {}
|
||||
(_, Some(body)) => panic!("Unexpected body {body} in enum variant `{value}`"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ pub struct Table<'a> {
|
||||
sources: HashMap<Handle, Source<'a>>,
|
||||
impl_targets: HashMap<Handle, Handle>,
|
||||
anon_types: HashMap<TypeKind, Handle>,
|
||||
lang_items: HashMap<Sym, Handle>,
|
||||
lang_items: HashMap<&'static str, Handle>,
|
||||
|
||||
// --- Queues for algorithms ---
|
||||
pub(crate) unchecked: Vec<Handle>,
|
||||
@@ -129,10 +129,17 @@ impl<'a> Table<'a> {
|
||||
self.impls.push(item);
|
||||
}
|
||||
|
||||
pub fn mark_lang_item(&mut self, name: Sym, item: Handle) {
|
||||
pub fn mark_lang_item(&mut self, name: &'static str, item: Handle) {
|
||||
self.lang_items.insert(name, item);
|
||||
}
|
||||
|
||||
pub fn get_lang_item(&self, name: &str) -> Handle {
|
||||
match self.lang_items.get(name).copied() {
|
||||
Some(handle) => handle,
|
||||
None => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_iter(&self) -> impl Iterator<Item = Handle> + use<> {
|
||||
self.kinds.keys()
|
||||
}
|
||||
|
||||
@@ -40,8 +40,7 @@ impl TypeExpression for Ty {
|
||||
impl TypeExpression for TyKind {
|
||||
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
|
||||
match self {
|
||||
TyKind::Never => Ok(table.anon_type(TypeKind::Never)),
|
||||
TyKind::Empty => Ok(table.anon_type(TypeKind::Empty)),
|
||||
TyKind::Never => Ok(table.get_lang_item("never")),
|
||||
TyKind::Infer => Ok(table.inferred_type()),
|
||||
TyKind::Path(p) => p.evaluate(table, node),
|
||||
TyKind::Array(a) => a.evaluate(table, node),
|
||||
@@ -97,10 +96,7 @@ impl TypeExpression for TySlice {
|
||||
impl TypeExpression for TyTuple {
|
||||
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
|
||||
let Self { types } = self;
|
||||
let kind = match types.len() {
|
||||
0 => TypeKind::Empty,
|
||||
_ => TypeKind::Tuple(types.evaluate(table, node)?),
|
||||
};
|
||||
let kind = TypeKind::Tuple(types.evaluate(table, node)?);
|
||||
Ok(table.anon_type(kind))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,6 @@ pub enum TypeKind {
|
||||
Tuple(Vec<Handle>),
|
||||
/// A function which accepts multiple inputs and produces an output
|
||||
FnSig { args: Handle, rety: Handle },
|
||||
/// The unit type
|
||||
Empty,
|
||||
/// The never type
|
||||
Never,
|
||||
/// An untyped module
|
||||
Module,
|
||||
}
|
||||
@@ -70,6 +66,7 @@ pub enum Primitive {
|
||||
Bool, // boolean value
|
||||
Char, // Unicode codepoint
|
||||
Str, // UTF-8 string
|
||||
Never, // The never type
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
@@ -121,6 +118,7 @@ impl FromStr for Primitive {
|
||||
"bool" => Primitive::Bool,
|
||||
"char" => Primitive::Char,
|
||||
"str" => Primitive::Str,
|
||||
"never" => Primitive::Never,
|
||||
_ => Err(())?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -25,8 +25,6 @@ impl Display for TypeKind {
|
||||
})(f.delimit_with("tuple (", ")"))
|
||||
}
|
||||
TypeKind::FnSig { args, rety } => write!(f, "fn (#{args}) -> #{rety}"),
|
||||
TypeKind::Empty => f.write_str("()"),
|
||||
TypeKind::Never => f.write_str("!"),
|
||||
TypeKind::Module => f.write_str("mod"),
|
||||
}
|
||||
}
|
||||
@@ -94,6 +92,7 @@ impl Display for Primitive {
|
||||
Primitive::Bool => f.write_str("bool"),
|
||||
Primitive::Char => f.write_str("char"),
|
||||
Primitive::Str => f.write_str("str"),
|
||||
Primitive::Never => f.write_str("!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user