Do not return Option from monomorphize_var

This commit is contained in:
Agus Zubiaga 2024-12-11 15:26:40 -03:00
parent 4b28136143
commit 9868c5cfac
No known key found for this signature in database
3 changed files with 32 additions and 63 deletions

View file

@ -114,40 +114,38 @@ impl<'a, 'c, 'd, 'i, 's, 't, P: Push<Problem>> Env<'a, 'c, 'd, 'i, 's, 't, P> {
// Plain decimal number literals like `4.2` can still have an unbound var.
MonoExpr::Number(Number::Dec(*val))
}
_ => match mono_from_var(*var) {
Some(mono_id) => match mono_types.get(mono_id) {
_ => {
let mono_type = mono_from_var(*var);
match mono_types.get(mono_type) {
MonoType::Primitive(primitive) => to_frac(*primitive, *val, problems),
other => {
compiler_bug!(Problem::NumSpecializedToWrongType(Some(*other)))
}
},
None => {
compiler_bug!(Problem::NumSpecializedToWrongType(None))
}
},
}
}
}
Expr::Num(var, _, int_value, _) | Expr::Int(var, _, _, int_value, _) => {
let mono_type = mono_from_var(*var);
// Number literals and int literals both specify integer numbers, so to_num() can work on both.
match mono_from_var(*var) {
Some(mono_id) => match mono_types.get(mono_id) {
MonoType::Primitive(primitive) => to_num(*primitive, *int_value, problems),
other => compiler_bug!(Problem::NumSpecializedToWrongType(Some(*other))),
},
None => compiler_bug!(Problem::NumSpecializedToWrongType(None)),
match mono_types.get(mono_type) {
MonoType::Primitive(primitive) => to_num(*primitive, *int_value, problems),
other => compiler_bug!(Problem::NumSpecializedToWrongType(Some(*other))),
}
}
Expr::SingleQuote(var, _, char, _) => match mono_from_var(*var) {
Expr::SingleQuote(var, _, char, _) => {
let mono_type = mono_from_var(*var);
// Single-quote characters monomorphize to an integer.
// TODO if we store these using the same representation as other ints (e.g. Expr::Int,
// TODO [mono2] if we store these using the same representation as other ints (e.g. Expr::Int,
// or keeping a separate value but storing an IntValue instead of a char), then
// even though we verify them differently, we can combine this branch with Num and Int.
Some(mono_id) => match mono_types.get(mono_id) {
match mono_types.get(mono_type) {
MonoType::Primitive(primitive) => char_to_int(*primitive, *char, problems),
other => compiler_bug!(Problem::CharSpecializedToWrongType(Some(*other))),
},
None => compiler_bug!(Problem::CharSpecializedToWrongType(None)),
},
}
}
Expr::Str(contents) => MonoExpr::Str(self.string_interns.get_id(
self.arena,
// TODO should be able to remove this alloc_str() once canonical Expr stores an arena-allocated string.

View file

@ -129,37 +129,21 @@ impl MonoTypes {
pub(crate) fn add_function(
&mut self,
ret: Option<MonoTypeId>,
ret: MonoTypeId,
args: impl IntoIterator<Item = MonoTypeId>,
) -> MonoTypeId {
let mono_type = match ret {
Some(ret) => {
let ret_then_args = {
let start = self.ids.len();
self.ids.push(ret);
self.ids.extend(args);
// Safety: we definitely have at least 2 elements in here, even if the iterator is empty.
let length =
unsafe { NonZeroU16::new_unchecked((self.ids.len() - start) as u16) };
let ret_then_args = {
let start = self.ids.len();
self.ids.push(ret);
self.ids.extend(args);
// Safety: we definitely have at least 2 elements in here, even if the iterator is empty.
let length = unsafe { NonZeroU16::new_unchecked((self.ids.len() - start) as u16) };
NonEmptySlice::new(start as u32, length)
};
MonoType::Func { ret_then_args }
}
None => {
let args = {
let start = self.ids.len();
self.ids.extend(args);
let length = (self.ids.len() - start) as u16;
Slice::new(start as u32, length)
};
MonoType::VoidFunc { args }
}
NonEmptySlice::new(start as u32, length)
};
let mono_type = MonoType::Func { ret_then_args };
let index = self.entries.len();
self.entries.push(mono_type);
MonoTypeId::new(Index::new(index as u32))
@ -275,16 +259,6 @@ pub enum MonoType {
Func {
ret_then_args: NonEmptySlice<MonoTypeId>,
},
/// A function that does not have a return value (e.g. the return value was {}, which
/// got eliminated), and which has 0 or more arguments.
/// This has to be its own variant because the other function variant uses one slice to
/// store the return value followed by the arguments. Without this separate variant,
/// the other one couldn't distinguish between a function with a return value and 0 arguments,
/// and a function with 1 argument but no return value.
VoidFunc {
args: Slice<MonoTypeId>,
},
// This last slot is tentatively reserved for Dict, because in the past we've discussed wanting to
// implement Dict in Zig (for performance) instead of on top of List, like it is as of this writing.
//

View file

@ -71,7 +71,7 @@ impl MonoTypeCache {
problems: &mut impl Push<Problem>,
debug_info: &mut Option<DebugInfo>,
var: Variable,
) -> Option<MonoTypeId> {
) -> MonoTypeId {
let mut env = Env {
arena,
cache: self,
@ -135,7 +135,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
mono_args.extend(
arg_vars
.into_iter()
.flat_map(|var_index| self.lower_var(subs, subs[var_index])),
.map(|var_index| self.lower_var(subs, subs[var_index])),
);
// TODO [mono2] populate debuginfo as appropriate
@ -143,7 +143,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
self.mono_types.add_function(func, mono_args)
}
fn lower_var(&mut self, subs: &Subs, var: Variable) -> Option<MonoTypeId> {
fn lower_var(&mut self, subs: &Subs, var: Variable) -> MonoTypeId {
let root_var = subs.get_root_key_without_compacting(var);
// TODO: we could replace this cache by having Subs store a Content::Monomorphic(MonoTypeId)
@ -151,7 +151,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
// for sure, and the lookups should be faster because they're O(1) but don't require hashing.
// Kinda creates a cyclic dep though.
if let Some(mono_id) = self.cache.inner.get(&root_var) {
return Some(*mono_id);
return *mono_id;
}
// Convert the Content to a MonoType, often by passing an iterator. None of these iterators introduce allocations.
@ -291,7 +291,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
}
_ => {
// TODO [mono2] record in debuginfo the alias name for whatever we're lowering.
self.lower_var(subs, real)?
self.lower_var(subs, real)
}
}
}
@ -313,10 +313,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
};
// This var is now known to be monomorphic, so we don't repeat this work again later.
// (We don't insert entries for Unit values.)
self.cache.inner.insert(root_var, mono_id);
Some(mono_id)
mono_id
}
}