merge main

This commit is contained in:
Bryce Miller 2023-06-07 20:36:54 -04:00
commit e463ccf4a6
No known key found for this signature in database
GPG key ID: F1E97BF8DF152350
59 changed files with 1192 additions and 706 deletions

View file

@ -121,16 +121,18 @@ impl<'a> Env<'a> {
Ok(symbol)
}
None => Err(RuntimeError::LookupNotInScope(
Loc {
None => Err(RuntimeError::LookupNotInScope {
loc_name: Loc {
value: Ident::from(ident),
region,
},
self.ident_ids
suggestion_options: self
.ident_ids
.ident_strs()
.map(|(_, string)| string.into())
.collect(),
)),
underscored_suggestion_region: None,
}),
}
} else {
match self.dep_idents.get(&module_id) {

View file

@ -203,13 +203,14 @@ impl Scope {
pub fn lookup(&mut self, ident: &Ident, region: Region) -> Result<Symbol, RuntimeError> {
match self.idents.get(ident) {
Some((symbol, _)) => Ok(*symbol),
None => Err(RuntimeError::LookupNotInScope(
Loc {
None => Err(RuntimeError::LookupNotInScope {
loc_name: Loc {
region,
value: ident.clone().into(),
},
self.idents.keys().map(|v| v.as_ref().into()).collect(),
)),
suggestion_options: self.idents.keys().map(|v| v.as_ref().into()).collect(),
underscored_suggestion_region: None,
}),
}
}

View file

@ -403,7 +403,7 @@ fn build_entry_point<'a>(
let block = builder.add_block();
let struct_layout = interner.insert_no_semantic(LayoutRepr::struct_(layouts));
let struct_layout = interner.insert_direct_no_semantic(LayoutRepr::struct_(layouts));
let type_id = layout_spec(env, &mut builder, interner, struct_layout)?;
let argument = builder.add_unknown_with(block, &[], type_id)?;
@ -461,7 +461,7 @@ fn proc_spec<'a>(
let root = BlockExpr(block, value_id);
let args_struct_layout =
interner.insert_no_semantic(LayoutRepr::struct_(argument_layouts.into_bump_slice()));
interner.insert_direct_no_semantic(LayoutRepr::struct_(argument_layouts.into_bump_slice()));
let arg_type_id = layout_spec(&mut env, &mut builder, interner, args_struct_layout)?;
let ret_type_id = layout_spec(&mut env, &mut builder, interner, proc.ret_layout)?;
@ -851,8 +851,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout = interner
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
Builtin::List(*return_layout),
));
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -880,7 +881,7 @@ fn call_spec<'a>(
let arg0_layout = argument_layouts[0];
let state_layout = interner
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(arg0_layout)));
.insert_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(arg0_layout)));
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = list;
@ -907,8 +908,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout = interner
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
Builtin::List(*return_layout),
));
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -941,8 +943,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout = interner
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
Builtin::List(*return_layout),
));
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -981,8 +984,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout = interner
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
Builtin::List(*return_layout),
));
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -1111,12 +1115,12 @@ fn lowlevel_spec<'a>(
let new_list = with_new_heap_cell(builder, block, bag)?;
// depending on the types, the list or value will come first in the struct
let fields = match interner.get(layout).repr {
let fields = match interner.get_repr(layout) {
LayoutRepr::Struct(field_layouts) => field_layouts,
_ => unreachable!(),
};
match (interner.get(fields[0]).repr, interner.get(fields[1]).repr) {
match (interner.get_repr(fields[0]), interner.get_repr(fields[1])) {
(LayoutRepr::Builtin(Builtin::List(_)), LayoutRepr::Builtin(Builtin::List(_))) => {
// field name is the tie breaker, list is first in
// { list : List a, value : a }
@ -1144,7 +1148,7 @@ fn lowlevel_spec<'a>(
ListWithCapacity => {
// essentially an empty list, capacity is not relevant for morphic
match interner.get(layout).repr {
match interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
let type_id = layout_spec(env, builder, interner, element_layout)?;
new_list(builder, block, type_id)
@ -1440,7 +1444,7 @@ fn expr_spec<'a>(
}
}
EmptyArray => match interner.get(layout).repr {
EmptyArray => match interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
let type_id = layout_spec(env, builder, interner, element_layout)?;
new_list(builder, block, type_id)
@ -1457,7 +1461,7 @@ fn expr_spec<'a>(
} => {
let tag_value_id = env.symbols[symbol];
let union_layout = match interner.get(layout).repr {
let union_layout = match interner.get_repr(layout) {
LayoutRepr::Union(ul) => ul,
_ => unreachable!(),
};
@ -1539,7 +1543,7 @@ fn layout_spec_help<'a>(
) -> Result<TypeId> {
use LayoutRepr::*;
match interner.get(layout).repr {
match interner.get_repr(layout) {
Builtin(builtin) => builtin_spec(env, builder, interner, &builtin),
Struct(field_layouts) => build_recursive_tuple_type(env, builder, interner, field_layouts),
LambdaSet(lambda_set) => {
@ -1578,7 +1582,7 @@ fn layout_spec_help<'a>(
builder.add_tuple_type(&[cell_type, inner_type])
}
// TODO(recursive-layouts): update once we have recursive pointer loops
RecursivePointer(union_layout) => match interner.get(union_layout).repr {
RecursivePointer(union_layout) => match interner.get_repr(union_layout) {
LayoutRepr::Union(union_layout) => {
assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();

View file

@ -34,7 +34,9 @@ pub const DEFAULT_ROC_FILENAME: &str = "main.roc";
#[derive(Debug, Clone, Copy, Default)]
pub struct CodeGenTiming {
pub code_gen: Duration,
pub generate_final_ir: Duration,
pub code_gen_object: Duration,
pub total: Duration,
}
pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems {
@ -144,7 +146,7 @@ fn gen_from_mono_module_llvm<'a>(
use inkwell::module::Linkage;
use inkwell::targets::{FileType, RelocMode};
let code_gen_start = Instant::now();
let all_code_gen_start = Instant::now();
// Generate the binary
let target_info = roc_target::TargetInfo::from(target);
@ -238,6 +240,10 @@ fn gen_from_mono_module_llvm<'a>(
&loaded.glue_layouts,
);
// We are now finished building the LLVM IR.
let generate_final_ir = all_code_gen_start.elapsed();
let code_gen_object_start = Instant::now();
env.dibuilder.finalize();
// we don't use the debug info, and it causes weird errors.
@ -439,11 +445,16 @@ fn gen_from_mono_module_llvm<'a>(
}
};
let code_gen = code_gen_start.elapsed();
let code_gen_object = code_gen_object_start.elapsed();
let total = all_code_gen_start.elapsed();
(
CodeObject::MemoryBuffer(memory_buffer),
CodeGenTiming { code_gen },
CodeGenTiming {
generate_final_ir,
code_gen_object,
total,
},
ExpectMetadata {
interns: env.interns,
layout_interner: loaded.layout_interner,
@ -503,7 +514,7 @@ fn gen_from_mono_module_dev_wasm32<'a>(
preprocessed_host_path: &Path,
wasm_dev_stack_bytes: Option<u32>,
) -> GenFromMono<'a> {
let code_gen_start = Instant::now();
let all_code_gen_start = Instant::now();
let MonomorphizedModule {
module_id,
procedures,
@ -550,11 +561,18 @@ fn gen_from_mono_module_dev_wasm32<'a>(
procedures,
);
let code_gen = code_gen_start.elapsed();
let generate_final_ir = all_code_gen_start.elapsed();
let code_gen_object_start = Instant::now();
let code_gen_object = code_gen_object_start.elapsed();
let total = all_code_gen_start.elapsed();
(
CodeObject::Vector(final_binary_bytes),
CodeGenTiming { code_gen },
CodeGenTiming {
generate_final_ir,
code_gen_object,
total,
},
ExpectMetadata {
interns,
layout_interner,
@ -569,7 +587,7 @@ fn gen_from_mono_module_dev_assembly<'a>(
target: &target_lexicon::Triple,
backend_mode: AssemblyBackendMode,
) -> GenFromMono<'a> {
let code_gen_start = Instant::now();
let all_code_gen_start = Instant::now();
let lazy_literals = true;
@ -593,15 +611,23 @@ fn gen_from_mono_module_dev_assembly<'a>(
let module_object =
roc_gen_dev::build_module(&env, &mut interns, &mut layout_interner, target, procedures);
let code_gen = code_gen_start.elapsed();
let generate_final_ir = all_code_gen_start.elapsed();
let code_gen_object_start = Instant::now();
let module_out = module_object
.write()
.expect("failed to build output object");
let code_gen_object = code_gen_object_start.elapsed();
let total = all_code_gen_start.elapsed();
(
CodeObject::Vector(module_out),
CodeGenTiming { code_gen },
CodeGenTiming {
generate_final_ir,
code_gen_object,
total,
},
ExpectMetadata {
interns,
layout_interner,
@ -919,9 +945,12 @@ fn build_loaded_file<'a>(
report_timing(
buf,
"Generate Assembly from Mono IR",
code_gen_timing.code_gen,
"Generate final IR from Mono IR",
code_gen_timing.generate_final_ir,
);
report_timing(buf, "Generate object", code_gen_timing.code_gen_object);
buf.push('\n');
report_timing(buf, "Total", code_gen_timing.total);
let compilation_end = compilation_start.elapsed();
let size = roc_app_bytes.len();

View file

@ -124,18 +124,19 @@ impl<'a> Env<'a> {
Ok(symbol)
}
None => {
let error = RuntimeError::LookupNotInScope(
Loc {
let error = RuntimeError::LookupNotInScope {
loc_name: Loc {
value: Ident::from(ident),
region,
},
scope
suggestion_options: scope
.locals
.ident_ids
.ident_strs()
.map(|(_, string)| string.into())
.collect(),
);
underscored_suggestion_region: None,
};
Err(error)
}
}

View file

@ -1019,9 +1019,18 @@ pub fn canonicalize_expr<'a>(
}
ast::Expr::Underscore(name) => {
// we parse underscores, but they are not valid expression syntax
let problem = roc_problem::can::RuntimeError::MalformedIdentifier(
(*name).into(),
roc_parse::ident::BadIdent::Underscore(region.start()),
if name.is_empty() {
roc_parse::ident::BadIdent::UnderscoreAlone(region.start())
} else {
roc_parse::ident::BadIdent::UnderscoreAtStart {
position: region.start(),
// Check if there's an ignored identifier with this name in scope (for better error messages)
declaration_region: scope.lookup_ignored_local(name),
}
},
region,
);

View file

@ -379,6 +379,12 @@ pub fn canonicalize_pattern<'a>(
Err(pattern) => pattern,
}
}
Underscore(name) => {
// An underscored identifier can't be used, but we'll still add it to the scope
// for better error messages if someone tries to use it.
scope.introduce_ignored_local(name, region);
Pattern::Underscore
}
Tag(name) => {
// Canonicalize the tag's name.
Pattern::AppliedTag {
@ -479,8 +485,6 @@ pub fn canonicalize_pattern<'a>(
ptype => unsupported_pattern(env, ptype, region),
},
Underscore(_) => Pattern::Underscore,
&NumLiteral(str) => match pattern_type {
WhenBranch => match finish_parsing_num(str) {
Err(_error) => {

View file

@ -41,6 +41,10 @@ pub struct Scope {
/// Identifiers that are in scope, and defined in the current module
pub locals: ScopedIdentIds,
/// Ignored variables (variables that start with an underscore).
/// We won't intern them because they're only used during canonicalization for error reporting.
ignored_locals: VecMap<String, Region>,
}
impl Scope {
@ -65,6 +69,7 @@ impl Scope {
abilities_store: starting_abilities_store,
shadows: VecMap::default(),
imports: default_imports,
ignored_locals: VecMap::default(),
}
}
@ -89,13 +94,17 @@ impl Scope {
match self.scope_contains_ident(ident) {
InScope(symbol, _) => Ok(symbol),
NotInScope(_) | NotPresent => {
let error = RuntimeError::LookupNotInScope(
Loc {
// identifier not found
let error = RuntimeError::LookupNotInScope {
loc_name: Loc {
region,
value: Ident::from(ident),
},
self.idents_in_scope().map(|v| v.as_ref().into()).collect(),
);
suggestion_options: self.idents_in_scope().map(|v| v.as_ref().into()).collect(),
// Check if the user just forgot to remove an underscore from an ignored identifier
underscored_suggestion_region: self.lookup_ignored_local(ident),
};
Err(error)
}
@ -418,11 +427,13 @@ impl Scope {
// - exposed_ident_count: unchanged
// - home: unchanged
let aliases_count = self.aliases.len();
let ignored_locals_count = self.ignored_locals.len();
let locals_snapshot = self.locals.in_scope.len();
let result = f(self);
self.aliases.truncate(aliases_count);
self.ignored_locals.truncate(ignored_locals_count);
// anything added in the inner scope is no longer in scope now
for i in locals_snapshot..self.locals.in_scope.len() {
@ -444,6 +455,19 @@ impl Scope {
pub fn gen_unique_symbol(&mut self) -> Symbol {
Symbol::new(self.home, self.locals.gen_unique())
}
/// Introduce a new ignored variable (variable starting with an underscore).
/// The underscore itself should not be included in `ident`.
pub fn introduce_ignored_local(&mut self, ident: &str, region: Region) {
self.ignored_locals.insert(ident.to_owned(), region);
}
/// Lookup an ignored variable (variable starting with an underscore).
/// The underscore itself should not be included in `ident`.
/// Returns the source code region of the ignored variable if it's found.
pub fn lookup_ignored_local(&self, ident: &str) -> Option<Region> {
self.ignored_locals.get(&ident.to_owned()).copied()
}
}
pub fn create_alias(

View file

@ -332,7 +332,7 @@ mod test_can {
matches!(
problem,
Problem::SignatureDefMismatch { .. }
| Problem::RuntimeError(RuntimeError::LookupNotInScope(_, _))
| Problem::RuntimeError(RuntimeError::LookupNotInScope { .. })
)
}));
}
@ -360,7 +360,7 @@ mod test_can {
matches!(
problem,
Problem::SignatureDefMismatch { .. }
| Problem::RuntimeError(RuntimeError::LookupNotInScope(_, _))
| Problem::RuntimeError(RuntimeError::LookupNotInScope { .. })
)
}));
}

View file

@ -761,7 +761,15 @@ fn remove_spaces_bad_ident(ident: BadIdent) -> BadIdent {
match ident {
BadIdent::Start(_) => BadIdent::Start(Position::zero()),
BadIdent::Space(e, _) => BadIdent::Space(e, Position::zero()),
BadIdent::Underscore(_) => BadIdent::Underscore(Position::zero()),
BadIdent::UnderscoreAlone(_) => BadIdent::UnderscoreAlone(Position::zero()),
BadIdent::UnderscoreInMiddle(_) => BadIdent::UnderscoreInMiddle(Position::zero()),
BadIdent::UnderscoreAtStart {
position: _,
declaration_region,
} => BadIdent::UnderscoreAtStart {
position: Position::zero(),
declaration_region,
},
BadIdent::QualifiedTag(_) => BadIdent::QualifiedTag(Position::zero()),
BadIdent::WeirdAccessor(_) => BadIdent::WeirdAccessor(Position::zero()),
BadIdent::WeirdDotAccess(_) => BadIdent::WeirdDotAccess(Position::zero()),

View file

@ -888,7 +888,7 @@ impl<
fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>) {
// move return value to dst.
let ret_repr = self.interner().get(*ret_layout).repr;
let ret_repr = self.interner().get_repr(*ret_layout);
match ret_repr {
single_register_integers!() => {
let width = RegisterWidth::try_from_layout(ret_repr).unwrap();
@ -1070,7 +1070,7 @@ impl<
}
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>) {
match self.interner().get(*layout).repr {
match self.interner().get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
@ -1086,7 +1086,7 @@ impl<
}
fn build_num_add(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout).repr {
match self.layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
@ -1120,7 +1120,7 @@ impl<
src2: Symbol,
layout: InLayout<'a>,
) {
match self.layout_interner.get(layout).repr {
match self.layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Int(width @ quadword_and_smaller!())) => {
let intrinsic = bitcode::NUM_ADD_SATURATED_INT[width].to_string();
self.build_fn_call(&dst, intrinsic, &[src1, src2], &[layout, layout], &layout);
@ -1161,7 +1161,7 @@ impl<
let base_offset = self.storage_manager.claim_stack_area(dst, struct_size);
match self.layout_interner.get(*num_layout).repr {
match self.layout_interner.get_repr(*num_layout) {
LayoutRepr::Builtin(Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
@ -1208,7 +1208,7 @@ impl<
num_layout: &InLayout<'a>,
return_layout: &InLayout<'a>,
) {
let function_name = match self.interner().get(*num_layout).repr {
let function_name = match self.interner().get_repr(*num_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => &bitcode::NUM_SUB_CHECKED_INT[width],
LayoutRepr::Builtin(Builtin::Float(width)) => &bitcode::NUM_SUB_CHECKED_FLOAT[width],
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_SUB_WITH_OVERFLOW,
@ -1227,7 +1227,7 @@ impl<
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
use Builtin::Int;
match self.layout_interner.get(*layout).repr {
match self.layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
@ -1291,7 +1291,7 @@ impl<
}
fn build_num_div(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout).repr {
match self.layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
@ -1347,7 +1347,7 @@ impl<
}
fn build_num_rem(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout).repr {
match self.layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
@ -1391,7 +1391,7 @@ impl<
}
fn build_num_neg(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout).repr {
match self.layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
@ -1414,7 +1414,7 @@ impl<
src2: &Symbol,
layout: &InLayout<'a>,
) {
match self.layout_interner.get(*layout).repr {
match self.layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
@ -1430,7 +1430,7 @@ impl<
}
fn build_eq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) {
let repr = self.interner().get(*arg_layout).repr;
let repr = self.interner().get_repr(*arg_layout);
match repr {
single_register_int_builtins!() | LayoutRepr::BOOL => {
let width = match repr {
@ -1546,7 +1546,7 @@ impl<
}
fn build_neq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) {
match self.interner().get(*arg_layout).repr {
match self.interner().get_repr(*arg_layout) {
single_register_int_builtins!() | LayoutRepr::BOOL => {
let width = match *arg_layout {
Layout::BOOL | Layout::I8 | Layout::U8 => RegisterWidth::W8,
@ -1588,7 +1588,7 @@ impl<
}
fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>) {
match self.interner().get(*arg_layout).repr {
match self.interner().get_repr(*arg_layout) {
LayoutRepr::BOOL => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
@ -1613,8 +1613,8 @@ impl<
) {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
match (
self.layout_interner.get(*arg_layout).repr,
self.layout_interner.get(*ret_layout).repr,
self.layout_interner.get_repr(*arg_layout),
self.layout_interner.get_repr(*ret_layout),
) {
(
LayoutRepr::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::I64)),
@ -1850,8 +1850,9 @@ impl<
let new_element_layout = higher_order.passed_function.return_layout;
let input_list_layout = LayoutRepr::Builtin(Builtin::List(old_element_layout));
let input_list_in_layout =
self.layout_interner.insert_no_semantic(input_list_layout);
let input_list_in_layout = self
.layout_interner
.insert_direct_no_semantic(input_list_layout);
let caller = self.debug_symbol("caller");
let data = self.debug_symbol("data");
@ -2256,7 +2257,7 @@ impl<
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let ret_fields =
if let LayoutRepr::Struct(field_layouts) = self.layout_interner.get(*ret_layout).repr {
if let LayoutRepr::Struct(field_layouts) = self.layout_interner.get_repr(*ret_layout) {
field_layouts
} else {
internal_error!(
@ -2478,7 +2479,7 @@ impl<
element_in_layout: &InLayout<'a>,
elements: &[ListLiteralElement<'a>],
) {
let element_layout = self.layout_interner.get(*element_in_layout);
let element_layout = self.layout_interner.get_repr(*element_in_layout);
let element_width = self.layout_interner.stack_size(*element_in_layout) as u64;
// load the total size of the data we want to store (excludes refcount)
@ -2677,7 +2678,7 @@ impl<
_ => {
let union_in_layout = self
.layout_interner
.insert_no_semantic(LayoutRepr::Union(*union_layout));
.insert_direct_no_semantic(LayoutRepr::Union(*union_layout));
todo!(
"loading from union type: {:?}",
self.layout_interner.dbg(union_in_layout)
@ -2700,7 +2701,7 @@ impl<
let element_width = self.layout_interner.stack_size(element_layout) as u64;
let element_offset = 0;
let layout = self.layout_interner.get(element_layout);
let layout = self.layout_interner.get_repr(element_layout);
Self::ptr_write(
&mut self.buf,
@ -2958,7 +2959,7 @@ impl<
let temp_sym = Symbol::DEV_TMP5;
let layout = self
.layout_interner
.insert_no_semantic(LayoutRepr::Struct(other_fields));
.insert_direct_no_semantic(LayoutRepr::Struct(other_fields));
self.load_literal_symbols(fields);
self.storage_manager.create_struct(
@ -2995,7 +2996,7 @@ impl<
let temp_sym = Symbol::DEV_TMP5;
let layout = self
.layout_interner
.insert_no_semantic(LayoutRepr::Struct(other_fields));
.insert_direct_no_semantic(LayoutRepr::Struct(other_fields));
self.load_literal_symbols(fields);
self.storage_manager.create_struct(
@ -3042,13 +3043,13 @@ impl<
}
fn load_literal(&mut self, sym: &Symbol, layout: &InLayout<'a>, lit: &Literal<'a>) {
let layout = self.layout_interner.get(*layout);
let layout = self.layout_interner.get_repr(*layout);
if let LayoutRepr::LambdaSet(lambda_set) = layout.repr {
if let LayoutRepr::LambdaSet(lambda_set) = layout {
return self.load_literal(sym, &lambda_set.runtime_representation(), lit);
}
match (lit, layout.repr) {
match (lit, layout) {
(
Literal::Int(x),
LayoutRepr::Builtin(Builtin::Int(
@ -3176,7 +3177,7 @@ impl<
}
fn return_symbol(&mut self, sym: &Symbol, layout: &InLayout<'a>) {
let repr = self.layout_interner.get(*layout).repr;
let repr = self.layout_interner.get_repr(*layout);
if self.storage_manager.is_stored_primitive(sym) {
// Just load it to the correct type of reg as a stand alone value.
match repr {
@ -3547,7 +3548,7 @@ impl<
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
match self.interner().get(*arg_layout).repr {
match self.interner().get_repr(*arg_layout) {
single_register_integers!() => {
let buf = &mut self.buf;
@ -3749,7 +3750,7 @@ impl<
element_in_layout: InLayout<'a>,
dst: Symbol,
) {
match layout_interner.get(element_in_layout).repr {
match layout_interner.get_repr(element_in_layout) {
LayoutRepr::Builtin(builtin) => match builtin {
Builtin::Int(int_width) => match int_width {
IntWidth::I128 | IntWidth::U128 => {
@ -3865,10 +3866,10 @@ impl<
ptr_reg: GeneralReg,
element_offset: i32,
element_width: u64,
element_layout: Layout<'a>,
element_layout: LayoutRepr<'a>,
value: Symbol,
) {
match element_layout.repr {
match element_layout {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
@ -3894,7 +3895,7 @@ impl<
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
}
LayoutRepr::LambdaSet(lambda_set) => {
let layout = layout_interner.get(lambda_set.runtime_representation());
let repr = layout_interner.get_repr(lambda_set.runtime_representation());
Self::ptr_write(
buf,
@ -3903,7 +3904,7 @@ impl<
ptr_reg,
element_offset,
element_width,
layout,
repr,
value,
);
}

View file

@ -665,7 +665,7 @@ impl<
let mut in_layout = *layout;
let layout = loop {
match layout_interner.get(in_layout).repr {
match layout_interner.get_repr(in_layout) {
LayoutRepr::LambdaSet(inner) => in_layout = inner.runtime_representation(),
other => break other,
}
@ -728,7 +728,7 @@ impl<
sym: &Symbol,
layout: &InLayout<'a>,
) {
match layout_interner.get(*layout).repr {
match layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(builtin) => match builtin {
Builtin::Int(int_width) => match int_width {
IntWidth::I128 | IntWidth::U128 => {
@ -1104,7 +1104,7 @@ impl<
symbol: Symbol,
layout: InLayout<'a>,
) {
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
single_register_layouts!() | pointer_layouts!() => {
let base_offset = self.claim_stack_size(8);
self.symbol_storage_map.insert(
@ -1169,7 +1169,7 @@ impl<
layout: InLayout<'a>,
base_offset: i32,
) {
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
single_register_integers!() | pointer_layouts!() => {
let reg = self.load_to_general_reg(buf, &symbol);
ASM::mov_base32_reg64(buf, base_offset, reg);
@ -1491,7 +1491,7 @@ impl<
}
fn is_primitive(layout_interner: &mut STLayoutInterner<'_>, layout: InLayout<'_>) -> bool {
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
single_register_layouts!() => true,
pointer_layouts!() => true,
LayoutRepr::LambdaSet(lambda_set) => {

View file

@ -346,7 +346,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
sym: &Symbol,
layout: &InLayout<'a>,
) {
match layout_interner.get(*layout).repr {
match layout_interner.get_repr(*layout) {
single_register_layouts!() => {
internal_error!("single register layouts are not complex symbols");
}
@ -404,7 +404,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
sym: &Symbol,
layout: &InLayout<'a>,
) {
match layout_interner.get(*layout).repr {
match layout_interner.get_repr(*layout) {
single_register_layouts!() => {
internal_error!("single register layouts are not complex symbols");
}
@ -459,7 +459,7 @@ impl X64_64SystemVStoreArgs {
sym: Symbol,
in_layout: InLayout<'a>,
) {
match layout_interner.get(in_layout).repr {
match layout_interner.get_repr(in_layout) {
single_register_integers!() => self.store_arg_general(buf, storage_manager, sym),
pointer_layouts!() => self.store_arg_general(buf, storage_manager, sym),
single_register_floats!() => self.store_arg_float(buf, storage_manager, sym),
@ -654,7 +654,7 @@ impl X64_64SystemVLoadArgs {
in_layout: InLayout<'a>,
) {
let stack_size = layout_interner.stack_size(in_layout);
match layout_interner.get(in_layout).repr {
match layout_interner.get_repr(in_layout) {
single_register_integers!() => self.load_arg_general(storage_manager, sym),
pointer_layouts!() => self.load_arg_general(storage_manager, sym),
single_register_floats!() => self.load_arg_float(storage_manager, sym),
@ -885,7 +885,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
}
for (layout, sym) in args.iter() {
match layout_interner.get(*layout).repr {
match layout_interner.get_repr(*layout) {
single_register_integers!() => {
match Self::GENERAL_PARAM_REGS.get(general_registers_used) {
Some(reg) => {
@ -946,7 +946,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
let mut float_registers_used = 0;
for (sym, layout) in args.iter().zip(arg_layouts.iter()) {
match layout_interner.get(*layout).repr {
match layout_interner.get_repr(*layout) {
single_register_integers!() => {
match Self::GENERAL_PARAM_REGS.get(general_registers_used) {
Some(reg) => {

View file

@ -360,7 +360,7 @@ trait Backend<'a> {
}
fn list_argument(&mut self, list_layout: InLayout<'a>) -> ListArgument<'a> {
let element_layout = match self.interner().get(list_layout).repr {
let element_layout = match self.interner().get_repr(list_layout) {
LayoutRepr::Builtin(Builtin::List(e)) => e,
_ => unreachable!(),
};
@ -384,7 +384,7 @@ trait Backend<'a> {
fn increment_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
let box_layout = self
.interner_mut()
.insert_no_semantic(LayoutRepr::Boxed(layout));
.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
let element_increment = self.debug_symbol("element_increment");
let element_increment_symbol = self.build_indirect_inc(layout);
@ -404,7 +404,7 @@ trait Backend<'a> {
fn decrement_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
let box_layout = self
.interner_mut()
.insert_no_semantic(LayoutRepr::Boxed(layout));
.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
let element_decrement = self.debug_symbol("element_decrement");
let element_decrement_symbol = self.build_indirect_dec(layout);
@ -801,7 +801,7 @@ trait Backend<'a> {
self.tag(sym, arguments, tag_layout, *tag_id, None);
}
Expr::ExprBox { symbol: value } => {
let element_layout = match self.interner().get(*layout).repr {
let element_layout = match self.interner().get_repr(*layout) {
LayoutRepr::Boxed(boxed) => boxed,
_ => unreachable!("{:?}", self.interner().dbg(*layout)),
};
@ -1030,7 +1030,7 @@ trait Backend<'a> {
);
self.build_num_sub_wrap(sym, &args[0], &args[1], ret_layout)
}
LowLevel::NumSubSaturated => match self.interner().get(*ret_layout).repr {
LowLevel::NumSubSaturated => match self.interner().get_repr(*ret_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
sym,
bitcode::NUM_SUB_SATURATED_INT[int_width].to_string(),
@ -1053,7 +1053,7 @@ trait Backend<'a> {
},
LowLevel::NumBitwiseAnd => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
self.interner().get_repr(*ret_layout)
{
self.build_int_bitwise_and(sym, &args[0], &args[1], int_width)
} else {
@ -1062,7 +1062,7 @@ trait Backend<'a> {
}
LowLevel::NumBitwiseOr => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
self.interner().get_repr(*ret_layout)
{
self.build_int_bitwise_or(sym, &args[0], &args[1], int_width)
} else {
@ -1071,7 +1071,7 @@ trait Backend<'a> {
}
LowLevel::NumBitwiseXor => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
self.interner().get_repr(*ret_layout)
{
self.build_int_bitwise_xor(sym, &args[0], &args[1], int_width)
} else {
@ -1079,14 +1079,14 @@ trait Backend<'a> {
}
}
LowLevel::And => {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get(*ret_layout).repr {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get_repr(*ret_layout) {
self.build_int_bitwise_and(sym, &args[0], &args[1], IntWidth::U8)
} else {
internal_error!("bitwise and on a non-integer")
}
}
LowLevel::Or => {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get(*ret_layout).repr {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get_repr(*ret_layout) {
self.build_int_bitwise_or(sym, &args[0], &args[1], IntWidth::U8)
} else {
internal_error!("bitwise or on a non-integer")
@ -1094,7 +1094,7 @@ trait Backend<'a> {
}
LowLevel::NumShiftLeftBy => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
self.interner().get_repr(*ret_layout)
{
self.build_int_shift_left(sym, &args[0], &args[1], int_width)
} else {
@ -1103,7 +1103,7 @@ trait Backend<'a> {
}
LowLevel::NumShiftRightBy => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
self.interner().get_repr(*ret_layout)
{
self.build_int_shift_right(sym, &args[0], &args[1], int_width)
} else {
@ -1112,7 +1112,7 @@ trait Backend<'a> {
}
LowLevel::NumShiftRightZfBy => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
self.interner().get_repr(*ret_layout)
{
self.build_int_shift_right_zero_fill(sym, &args[0], &args[1], int_width)
} else {
@ -1523,13 +1523,13 @@ trait Backend<'a> {
ret_layout,
),
LowLevel::StrToNum => {
let number_layout = match self.interner().get(*ret_layout).repr {
let number_layout = match self.interner().get_repr(*ret_layout) {
LayoutRepr::Struct(field_layouts) => field_layouts[0], // TODO: why is it sometimes a struct?
_ => unreachable!(),
};
// match on the return layout to figure out which zig builtin we need
let intrinsic = match self.interner().get(number_layout).repr {
let intrinsic = match self.interner().get_repr(number_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
&bitcode::STR_TO_FLOAT[float_width]
@ -1549,7 +1549,7 @@ trait Backend<'a> {
self.build_ptr_cast(sym, &args[0])
}
LowLevel::PtrWrite => {
let element_layout = match self.interner().get(*ret_layout).repr {
let element_layout = match self.interner().get_repr(*ret_layout) {
LayoutRepr::Boxed(boxed) => boxed,
_ => unreachable!("cannot write to {:?}", self.interner().dbg(*ret_layout)),
};
@ -1600,7 +1600,7 @@ trait Backend<'a> {
),
LowLevel::NumToStr => {
let arg_layout = arg_layouts[0];
let intrinsic = match self.interner().get(arg_layout).repr {
let intrinsic = match self.interner().get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => &bitcode::STR_FROM_INT[width],
LayoutRepr::Builtin(Builtin::Float(width)) => &bitcode::STR_FROM_FLOAT[width],
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_TO_STR,
@ -1614,12 +1614,12 @@ trait Backend<'a> {
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout);
}
LowLevel::NumIntCast => {
let source_width = match self.interner().get(arg_layouts[0]).repr {
let source_width = match self.interner().get_repr(arg_layouts[0]) {
LayoutRepr::Builtin(Builtin::Int(width)) => width,
_ => unreachable!(),
};
let target_width = match self.interner().get(*ret_layout).repr {
let target_width = match self.interner().get_repr(*ret_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => width,
_ => unreachable!(),
};

View file

@ -464,7 +464,7 @@ fn build_exposed_generic_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<'
let box_layout = backend
.interner_mut()
.insert_no_semantic(roc_mono::layout::LayoutRepr::Boxed(proc.ret_layout));
.insert_direct_no_semantic(roc_mono::layout::LayoutRepr::Boxed(proc.ret_layout));
let mut args = bumpalo::collections::Vec::new_in(arena);
args.extend(proc.args);

View file

@ -610,7 +610,7 @@ pub fn build_compare_wrapper<'a, 'ctx>(
let closure_data_repr = closure_data_layout.runtime_representation();
let arguments_cast = match layout_interner.get(closure_data_repr).repr {
let arguments_cast = match layout_interner.get_repr(closure_data_repr) {
LayoutRepr::Struct(&[]) => {
// nothing to add
&default

View file

@ -783,7 +783,7 @@ pub fn build_exp_literal<'a, 'ctx>(
use roc_mono::ir::Literal::*;
match literal {
Int(bytes) => match layout_interner.get(layout).repr {
Int(bytes) => match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Bool) => env
.context
.bool_type()
@ -797,7 +797,7 @@ pub fn build_exp_literal<'a, 'ctx>(
U128(bytes) => const_u128(env, u128::from_ne_bytes(*bytes)).into(),
Float(float) => match layout_interner.get(layout).repr {
Float(float) => match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
float_with_precision(env, *float, float_width)
}
@ -1178,7 +1178,7 @@ pub fn build_exp_expr<'a, 'ctx>(
let tag_ptr = tag_ptr.into_pointer_value();
// reset is only generated for union values
let union_layout = match layout_interner.get(layout).repr {
let union_layout = match layout_interner.get_repr(layout) {
LayoutRepr::Union(ul) => ul,
_ => unreachable!(),
};
@ -1323,7 +1323,7 @@ pub fn build_exp_expr<'a, 'ctx>(
} => {
let (value, layout) = load_symbol_and_layout(scope, structure);
let layout = if let LayoutRepr::LambdaSet(lambda_set) = layout_interner.get(layout).repr
let layout = if let LayoutRepr::LambdaSet(lambda_set) = layout_interner.get_repr(layout)
{
lambda_set.runtime_representation()
} else {
@ -1331,7 +1331,7 @@ pub fn build_exp_expr<'a, 'ctx>(
};
// extract field from a record
match (value, layout_interner.get(layout).repr) {
match (value, layout_interner.get_repr(layout)) {
(StructValue(argument), LayoutRepr::Struct(field_layouts)) => {
debug_assert!(!field_layouts.is_empty());
@ -1385,8 +1385,8 @@ pub fn build_exp_expr<'a, 'ctx>(
let field_layouts = tag_layouts[*tag_id as usize];
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_layout = layout_interner
.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
let opaque_data_ptr = env
@ -1442,8 +1442,8 @@ pub fn build_exp_expr<'a, 'ctx>(
)
}
UnionLayout::NonNullableUnwrapped(field_layouts) => {
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_layout = layout_interner
.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
let target_loaded_type = basic_type_from_layout(env, layout_interner, layout);
@ -1493,8 +1493,8 @@ pub fn build_exp_expr<'a, 'ctx>(
debug_assert_ne!(*tag_id != 0, *nullable_id);
let field_layouts = other_fields;
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_layout = layout_interner
.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
let target_loaded_type = basic_type_from_layout(env, layout_interner, layout);
@ -1625,7 +1625,7 @@ fn build_tag_field_value<'a, 'ctx>(
value: BasicValueEnum<'ctx>,
tag_field_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
if let LayoutRepr::RecursivePointer(_) = layout_interner.get(tag_field_layout).repr {
if let LayoutRepr::RecursivePointer(_) = layout_interner.get_repr(tag_field_layout) {
debug_assert!(value.is_pointer_value());
// we store recursive pointers as `i64*`
@ -1696,7 +1696,10 @@ fn build_struct<'a, 'ctx>(
// Zero-sized fields have no runtime representation.
// The layout of the struct expects them to be dropped!
let (field_expr, field_layout) = load_symbol_and_layout(scope, symbol);
if !layout_interner.get(field_layout).is_dropped_because_empty() {
if !layout_interner
.get_repr(field_layout)
.is_dropped_because_empty()
{
let field_type = basic_type_from_layout(env, layout_interner, field_layout);
field_types.push(field_type);
@ -1780,8 +1783,8 @@ fn build_tag<'a, 'ctx>(
use std::cmp::Ordering::*;
match tag_id.cmp(&(*nullable_id as _)) {
Equal => {
let layout =
layout_interner.insert_no_semantic(LayoutRepr::Union(*union_layout));
let layout = layout_interner
.insert_direct_no_semantic(LayoutRepr::Union(*union_layout));
return basic_type_from_layout(env, layout_interner, layout)
.into_pointer_type()
@ -2133,7 +2136,8 @@ fn lookup_at_index_ptr2<'a, 'ctx>(
) -> BasicValueEnum<'ctx> {
let builder = env.builder;
let struct_layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let struct_type =
basic_type_from_layout(env, layout_interner, struct_layout).into_struct_type();
@ -2545,7 +2549,7 @@ pub fn build_exp_stmt<'a, 'ctx>(
for (symbol, expr, layout) in queue {
debug_assert!(!matches!(
layout_interner.get(*layout).repr,
layout_interner.get_repr(*layout),
LayoutRepr::RecursivePointer(_)
));
@ -2845,12 +2849,12 @@ pub fn build_exp_stmt<'a, 'ctx>(
DecRef(symbol) => {
let (value, layout) = load_symbol_and_layout(scope, symbol);
let lay = layout_interner.get(layout);
match lay.repr {
let lay = layout_interner.get_repr(layout);
match lay {
LayoutRepr::Builtin(Builtin::Str) => todo!(),
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
debug_assert!(value.is_struct_value());
let element_layout = layout_interner.get(element_layout);
let element_layout = layout_interner.get_repr(element_layout);
let alignment =
element_layout.alignment_bytes(layout_interner, env.target_info);
@ -2859,7 +2863,7 @@ pub fn build_exp_stmt<'a, 'ctx>(
_ if lay.is_refcounted() => {
if value.is_pointer_value() {
let value_ptr = match lay.repr {
let value_ptr = match lay {
LayoutRepr::Union(union_layout)
if union_layout
.stores_tag_id_in_pointer(env.target_info) =>
@ -3437,7 +3441,7 @@ fn build_switch_ir<'a, 'ctx>(
let cont_block = context.append_basic_block(parent, "cont");
// Build the condition
let cond = match layout_interner.get(cond_layout).repr {
let cond = match layout_interner.get_repr(cond_layout) {
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
// float matches are done on the bit pattern
cond_layout = Layout::float_width(float_width);
@ -3463,7 +3467,7 @@ fn build_switch_ir<'a, 'ctx>(
// Build the cases
let mut incoming = Vec::with_capacity_in(branches.len(), arena);
if let LayoutRepr::Builtin(Builtin::Bool) = layout_interner.get(cond_layout).repr {
if let LayoutRepr::Builtin(Builtin::Bool) = layout_interner.get_repr(cond_layout) {
match (branches, default_branch) {
([(0, _, false_branch)], true_branch) | ([(1, _, true_branch)], false_branch) => {
let then_block = context.append_basic_block(parent, "then_block");
@ -3764,7 +3768,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
builder.position_at_end(entry);
let wrapped_layout = layout_interner.insert_no_semantic(roc_call_result_layout(
let wrapped_layout = layout_interner.insert_direct_no_semantic(roc_call_result_layout(
env.arena,
return_layout,
env.target_info,
@ -3871,7 +3875,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
// the C and Fast calling conventions agree
arguments_for_call.push(*arg);
} else {
match layout_interner.get(*layout).repr {
match layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::List(_)) => {
let list_type = arg_type
.into_pointer_type()
@ -3905,7 +3909,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
builder.position_at_end(last_block);
let wrapper_result = layout_interner.insert_no_semantic(LayoutRepr::struct_(
let wrapper_result = layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(
env.arena.alloc([Layout::U64, return_layout]),
));
@ -4010,7 +4014,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
};
for (i, layout) in arguments.iter().enumerate() {
if let LayoutRepr::Builtin(Builtin::Str) = layout_interner.get(*layout).repr {
if let LayoutRepr::Builtin(Builtin::Str) = layout_interner.get_repr(*layout) {
// Indicate to LLVM that this argument is semantically passed by-value
// even though technically (because of its size) it is passed by-reference
let byval_attribute_id = Attribute::get_named_enum_kind_id("byval");
@ -4110,7 +4114,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
env.target_info.architecture,
roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64
) {
let c_abi_type = match layout_interner.get(*layout).repr {
let c_abi_type = match layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Str | Builtin::List(_)) => {
c_abi_roc_str_type
}
@ -5679,7 +5683,7 @@ fn to_cc_type<'a, 'ctx>(
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> BasicTypeEnum<'ctx> {
match layout_interner.runtime_representation(layout).repr {
match layout_interner.runtime_representation(layout) {
LayoutRepr::Builtin(builtin) => to_cc_type_builtin(env, &builtin),
_ => {
// TODO this is almost certainly incorrect for bigger structs
@ -5726,7 +5730,7 @@ impl RocReturn {
target_info: TargetInfo,
layout: InLayout,
) -> bool {
match interner.get(layout).repr {
match interner.get_repr(layout) {
LayoutRepr::Builtin(builtin) => {
use Builtin::*;

View file

@ -154,7 +154,7 @@ fn build_eq<'a, 'ctx>(
rhs_layout
);
match layout_interner.get(*lhs_layout).repr {
match layout_interner.get_repr(*lhs_layout) {
LayoutRepr::Builtin(builtin) => build_eq_builtin(
env,
layout_interner,
@ -215,7 +215,7 @@ fn build_eq<'a, 'ctx>(
"i64_to_opaque",
);
let union_layout = match layout_interner.get(rec_layout).repr {
let union_layout = match layout_interner.get_repr(rec_layout) {
LayoutRepr::Union(union_layout) => {
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
union_layout
@ -342,7 +342,7 @@ fn build_neq<'a, 'ctx>(
);
}
match layout_interner.get(lhs_layout).repr {
match layout_interner.get_repr(lhs_layout) {
LayoutRepr::Builtin(builtin) => build_neq_builtin(
env,
layout_interner,
@ -425,7 +425,7 @@ fn build_list_eq<'a, 'ctx>(
let symbol = Symbol::LIST_EQ;
let element_layout =
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get(element_layout).repr {
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get_repr(element_layout) {
rec
} else {
element_layout
@ -742,10 +742,10 @@ fn build_struct_eq_help<'a, 'ctx>(
.unwrap();
let are_equal = if let LayoutRepr::RecursivePointer(rec_layout) =
layout_interner.get(*field_layout).repr
layout_interner.get_repr(*field_layout)
{
debug_assert!(
matches!(layout_interner.get(rec_layout).repr, LayoutRepr::Union(union_layout) if !matches!(union_layout, UnionLayout::NonRecursive(..)))
matches!(layout_interner.get_repr(rec_layout), LayoutRepr::Union(union_layout) if !matches!(union_layout, UnionLayout::NonRecursive(..)))
);
let field_layout = rec_layout;
@ -973,7 +973,7 @@ fn build_tag_eq_help<'a, 'ctx>(
env.builder.position_at_end(block);
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let answer = eq_ptr_to_struct(
env,
@ -1046,7 +1046,7 @@ fn build_tag_eq_help<'a, 'ctx>(
env.builder.position_at_end(block);
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let answer = eq_ptr_to_struct(
env,
@ -1109,7 +1109,7 @@ fn build_tag_eq_help<'a, 'ctx>(
env.builder.position_at_end(compare_other);
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(other_fields));
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(other_fields));
let answer = eq_ptr_to_struct(
env,
@ -1214,7 +1214,7 @@ fn build_tag_eq_help<'a, 'ctx>(
env.builder.position_at_end(block);
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let answer = eq_ptr_to_struct(
env,
@ -1255,7 +1255,7 @@ fn build_tag_eq_help<'a, 'ctx>(
env.builder.position_at_end(compare_fields);
let struct_layout =
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let answer = eq_ptr_to_struct(
env,

View file

@ -36,7 +36,7 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
) -> BasicTypeEnum<'ctx> {
use LayoutRepr::*;
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
Struct(sorted_fields, ..) => basic_type_from_record(env, layout_interner, sorted_fields),
LambdaSet(lambda_set) => {
basic_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
@ -150,7 +150,7 @@ pub fn argument_type_from_layout<'a, 'ctx>(
) -> BasicTypeEnum<'ctx> {
use LayoutRepr::*;
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
LambdaSet(lambda_set) => {
argument_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
}

View file

@ -296,7 +296,7 @@ fn build_clone<'a, 'ctx>(
value: BasicValueEnum<'ctx>,
layout: InLayout<'a>,
) -> IntValue<'ctx> {
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(builtin) => build_clone_builtin(
env,
layout_interner,
@ -396,7 +396,7 @@ fn build_clone<'a, 'ctx>(
"i64_to_opaque",
);
let union_layout = match layout_interner.get(rec_layout).repr {
let union_layout = match layout_interner.get_repr(rec_layout) {
LayoutRepr::Union(union_layout) => {
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
union_layout
@ -476,7 +476,7 @@ fn build_clone_tag<'a, 'ctx>(
value: BasicValueEnum<'ctx>,
union_layout: UnionLayout<'a>,
) -> IntValue<'ctx> {
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let layout_id = layout_ids.get(Symbol::CLONE, &layout);
let fn_name = layout_id.to_symbol_string(Symbol::CLONE, &env.interns);
@ -690,7 +690,7 @@ fn build_clone_tag_help<'a, 'ctx>(
// load the tag payload (if any)
let payload_layout = LayoutRepr::struct_(field_layouts);
let payload_in_layout = layout_interner.insert_no_semantic(payload_layout);
let payload_in_layout = layout_interner.insert_direct_no_semantic(payload_layout);
let opaque_payload_ptr = env
.builder
@ -748,11 +748,12 @@ fn build_clone_tag_help<'a, 'ctx>(
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
let layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let layout = if union_layout.stores_tag_id_in_pointer(env.target_info) {
layout
} else {
layout_interner.insert_no_semantic(LayoutRepr::struct_(
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(
env.arena.alloc([layout, union_layout.tag_id_layout()]),
))
};
@ -797,7 +798,7 @@ fn build_clone_tag_help<'a, 'ctx>(
build_copy(env, ptr, offset, extra_offset.into());
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(fields));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(fields));
let basic_type = basic_type_from_layout(env, layout_interner, layout);
let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info);
@ -853,7 +854,8 @@ fn build_clone_tag_help<'a, 'ctx>(
other_tags[i]
};
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(fields));
let layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(fields));
let basic_type = basic_type_from_layout(env, layout_interner, layout);
let (width, _) =
@ -928,7 +930,8 @@ fn build_clone_tag_help<'a, 'ctx>(
// write the "pointer" af the current offset
build_copy(env, ptr, offset, extra_offset.into());
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(other_fields));
let layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(other_fields));
let basic_type = basic_type_from_layout(env, layout_interner, layout);
let cursors = Cursors {

View file

@ -200,13 +200,13 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// Str.toNum : Str -> Result (Num *) {}
arguments!(string);
let number_layout = match layout_interner.get(layout).repr {
let number_layout = match layout_interner.get_repr(layout) {
LayoutRepr::Struct(field_layouts) => field_layouts[0], // TODO: why is it sometimes a struct?
_ => unreachable!(),
};
// match on the return layout to figure out which zig builtin we need
let intrinsic = match layout_interner.get(number_layout).repr {
let intrinsic = match layout_interner.get_repr(number_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
&bitcode::STR_TO_FLOAT[float_width]
@ -229,7 +229,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
intrinsic,
),
None => {
let return_type_name = match layout_interner.get(number_layout).repr {
let return_type_name = match layout_interner.get_repr(number_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
int_width.type_name()
}
@ -279,7 +279,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
}
}
PtrWidth::Bytes8 => {
let cc_return_by_pointer = match layout_interner.get(number_layout).repr {
let cc_return_by_pointer = match layout_interner.get_repr(number_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
(int_width.stack_size() as usize > env.target_info.ptr_size())
.then_some(int_width.type_name())
@ -325,7 +325,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let (int, int_layout) = load_symbol_and_layout(scope, &args[0]);
let int = int.into_int_value();
let int_width = match layout_interner.get(int_layout).repr {
let int_width = match layout_interner.get_repr(int_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
_ => unreachable!(),
};
@ -344,7 +344,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
let float_width = match layout_interner.get(float_layout).repr {
let float_width = match layout_interner.get_repr(float_layout) {
LayoutRepr::Builtin(Builtin::Float(float_width)) => float_width,
_ => unreachable!(),
};
@ -854,7 +854,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// Num.toStr : Num a -> Str
arguments_with_layouts!((num, num_layout));
match layout_interner.get(num_layout).repr {
match layout_interner.get_repr(num_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
let int = num.into_int_value();
@ -869,7 +869,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
LayoutRepr::Builtin(Builtin::Float(_float_width)) => {
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
let float_width = match layout_interner.get(float_layout).repr {
let float_width = match layout_interner.get_repr(float_layout) {
LayoutRepr::Builtin(Builtin::Float(float_width)) => float_width,
_ => unreachable!(),
};
@ -908,7 +908,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
| NumCountOneBits => {
arguments_with_layouts!((arg, arg_layout));
match layout_interner.get(arg_layout).repr {
match layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(arg_builtin) => {
use roc_mono::layout::Builtin::*;
@ -996,8 +996,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
use inkwell::FloatPredicate;
match (
layout_interner.get(lhs_layout).repr,
layout_interner.get(rhs_layout).repr,
layout_interner.get_repr(lhs_layout),
layout_interner.get_repr(rhs_layout),
) {
(LayoutRepr::Builtin(lhs_builtin), LayoutRepr::Builtin(rhs_builtin))
if lhs_builtin == rhs_builtin =>
@ -1152,7 +1152,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
NumToFloatCast => {
arguments_with_layouts!((arg, arg_layout));
match layout_interner.get(arg_layout).repr {
match layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => {
// Converting from int to float
let int_val = arg.into_int_value();
@ -1291,7 +1291,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
"cast_to_i8_ptr",
);
let value_ptr = match layout_interner.get(data_layout).repr {
let value_ptr = match layout_interner.get_repr(data_layout) {
LayoutRepr::Union(union_layout)
if union_layout.stores_tag_id_in_pointer(env.target_info) =>
{
@ -1562,8 +1562,8 @@ pub fn build_num_binop<'a, 'ctx>(
op: LowLevel,
) -> BasicValueEnum<'ctx> {
match (
layout_interner.get(lhs_layout).repr,
layout_interner.get(rhs_layout).repr,
layout_interner.get_repr(lhs_layout),
layout_interner.get_repr(rhs_layout),
) {
(LayoutRepr::Builtin(lhs_builtin), LayoutRepr::Builtin(rhs_builtin))
if lhs_builtin == rhs_builtin =>
@ -2031,7 +2031,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
NumToFrac => {
// This is an Int, so we need to convert it.
let target_float_type = match layout_interner.get(return_layout).repr {
let target_float_type = match layout_interner.get_repr(return_layout) {
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
convert::float_type_from_float_width(env, float_width)
}
@ -2048,7 +2048,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
NumToIntChecked => {
// return_layout : Result N [OutOfBounds]* ~ { result: N, out_of_bounds: bool }
let target_int_width = match layout_interner.get(return_layout).repr {
let target_int_width = match layout_interner.get_repr(return_layout) {
LayoutRepr::Struct(field_layouts) if field_layouts.len() == 2 => {
debug_assert!(layout_interner.eq_repr(field_layouts[1], Layout::BOOL));
field_layouts[0].to_int_width()
@ -2328,7 +2328,7 @@ fn build_float_unary_op<'a, 'ctx>(
NumSqrtUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_SQRT[float_width]),
NumLogUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_LOG[float_width]),
NumToFrac => {
let return_width = match layout_interner.get(layout).repr {
let return_width = match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Float(return_width)) => return_width,
_ => internal_error!("Layout for returning is not Float : {:?}", layout),
};
@ -2350,7 +2350,7 @@ fn build_float_unary_op<'a, 'ctx>(
}
}
NumCeiling => {
let int_width = match layout_interner.get(layout).repr {
let int_width = match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
};
@ -2364,7 +2364,7 @@ fn build_float_unary_op<'a, 'ctx>(
}
}
NumFloor => {
let int_width = match layout_interner.get(layout).repr {
let int_width = match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
_ => internal_error!("Floor return layout is not int: {:?}", layout),
};
@ -2378,7 +2378,7 @@ fn build_float_unary_op<'a, 'ctx>(
}
}
NumRound => {
let int_width = match layout_interner.get(layout).repr {
let int_width = match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
_ => internal_error!("Round return layout is not int: {:?}", layout),
};
@ -2465,8 +2465,8 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list_layout).repr,
layout_interner.get(return_layout).repr,
layout_interner.get_repr(list_layout),
layout_interner.get_repr(return_layout),
) {
(
LayoutRepr::Builtin(Builtin::List(element_layout)),
@ -2505,9 +2505,9 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list1_layout).repr,
layout_interner.get(list2_layout).repr,
layout_interner.get(return_layout).repr,
layout_interner.get_repr(list1_layout),
layout_interner.get_repr(list2_layout),
layout_interner.get_repr(return_layout),
) {
(
LayoutRepr::Builtin(Builtin::List(element1_layout)),
@ -2551,10 +2551,10 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list1_layout).repr,
layout_interner.get(list2_layout).repr,
layout_interner.get(list3_layout).repr,
layout_interner.get(return_layout).repr,
layout_interner.get_repr(list1_layout),
layout_interner.get_repr(list2_layout),
layout_interner.get_repr(list3_layout),
layout_interner.get_repr(return_layout),
) {
(
LayoutRepr::Builtin(Builtin::List(element1_layout)),
@ -2602,11 +2602,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list1_layout).repr,
layout_interner.get(list2_layout).repr,
layout_interner.get(list3_layout).repr,
layout_interner.get(list4_layout).repr,
layout_interner.get(return_layout).repr,
layout_interner.get_repr(list1_layout),
layout_interner.get_repr(list2_layout),
layout_interner.get_repr(list3_layout),
layout_interner.get_repr(list4_layout),
layout_interner.get_repr(return_layout),
) {
(
LayoutRepr::Builtin(Builtin::List(element1_layout)),
@ -2659,7 +2659,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match layout_interner.get(list_layout).repr {
match layout_interner.get_repr(list_layout) {
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
use crate::llvm::bitcode::build_compare_wrapper;
@ -2710,7 +2710,7 @@ fn load_symbol_and_lambda_set<'a, 'ctx>(
) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) {
match scope
.get(symbol)
.map(|(l, v)| (layout_interner.get(*l).repr, v))
.map(|(l, v)| (layout_interner.get_repr(*l), v))
{
Some((LayoutRepr::LambdaSet(lambda_set), ptr)) => (*ptr, lambda_set),
Some((other, ptr)) => panic!("Not a lambda set: {:?}, {:?}", other, ptr),

View file

@ -267,7 +267,7 @@ fn modify_refcount_struct<'a, 'ctx>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(layouts));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(layouts));
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -470,7 +470,7 @@ fn modify_refcount_layout_help<'a, 'ctx>(
None => return,
};
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
LayoutRepr::RecursivePointer(rec_layout) => {
let layout = rec_layout;
@ -527,7 +527,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx>(
) -> Option<FunctionValue<'ctx>> {
use LayoutRepr::*;
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
Builtin(builtin) => {
modify_refcount_builtin(env, layout_interner, layout_ids, mode, layout, &builtin)
}
@ -603,14 +603,14 @@ fn modify_refcount_list<'a, 'ctx>(
let di_location = env.builder.get_current_debug_location().unwrap();
let element_layout =
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get(element_layout).repr {
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get_repr(element_layout) {
rec
} else {
element_layout
};
let list_layout =
layout_interner.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(element_layout)));
let list_layout = layout_interner
.insert_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(element_layout)));
let (_, fn_name) = function_name_from_mode(
layout_ids,
&env.interns,
@ -859,7 +859,7 @@ fn modify_refcount_boxed<'a, 'ctx>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let boxed_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(inner_layout));
let boxed_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(inner_layout));
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -921,7 +921,7 @@ fn modify_refcount_box_help<'a, 'ctx>(
let boxed = arg_val.into_pointer_value();
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
let call_mode = mode_to_call_mode(fn_val, mode);
let boxed_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(inner_layout));
let boxed_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(inner_layout));
match mode {
Mode::Inc => {
@ -1065,7 +1065,7 @@ fn build_rec_union<'a, 'ctx>(
mode: Mode,
union_layout: UnionLayout<'a>,
) -> FunctionValue<'ctx> {
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -1168,7 +1168,7 @@ fn build_rec_union_help<'a, 'ctx>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr);
let call_mode = mode_to_call_mode(fn_val, mode);
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
match mode {
Mode::Inc => {
@ -1223,7 +1223,7 @@ enum DecOrReuse {
fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[InLayout]) -> bool {
!field_layouts.iter().any(|x| {
let x = interner.get(*x);
let x = interner.get_repr(*x);
x.is_refcounted() || x.contains_refcounted(interner)
})
}
@ -1274,7 +1274,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
env.builder.position_at_end(block);
let fields_struct = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
let fields_struct =
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let wrapper_type = basic_type_from_layout(env, layout_interner, fields_struct);
// cast the opaque pointer to a pointer of the correct shape
@ -1290,7 +1291,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
let mut deferred_nonrec = Vec::new_in(env.arena);
for (i, field_layout) in field_layouts.iter().enumerate() {
if let LayoutRepr::RecursivePointer(_) = layout_interner.get(*field_layout).repr {
if let LayoutRepr::RecursivePointer(_) = layout_interner.get_repr(*field_layout) {
// this field has type `*i64`, but is really a pointer to the data we want
let elem_pointer = env
.builder
@ -1312,7 +1313,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
// therefore we must cast it to our desired type
let union_layout =
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let union_type = basic_type_from_layout(env, layout_interner, union_layout);
let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type);
@ -1351,7 +1352,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
DecOrReuse::Reuse => {}
DecOrReuse::Dec => {
let union_layout =
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
}
}
@ -1410,7 +1411,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
// increment/decrement the cons-cell itself
if let DecOrReuse::Dec = decrement_or_reuse {
let union_layout =
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
}
}
@ -1470,7 +1471,8 @@ pub fn build_reset<'a, 'ctx>(
) -> FunctionValue<'ctx> {
let mode = Mode::Dec;
let union_layout_in = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let union_layout_in =
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let layout_id = layout_ids.get(Symbol::DEC, &union_layout_in);
let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns);
let fn_name = format!("{}_reset", fn_name);
@ -1566,7 +1568,7 @@ fn build_reuse_rec_union_help<'a, 'ctx>(
env.builder.position_at_end(should_recurse_block);
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let do_recurse_block = env.context.append_basic_block(parent, "do_recurse");
let no_recurse_block = env.context.append_basic_block(parent, "no_recurse");
@ -1628,7 +1630,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx>(
fields: &'a [&'a [InLayout<'a>]],
) -> FunctionValue<'ctx> {
let union_layout = UnionLayout::NonRecursive(fields);
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
@ -1698,7 +1700,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
let before_block = env.builder.get_insert_block().expect("to be in a function");
let union_layout = UnionLayout::NonRecursive(tags);
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let union_struct_type = basic_type_from_layout(env, layout_interner, layout).into_struct_type();
// read the tag_id
@ -1735,7 +1737,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
for (tag_id, field_layouts) in tags.iter().enumerate() {
// if none of the fields are or contain anything refcounted, just move on
if !field_layouts.iter().any(|x| {
let x = layout_interner.get(*x);
let x = layout_interner.get_repr(*x);
x.is_refcounted() || x.contains_refcounted(layout_interner)
}) {
continue;
@ -1744,7 +1746,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
let block = env.context.append_basic_block(parent, "tag_id_modify");
env.builder.position_at_end(block);
let fields_struct = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
let fields_struct =
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
let data_struct_type = basic_type_from_layout(env, layout_interner, fields_struct);
debug_assert!(data_struct_type.is_struct_type());
@ -1767,7 +1770,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
for (i, field_layout) in field_layouts.iter().enumerate() {
if let LayoutRepr::RecursivePointer(union_layout) =
layout_interner.get(*field_layout).repr
layout_interner.get_repr(*field_layout)
{
// This field is a pointer to the recursive pointer.
let field_ptr = env

View file

@ -507,7 +507,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
let heap_return_ptr_id = LocalId(wrapper_arg_layouts.len() as u32 - 1);
let inner_ret_layout = match wrapper_arg_layouts
.last()
.map(|l| self.layout_interner.get(*l).repr)
.map(|l| self.layout_interner.get_repr(*l))
{
Some(LayoutRepr::Boxed(inner)) => WasmLayout::new(self.layout_interner, inner),
x => internal_error!("Higher-order wrapper: invalid return layout {:?}", x),
@ -539,7 +539,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
continue;
}
let inner_layout = match self.layout_interner.get(*wrapper_arg).repr {
let inner_layout = match self.layout_interner.get_repr(*wrapper_arg) {
LayoutRepr::Boxed(inner) => inner,
x => internal_error!("Expected a Boxed layout, got {:?}", x),
};
@ -558,7 +558,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
if self.layout_interner.stack_size(closure_data_layout) > 0 {
// The closure data exists, and will have been passed in to the wrapper as a
// one-element struct.
let inner_closure_data_layout = match self.layout_interner.get(closure_data_layout).repr
let inner_closure_data_layout = match self.layout_interner.get_repr(closure_data_layout)
{
LayoutRepr::Struct([inner]) => inner,
other => internal_error!(
@ -633,7 +633,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
n_inner_args += 1;
}
let inner_layout = match self.layout_interner.get(value_layout).repr {
let inner_layout = match self.layout_interner.get_repr(value_layout) {
LayoutRepr::Boxed(inner) => inner,
x => internal_error!("Expected a Boxed layout, got {:?}", x),
};
@ -662,7 +662,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
fn dereference_boxed_value(&mut self, inner: InLayout) {
use Align::*;
match self.layout_interner.get(inner).repr {
match self.layout_interner.get_repr(inner) {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
self.code_builder.i32_load8_u(Bytes1, 0);
}
@ -1367,7 +1367,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
arguments,
ret_symbol,
ret_layout,
ret_layout_raw: self.layout_interner.get(ret_layout),
ret_layout_raw: self.layout_interner.get_repr(ret_layout),
ret_storage: ret_storage.to_owned(),
};
low_level_call.generate(self);
@ -1445,7 +1445,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
storage: &StoredValue,
fields: &'a [Symbol],
) {
match self.layout_interner.get(layout).repr {
match self.layout_interner.get_repr(layout) {
LayoutRepr::Struct { .. } => {
match storage {
StoredValue::StackMemory { location, size, .. } => {
@ -1903,7 +1903,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
};
// allocate heap memory and load its data address onto the value stack
let arg_layout = match self.layout_interner.get(layout).repr {
let arg_layout = match self.layout_interner.get_repr(layout) {
LayoutRepr::Boxed(arg) => arg,
_ => internal_error!("ExprBox should always produce a Boxed layout"),
};

View file

@ -47,7 +47,7 @@ impl WasmLayout {
let (size, alignment_bytes) = interner.stack_size_and_alignment(layout);
match interner.get(layout).repr {
match interner.get_repr(layout) {
LayoutRepr::Builtin(Int(int_width)) => {
use IntWidth::*;

View file

@ -126,7 +126,7 @@ pub struct LowLevelCall<'a> {
pub arguments: &'a [Symbol],
pub ret_symbol: Symbol,
pub ret_layout: InLayout<'a>,
pub ret_layout_raw: Layout<'a>,
pub ret_layout_raw: LayoutRepr<'a>,
pub ret_storage: StoredValue,
}
@ -237,14 +237,14 @@ impl<'a> LowLevelCall<'a> {
}
StrGetCapacity => self.load_args_and_call_zig(backend, bitcode::STR_CAPACITY),
StrToNum => {
let number_layout = match backend.layout_interner.get(self.ret_layout).repr {
let number_layout = match backend.layout_interner.get_repr(self.ret_layout) {
LayoutRepr::Struct(field_layouts) => field_layouts[0],
_ => {
internal_error!("Unexpected mono layout {:?} for StrToNum", self.ret_layout)
}
};
// match on the return layout to figure out which zig builtin we need
let intrinsic = match backend.layout_interner.get(number_layout).repr {
let intrinsic = match backend.layout_interner.get_repr(number_layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
&bitcode::STR_TO_FLOAT[float_width]
@ -388,14 +388,13 @@ impl<'a> LowLevelCall<'a> {
};
// Byte offsets of each field in the return struct
let (ret_list_offset, ret_elem_offset, elem_layout) = match self.ret_layout_raw.repr
{
let (ret_list_offset, ret_elem_offset, elem_layout) = match self.ret_layout_raw {
LayoutRepr::Struct(&[f1, f2]) => {
let l1 = backend.layout_interner.get(f1);
let l2 = backend.layout_interner.get(f2);
match (l1.repr, l2.repr) {
let l1 = backend.layout_interner.get_repr(f1);
let l2 = backend.layout_interner.get_repr(f2);
match (l1, l2) {
(LayoutRepr::Builtin(Builtin::List(list_elem)), _)
if l2.repr == backend.layout_interner.get(list_elem).repr =>
if l2 == backend.layout_interner.get_repr(list_elem) =>
{
let list_offset = 0;
let elem_offset = LayoutRepr::Builtin(Builtin::List(list_elem))
@ -403,7 +402,7 @@ impl<'a> LowLevelCall<'a> {
(list_offset, elem_offset, f2)
}
(_, LayoutRepr::Builtin(Builtin::List(list_elem)))
if l1.repr == backend.layout_interner.get(list_elem).repr =>
if l1 == backend.layout_interner.get_repr(list_elem) =>
{
let list_offset =
l1.stack_size(backend.layout_interner, TARGET_INFO);
@ -467,7 +466,7 @@ impl<'a> LowLevelCall<'a> {
let capacity: Symbol = self.arguments[0];
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
let elem_layout = backend.layout_interner.get(elem_layout);
let elem_layout = backend.layout_interner.get_repr(elem_layout);
let (elem_width, elem_align) =
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
@ -506,7 +505,7 @@ impl<'a> LowLevelCall<'a> {
// Load monomorphization constants
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
let elem_layout = backend.layout_interner.get(elem_layout);
let elem_layout = backend.layout_interner.get_repr(elem_layout);
let (elem_width, elem_align) =
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
backend.code_builder.i32_const(elem_align as i32);
@ -522,7 +521,7 @@ impl<'a> LowLevelCall<'a> {
let spare: Symbol = self.arguments[1];
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
let elem_layout = backend.layout_interner.get(elem_layout);
let elem_layout = backend.layout_interner.get_repr(elem_layout);
let (elem_width, elem_align) =
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
@ -563,7 +562,7 @@ impl<'a> LowLevelCall<'a> {
let list: Symbol = self.arguments[0];
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
let elem_layout = backend.layout_interner.get(elem_layout);
let elem_layout = backend.layout_interner.get_repr(elem_layout);
let (elem_width, elem_align) =
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
@ -690,9 +689,12 @@ impl<'a> LowLevelCall<'a> {
// The refcount function receives a pointer to an element in the list
// This is the same as a Struct containing the element
let in_memory_layout = backend
.layout_interner
.insert_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([elem_layout])));
let in_memory_layout =
backend
.layout_interner
.insert_direct_no_semantic(LayoutRepr::Struct(
backend.env.arena.alloc([elem_layout]),
));
let dec_fn = backend.get_refcount_fn_index(in_memory_layout, HelperOp::Dec);
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
@ -735,9 +737,12 @@ impl<'a> LowLevelCall<'a> {
// The refcount function receives a pointer to an element in the list
// This is the same as a Struct containing the element
let in_memory_layout = backend
.layout_interner
.insert_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([elem_layout])));
let in_memory_layout =
backend
.layout_interner
.insert_direct_no_semantic(LayoutRepr::Struct(
backend.env.arena.alloc([elem_layout]),
));
let dec_fn = backend.get_refcount_fn_index(in_memory_layout, HelperOp::Dec);
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
@ -809,7 +814,7 @@ impl<'a> LowLevelCall<'a> {
}
// Num
NumAdd => match self.ret_layout_raw.repr {
NumAdd => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_OR_PANIC_INT[width])
}
@ -829,7 +834,7 @@ impl<'a> LowLevelCall<'a> {
_ => panic_ret_type(),
},
NumAddWrap => match self.ret_layout_raw.repr {
NumAddWrap => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
IntWidth::I128 | IntWidth::U128 => {
// TODO: don't panic
@ -869,7 +874,7 @@ impl<'a> LowLevelCall<'a> {
NumToStr => self.num_to_str(backend),
NumAddChecked => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout).repr {
match backend.layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_CHECKED_INT[width])
}
@ -882,7 +887,7 @@ impl<'a> LowLevelCall<'a> {
x => internal_error!("NumAddChecked is not defined for {:?}", x),
}
}
NumAddSaturated => match self.ret_layout_raw.repr {
NumAddSaturated => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_SATURATED_INT[width])
}
@ -900,7 +905,7 @@ impl<'a> LowLevelCall<'a> {
_ => panic_ret_type(),
},
NumSub => match self.ret_layout_raw.repr {
NumSub => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_OR_PANIC_INT[width])
}
@ -920,7 +925,7 @@ impl<'a> LowLevelCall<'a> {
_ => panic_ret_type(),
},
NumSubWrap => match self.ret_layout_raw.repr {
NumSubWrap => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
IntWidth::I128 | IntWidth::U128 => {
// TODO: don't panic
@ -958,7 +963,7 @@ impl<'a> LowLevelCall<'a> {
},
NumSubChecked => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout).repr {
match backend.layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_CHECKED_INT[width])
}
@ -971,7 +976,7 @@ impl<'a> LowLevelCall<'a> {
x => internal_error!("NumSubChecked is not defined for {:?}", x),
}
}
NumSubSaturated => match self.ret_layout_raw.repr {
NumSubSaturated => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_SATURATED_INT[width])
}
@ -989,7 +994,7 @@ impl<'a> LowLevelCall<'a> {
_ => panic_ret_type(),
},
NumMul => match self.ret_layout_raw.repr {
NumMul => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_OR_PANIC_INT[width])
}
@ -1008,7 +1013,7 @@ impl<'a> LowLevelCall<'a> {
}
_ => panic_ret_type(),
},
NumMulWrap => match self.ret_layout_raw.repr {
NumMulWrap => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
IntWidth::I128 | IntWidth::U128 => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_WRAP_INT[width])
@ -1043,7 +1048,7 @@ impl<'a> LowLevelCall<'a> {
}
_ => panic_ret_type(),
},
NumMulSaturated => match self.ret_layout_raw.repr {
NumMulSaturated => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_SATURATED_INT[width])
}
@ -1063,7 +1068,7 @@ impl<'a> LowLevelCall<'a> {
NumMulChecked => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout).repr {
match backend.layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_CHECKED_INT[width])
}
@ -1245,7 +1250,7 @@ impl<'a> LowLevelCall<'a> {
x => todo!("{:?} for {:?}", self.lowlevel, x),
}
}
NumDivCeilUnchecked => match self.ret_layout_raw.repr {
NumDivCeilUnchecked => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_DIV_CEIL[width])
}
@ -1456,13 +1461,13 @@ impl<'a> LowLevelCall<'a> {
_ => todo!("{:?} for {:?}", self.lowlevel, self.ret_layout),
}
}
NumSin => match self.ret_layout_raw.repr {
NumSin => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SIN[width]);
}
_ => panic_ret_type(),
},
NumCos => match self.ret_layout_raw.repr {
NumCos => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_COS[width]);
}
@ -1470,7 +1475,7 @@ impl<'a> LowLevelCall<'a> {
},
NumSqrtUnchecked => {
self.load_args(backend);
match self.ret_layout_raw.repr {
match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
backend.code_builder.f32_sqrt()
}
@ -1480,7 +1485,7 @@ impl<'a> LowLevelCall<'a> {
_ => panic_ret_type(),
}
}
NumLogUnchecked => match self.ret_layout_raw.repr {
NumLogUnchecked => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_LOG[width]);
}
@ -1504,7 +1509,7 @@ impl<'a> LowLevelCall<'a> {
_ => todo!("{:?}: {:?} -> {:?}", self.lowlevel, arg_type, ret_type),
}
}
NumPow => match self.ret_layout_raw.repr {
NumPow => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_POW[width]);
}
@ -1513,8 +1518,7 @@ impl<'a> LowLevelCall<'a> {
NumCountLeadingZeroBits => match backend
.layout_interner
.get(backend.storage.symbol_layouts[&self.arguments[0]])
.repr
.get_repr(backend.storage.symbol_layouts[&self.arguments[0]])
{
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(
@ -1526,8 +1530,7 @@ impl<'a> LowLevelCall<'a> {
},
NumCountTrailingZeroBits => match backend
.layout_interner
.get(backend.storage.symbol_layouts[&self.arguments[0]])
.repr
.get_repr(backend.storage.symbol_layouts[&self.arguments[0]])
{
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(
@ -1539,8 +1542,7 @@ impl<'a> LowLevelCall<'a> {
},
NumCountOneBits => match backend
.layout_interner
.get(backend.storage.symbol_layouts[&self.arguments[0]])
.repr
.get_repr(backend.storage.symbol_layouts[&self.arguments[0]])
{
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_COUNT_ONE_BITS[width]);
@ -1617,19 +1619,19 @@ impl<'a> LowLevelCall<'a> {
NumIsInfinite => num_is_infinite(backend, self.arguments[0]),
NumIsFinite => num_is_finite(backend, self.arguments[0]),
NumAtan => match self.ret_layout_raw.repr {
NumAtan => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ATAN[width]);
}
_ => panic_ret_type(),
},
NumAcos => match self.ret_layout_raw.repr {
NumAcos => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ACOS[width]);
}
_ => panic_ret_type(),
},
NumAsin => match self.ret_layout_raw.repr {
NumAsin => match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ASIN[width]);
}
@ -1777,14 +1779,14 @@ impl<'a> LowLevelCall<'a> {
NumIntCast => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
let arg_type = CodeGenNumType::from(arg_layout);
let arg_width = match backend.layout_interner.get(arg_layout).repr {
let arg_width = match backend.layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(w)) => w,
LayoutRepr::Builtin(Builtin::Bool) => IntWidth::U8,
x => internal_error!("Num.intCast is not defined for {:?}", x),
};
let ret_type = CodeGenNumType::from(self.ret_layout);
let ret_width = match self.ret_layout_raw.repr {
let ret_width = match self.ret_layout_raw {
LayoutRepr::Builtin(Builtin::Int(w)) => w,
x => internal_error!("Num.intCast is not defined for {:?}", x),
};
@ -1847,7 +1849,7 @@ impl<'a> LowLevelCall<'a> {
NumToFloatCast => {
self.load_args(backend);
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
let arg_signed = match backend.layout_interner.get(arg_layout).repr {
let arg_signed = match backend.layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(w)) => w.is_signed(),
LayoutRepr::Builtin(Builtin::Float(_)) => true, // unused
LayoutRepr::Builtin(Builtin::Decimal) => true,
@ -1895,13 +1897,13 @@ impl<'a> LowLevelCall<'a> {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
let (arg_width, ret_width) = match (
backend.layout_interner.get(arg_layout).repr,
self.ret_layout_raw.repr,
backend.layout_interner.get_repr(arg_layout),
self.ret_layout_raw,
) {
(
LayoutRepr::Builtin(Builtin::Int(arg_width)),
LayoutRepr::Struct(&[ret, ..]),
) => match backend.layout_interner.get(ret).repr {
) => match backend.layout_interner.get_repr(ret) {
LayoutRepr::Builtin(Builtin::Int(ret_width)) => (arg_width, ret_width),
_ => {
internal_error!(
@ -1993,19 +1995,19 @@ impl<'a> LowLevelCall<'a> {
let arg_layout = backend
.layout_interner
.runtime_representation_in(backend.storage.symbol_layouts[&self.arguments[0]]);
let arg_layout_raw = backend.layout_interner.get(arg_layout);
let arg_layout_raw = backend.layout_interner.get_repr(arg_layout);
let other_arg_layout = backend
.layout_interner
.runtime_representation(backend.storage.symbol_layouts[&self.arguments[1]]);
debug_assert_eq!(
arg_layout_raw.repr, other_arg_layout.repr,
arg_layout_raw, other_arg_layout,
"Cannot do `==` comparison on different types: {:?} vs {:?}",
arg_layout, other_arg_layout
);
let invert_result = matches!(self.lowlevel, LowLevel::NotEq);
match arg_layout_raw.repr {
match arg_layout_raw {
LayoutRepr::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => self.eq_or_neq_number(backend),
@ -2147,7 +2149,7 @@ impl<'a> LowLevelCall<'a> {
fn num_to_str(&self, backend: &mut WasmBackend<'a, '_>) {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout).repr {
match backend.layout_interner.get_repr(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::STR_FROM_INT[width])
}
@ -2355,8 +2357,7 @@ pub fn call_higher_order_lowlevel<'a>(
// The wrapper around the passed function will access the actual closure data in the struct.
let (closure_data_layout, closure_data_exists) = match backend
.layout_interner
.get(backend.storage.symbol_layouts[captured_environment])
.repr
.get_repr(backend.storage.symbol_layouts[captured_environment])
{
LayoutRepr::LambdaSet(lambda_set) => {
if lambda_set.is_represented(backend.layout_interner).is_some() {
@ -2379,7 +2380,7 @@ pub fn call_higher_order_lowlevel<'a>(
let wrapped_captures_layout =
backend
.layout_interner
.insert_no_semantic(LayoutRepr::struct_(
.insert_direct_no_semantic(LayoutRepr::struct_(
backend.env.arena.alloc([closure_data_layout]),
));
@ -2454,7 +2455,7 @@ pub fn call_higher_order_lowlevel<'a>(
argument_layouts.iter().take(n_non_closure_args).map(|lay| {
backend
.layout_interner
.insert_no_semantic(LayoutRepr::Boxed(*lay))
.insert_direct_no_semantic(LayoutRepr::Boxed(*lay))
});
wrapper_arg_layouts.push(wrapped_captures_layout);
@ -2466,7 +2467,7 @@ pub fn call_higher_order_lowlevel<'a>(
wrapper_arg_layouts.push(
backend
.layout_interner
.insert_no_semantic(LayoutRepr::Boxed(*result_layout)),
.insert_direct_no_semantic(LayoutRepr::Boxed(*result_layout)),
);
ProcLayout {
arguments: wrapper_arg_layouts.into_bump_slice(),
@ -2556,9 +2557,9 @@ pub fn call_higher_order_lowlevel<'a>(
let elem_layout = unwrap_list_elem_layout(
backend
.layout_interner
.get(backend.storage.symbol_layouts[xs]),
.get_repr(backend.storage.symbol_layouts[xs]),
);
let elem_layout = backend.layout_interner.get(elem_layout);
let elem_layout = backend.layout_interner.get_repr(elem_layout);
let (element_width, alignment) =
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
@ -2595,8 +2596,8 @@ pub fn call_higher_order_lowlevel<'a>(
}
}
fn unwrap_list_elem_layout(list_layout: Layout) -> InLayout {
match list_layout.repr {
fn unwrap_list_elem_layout(list_layout: LayoutRepr) -> InLayout {
match list_layout {
LayoutRepr::Builtin(Builtin::List(x)) => x,
e => internal_error!("expected List layout, got {:?}", e),
}
@ -2620,14 +2621,14 @@ fn list_map_n<'a>(
unwrap_list_elem_layout(
backend
.layout_interner
.get(backend.storage.symbol_layouts[sym]),
.get_repr(backend.storage.symbol_layouts[sym]),
)
}),
backend.env.arena,
);
let elem_ret = unwrap_list_elem_layout(backend.layout_interner.get(return_layout));
let elem_ret = backend.layout_interner.get(elem_ret);
let elem_ret = unwrap_list_elem_layout(backend.layout_interner.get_repr(return_layout));
let elem_ret = backend.layout_interner.get_repr(elem_ret);
let (elem_ret_size, elem_ret_align) =
elem_ret.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
@ -2661,7 +2662,7 @@ fn list_map_n<'a>(
// Here we wrap the layout in a Struct to ensure we get the right code gen
let el_ptr = backend
.layout_interner
.insert_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([*el])));
.insert_direct_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([*el])));
let idx = backend.get_refcount_fn_index(el_ptr, HelperOp::Dec);
let ptr = backend.get_fn_ptr(idx);
backend.code_builder.i32_const(ptr);
@ -2700,7 +2701,7 @@ fn ensure_symbol_is_in_memory<'a>(
);
let in_memory_layout = backend
.layout_interner
.insert_no_semantic(LayoutRepr::Struct(arena.alloc([layout])));
.insert_direct_no_semantic(LayoutRepr::Struct(arena.alloc([layout])));
(frame_ptr, offset, in_memory_layout)
}
}

View file

@ -55,7 +55,7 @@ pub fn insert_wrapper_for_layout<'a>(
}
};
match interner.get(layout).repr {
match interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
i8::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}

View file

@ -4,7 +4,7 @@ use std::hash::Hash;
use crate::ir::{
Expr, HigherOrderLowLevel, JoinPointId, Param, PassedFunction, Proc, ProcLayout, Stmt,
};
use crate::layout::{InLayout, Layout, LayoutInterner, STLayoutInterner};
use crate::layout::{InLayout, LayoutInterner, LayoutRepr, STLayoutInterner};
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_collections::all::{MutMap, MutSet};
@ -29,7 +29,7 @@ impl Ownership {
/// For reference-counted types (lists, (big) strings, recursive tags), owning a value
/// means incrementing its reference count. Hence, we prefer borrowing for these types
fn from_layout(layout: &Layout) -> Self {
fn from_layout(layout: &LayoutRepr) -> Self {
match layout.is_refcounted() {
true => Ownership::Borrowed,
false => Ownership::Owned,
@ -265,7 +265,7 @@ impl<'a> ParamMap<'a> {
) -> &'a [Param<'a>] {
Vec::from_iter_in(
ps.iter().map(|p| Param {
ownership: Ownership::from_layout(&interner.get(p.layout)),
ownership: Ownership::from_layout(&interner.get_repr(p.layout)),
layout: p.layout,
symbol: p.symbol,
}),
@ -281,7 +281,7 @@ impl<'a> ParamMap<'a> {
) -> &'a [Param<'a>] {
Vec::from_iter_in(
ps.iter().map(|(layout, symbol)| Param {
ownership: Ownership::from_layout(&interner.get(*layout)),
ownership: Ownership::from_layout(&interner.get_repr(*layout)),
layout: *layout,
symbol: *symbol,
}),

View file

@ -24,7 +24,7 @@ pub fn eq_generic<'a>(
) -> Stmt<'a> {
use crate::layout::Builtin::*;
use LayoutRepr::*;
let main_body = match layout_interner.get(layout).repr {
let main_body = match layout_interner.get_repr(layout) {
Builtin(Int(_) | Float(_) | Bool | Decimal) => {
unreachable!(
"No generated proc for `==`. Use direct code gen for {:?}",
@ -434,7 +434,8 @@ fn eq_tag_union_help<'a>(
if is_non_recursive {
compare_ptr_or_value
} else {
let union_layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let union_layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let loop_params_iter = operands.iter().map(|arg| Param {
symbol: *arg,
ownership: Ownership::Borrowed,
@ -468,7 +469,7 @@ fn eq_tag_fields<'a>(
// (If there are more than one, the others will use non-tail recursion)
let rec_ptr_index = field_layouts.iter().position(|field| {
matches!(
layout_interner.get(*field).repr,
layout_interner.get_repr(*field),
LayoutRepr::RecursivePointer(_)
)
});
@ -657,7 +658,7 @@ fn eq_list<'a>(
let arena = root.arena;
// A "Box" layout (heap pointer to a single list element)
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(elem_layout));
let box_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(elem_layout));
// Compare lengths
@ -703,7 +704,7 @@ fn eq_list<'a>(
let size = root.create_symbol(ident_ids, "size");
let size_expr = Expr::Literal(Literal::Int(
(layout_interner
.get(elem_layout)
.get_repr(elem_layout)
.stack_size(layout_interner, root.target_info) as i128)
.to_ne_bytes(),
));

View file

@ -10,8 +10,8 @@ use crate::ir::{
Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
};
use crate::layout::{
Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, Niche, STLayoutInterner,
UnionLayout,
Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, LayoutWrapper, Niche,
STLayoutInterner, UnionLayout,
};
mod equality;
@ -286,11 +286,11 @@ impl<'a> CodeGenHelp<'a> {
self.debug_recursion_depth += 1;
let layout = if matches!(
layout_interner.get(called_layout).repr,
layout_interner.get_repr(called_layout),
LayoutRepr::RecursivePointer(_)
) {
let union_layout = ctx.recursive_union.unwrap();
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout))
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout))
} else {
called_layout
};
@ -301,7 +301,7 @@ impl<'a> CodeGenHelp<'a> {
let (ret_layout, arg_layouts): (InLayout<'a>, &'a [InLayout<'a>]) = {
let arg = self.replace_rec_ptr(ctx, layout_interner, layout);
let box_arg = layout_interner.insert_no_semantic(LayoutRepr::Boxed(arg));
let box_arg = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(arg));
match ctx.op {
Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])),
@ -430,12 +430,14 @@ impl<'a> CodeGenHelp<'a> {
}
Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
IndirectInc => {
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
let box_layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
let inc_amount = (self.layout_isize, ARG_2);
self.arena.alloc([(box_layout, ARG_1), inc_amount])
}
IndirectDec => {
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
let box_layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
self.arena.alloc([(box_layout, ARG_1)])
}
Eq => self.arena.alloc([roc_value, (layout, ARG_2)]),
@ -483,7 +485,8 @@ impl<'a> CodeGenHelp<'a> {
niche: Niche::NONE,
},
HelperOp::IndirectInc => {
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
let box_layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
ProcLayout {
arguments: self.arena.alloc([box_layout, self.layout_isize]),
@ -492,7 +495,8 @@ impl<'a> CodeGenHelp<'a> {
}
}
HelperOp::IndirectDec => {
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
let box_layout =
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
ProcLayout {
arguments: self.arena.alloc([box_layout]),
@ -532,8 +536,9 @@ impl<'a> CodeGenHelp<'a> {
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> InLayout<'a> {
let lay = layout_interner.get(layout);
let repr = match lay.repr {
let lay = layout_interner.get_repr(layout);
let semantic = layout_interner.get_semantic(layout);
let repr = match lay {
LayoutRepr::Builtin(Builtin::List(v)) => {
let v = self.replace_rec_ptr(ctx, layout_interner, v);
LayoutRepr::Builtin(Builtin::List(v))
@ -580,7 +585,7 @@ impl<'a> CodeGenHelp<'a> {
LayoutRepr::RecursivePointer(_) => LayoutRepr::Union(ctx.recursive_union.unwrap()),
};
layout_interner.insert(Layout::new(repr, lay.semantic()))
layout_interner.insert(Layout::new(LayoutWrapper::Direct(repr), semantic))
}
fn union_tail_recursion_fields(
@ -664,16 +669,16 @@ impl<'a> CallerProc<'a> {
};
let box_capture_layout = if let Some(capture_layout) = capture_layout {
layout_interner.insert_no_semantic(LayoutRepr::Boxed(capture_layout))
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(capture_layout))
} else {
layout_interner.insert_no_semantic(LayoutRepr::Boxed(Layout::UNIT))
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(Layout::UNIT))
};
let box_argument_layout = layout_interner
.insert_no_semantic(LayoutRepr::Boxed(passed_function.argument_layouts[0]));
.insert_direct_no_semantic(LayoutRepr::Boxed(passed_function.argument_layouts[0]));
let box_return_layout =
layout_interner.insert_no_semantic(LayoutRepr::Boxed(passed_function.return_layout));
let box_return_layout = layout_interner
.insert_direct_no_semantic(LayoutRepr::Boxed(passed_function.return_layout));
let proc_layout = ProcLayout {
arguments: arena.alloc([box_capture_layout, box_argument_layout, box_return_layout]),
@ -822,7 +827,7 @@ fn layout_needs_helper_proc<'a>(
layout: InLayout<'a>,
op: HelperOp,
) -> bool {
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => false,

View file

@ -75,7 +75,7 @@ pub fn refcount_stmt<'a>(
}
ModifyRc::DecRef(structure) => {
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
// Str has no children, so Dec is the same as DecRef.
LayoutRepr::Builtin(Builtin::Str) => {
ctx.op = HelperOp::Dec;
@ -182,7 +182,7 @@ pub fn refcount_generic<'a>(
layout: InLayout<'a>,
structure: Symbol,
) -> Stmt<'a> {
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => {
@ -301,7 +301,7 @@ pub fn refcount_reset_proc_body<'a>(
let is_unique = root.create_symbol(ident_ids, "is_unique");
let addr = root.create_symbol(ident_ids, "addr");
let union_layout = match layout_interner.get(layout).repr {
let union_layout = match layout_interner.get_repr(layout) {
LayoutRepr::Union(u) => u,
_ => unimplemented!("Reset is only implemented for UnionLayout"),
};
@ -309,7 +309,8 @@ pub fn refcount_reset_proc_body<'a>(
// Whenever we recurse into a child layout we will want to Decrement
ctx.op = HelperOp::Dec;
ctx.recursive_union = Some(union_layout);
let recursion_ptr = layout_interner.insert_no_semantic(LayoutRepr::RecursivePointer(layout));
let recursion_ptr =
layout_interner.insert_direct_no_semantic(LayoutRepr::RecursivePointer(layout));
// Reset structure is unique. Decrement its children and return a pointer to the allocation.
let then_stmt = {
@ -483,7 +484,7 @@ pub fn refcount_resetref_proc_body<'a>(
let is_unique = root.create_symbol(ident_ids, "is_unique");
let addr = root.create_symbol(ident_ids, "addr");
let union_layout = match layout_interner.get(layout).repr {
let union_layout = match layout_interner.get_repr(layout) {
LayoutRepr::Union(u) => u,
_ => unimplemented!("Resetref is only implemented for UnionLayout"),
};
@ -491,7 +492,8 @@ pub fn refcount_resetref_proc_body<'a>(
// Whenever we recurse into a child layout we will want to Decrement
ctx.op = HelperOp::Dec;
ctx.recursive_union = Some(union_layout);
let recursion_ptr = layout_interner.insert_no_semantic(LayoutRepr::RecursivePointer(layout));
let recursion_ptr =
layout_interner.insert_direct_no_semantic(LayoutRepr::RecursivePointer(layout));
// Reset structure is unique. Return a pointer to the allocation.
let then_stmt = Stmt::Ret(addr);
@ -979,7 +981,7 @@ fn refcount_list<'a>(
let arena = root.arena;
// A "Box" layout (heap pointer to a single list element)
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(elem_layout));
let box_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(elem_layout));
//
// Check if the list is empty
@ -1106,7 +1108,7 @@ fn refcount_list<'a>(
let is_relevant_op = ctx.op.is_dec() || ctx.op.is_inc();
let modify_elems_and_list =
if is_relevant_op && layout_interner.get(elem_layout).is_refcounted() {
if is_relevant_op && layout_interner.get_repr(elem_layout).is_refcounted() {
refcount_list_elems(
root,
ident_ids,
@ -1742,7 +1744,7 @@ fn refcount_union_tailrec<'a>(
let tailrec_loop = JoinPointId(root.create_symbol(ident_ids, "tailrec_loop"));
let current = root.create_symbol(ident_ids, "current");
let next_ptr = root.create_symbol(ident_ids, "next_ptr");
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let tag_id_layout = union_layout.tag_id_layout();
@ -1887,7 +1889,7 @@ fn refcount_union_tailrec<'a>(
let jump_with_null_ptr = Stmt::Let(
null_pointer,
Expr::NullPointer,
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout)),
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout)),
root.arena.alloc(Stmt::Jump(
jp_modify_union,
root.arena.alloc([null_pointer]),
@ -1931,7 +1933,7 @@ fn refcount_union_tailrec<'a>(
));
let loop_init = Stmt::Jump(tailrec_loop, root.arena.alloc([initial_structure]));
let union_layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
let union_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
let loop_param = Param {
symbol: current,
ownership: Ownership::Borrowed,

View file

@ -199,7 +199,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
// lazily.
loop {
layout = self.interner.chase_recursive_in(layout);
match self.interner.get(layout).repr {
match self.interner.get_repr(layout) {
LayoutRepr::LambdaSet(ls) => layout = ls.representation,
_ => return layout,
}
@ -292,7 +292,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
} => {
self.check_sym_layout(*cond_symbol, *cond_layout, UseKind::SwitchCond);
let layout = self.resolve(*cond_layout);
match self.interner.get(layout).repr {
match self.interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Int(_)) => {}
LayoutRepr::Builtin(Builtin::Bool) => {}
_ => self.problem(ProblemKind::BadSwitchConditionLayout {
@ -400,7 +400,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
} => {
let interned_layout = self
.interner
.insert_no_semantic(LayoutRepr::Union(tag_layout));
.insert_direct_no_semantic(LayoutRepr::Union(tag_layout));
self.check_tag_expr(interned_layout, tag_layout, tag_id, arguments);
Some(interned_layout)
}
@ -440,7 +440,9 @@ impl<'a, 'r> Ctx<'a, 'r> {
}
Some(
self.interner
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*elem_layout))),
.insert_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(
*elem_layout,
))),
)
}
Expr::EmptyArray => {
@ -449,11 +451,14 @@ impl<'a, 'r> Ctx<'a, 'r> {
}
&Expr::ExprBox { symbol } => self.with_sym_layout(symbol, |ctx, _def_line, layout| {
let inner = layout;
Some(ctx.interner.insert_no_semantic(LayoutRepr::Boxed(inner)))
Some(
ctx.interner
.insert_direct_no_semantic(LayoutRepr::Boxed(inner)),
)
}),
&Expr::ExprUnbox { symbol } => self.with_sym_layout(symbol, |ctx, def_line, layout| {
let layout = ctx.resolve(layout);
match ctx.interner.get(layout).repr {
match ctx.interner.get_repr(layout) {
LayoutRepr::Boxed(inner) => Some(inner),
_ => {
ctx.problem(ProblemKind::UnboxNotABox { symbol, def_line });
@ -471,7 +476,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
} => {
let union = self
.interner
.insert_no_semantic(LayoutRepr::Union(tag_layout));
.insert_direct_no_semantic(LayoutRepr::Union(tag_layout));
self.check_sym_layout(symbol, union, UseKind::TagReuse);
// TODO also check update arguments
Some(union)
@ -494,7 +499,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
fn check_struct_at_index(&mut self, structure: Symbol, index: u64) -> Option<InLayout<'a>> {
self.with_sym_layout(structure, |ctx, def_line, layout| {
let layout = ctx.resolve(layout);
match ctx.interner.get(layout).repr {
match ctx.interner.get_repr(layout) {
LayoutRepr::Struct(field_layouts) => {
if index as usize >= field_layouts.len() {
ctx.problem(ProblemKind::StructIndexOOB {
@ -529,7 +534,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
) -> Option<InLayout<'a>> {
let union = self
.interner
.insert_no_semantic(LayoutRepr::Union(union_layout));
.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
self.with_sym_layout(structure, |ctx, def_line, _layout| {
ctx.check_sym_layout(structure, union, UseKind::TagExpr);

View file

@ -483,9 +483,9 @@ fn specialize_drops_stmt<'a, 'i>(
// This decremented symbol was not incremented before, perhaps the children were.
let in_layout = environment.get_symbol_layout(symbol);
let runtime_layout = layout_interner.runtime_representation(*in_layout);
let runtime_repr = layout_interner.runtime_representation(*in_layout);
let updated_stmt = match runtime_layout.repr {
let updated_stmt = match runtime_repr {
// Layout has children, try to inline them.
LayoutRepr::Struct(field_layouts) => specialize_struct(
arena,

View file

@ -677,10 +677,17 @@ fn insert_refcount_operations_stmt<'v, 'a>(
} => {
let new_remainder = insert_refcount_operations_stmt(arena, environment, remainder);
let newer_remainder = consume_and_insert_dec_stmts(
arena,
environment,
environment.borrowed_usages([*symbol]),
new_remainder,
);
arena.alloc(Stmt::Dbg {
symbol: *symbol,
variable: *variable,
remainder: new_remainder,
remainder: newer_remainder,
})
}
Stmt::Join {

View file

@ -1066,7 +1066,7 @@ impl<'a> Procs<'a> {
let is_self_recursive = match top_level
.arguments
.last()
.map(|l| layout_cache.get_in(*l).repr)
.map(|l| layout_cache.get_repr(*l))
{
Some(LayoutRepr::LambdaSet(lambda_set)) => lambda_set.contains(name.name()),
_ => false,
@ -3509,10 +3509,10 @@ fn specialize_proc_help<'a>(
combined.sort_by(|(_, layout1), (_, layout2)| {
let size1 = layout_cache
.get_in(**layout1)
.get_repr(**layout1)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
let size2 = layout_cache
.get_in(**layout2)
.get_repr(**layout2)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
size2.cmp(&size1)
@ -3557,10 +3557,10 @@ fn specialize_proc_help<'a>(
combined.sort_by(|(_, layout1), (_, layout2)| {
let size1 = layout_cache
.get_in(**layout1)
.get_repr(**layout1)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
let size2 = layout_cache
.get_in(**layout2)
.get_repr(**layout2)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
size2.cmp(&size1)
@ -4145,9 +4145,9 @@ pub fn with_hole<'a>(
IngestedFile(_, bytes, var) => {
let interned = layout_cache.from_var(env.arena, var, env.subs).unwrap();
let layout = layout_cache.get_in(interned);
let layout = layout_cache.get_repr(interned);
match layout.repr {
match layout {
LayoutRepr::Builtin(Builtin::List(elem_layout)) if elem_layout == Layout::U8 => {
let mut elements = Vec::with_capacity_in(bytes.len(), env.arena);
for byte in bytes.iter() {
@ -4422,7 +4422,32 @@ pub fn with_hole<'a>(
Expect { .. } => unreachable!("I think this is unreachable"),
ExpectFx { .. } => unreachable!("I think this is unreachable"),
Dbg { .. } => unreachable!("I think this is unreachable"),
Dbg {
loc_condition,
loc_continuation,
variable: cond_variable,
symbol: dbg_symbol,
} => {
let rest = with_hole(
env,
loc_continuation.value,
variable,
procs,
layout_cache,
assigned,
hole,
);
compile_dbg(
env,
procs,
layout_cache,
dbg_symbol,
*loc_condition,
cond_variable,
rest,
)
}
If {
cond_var,
@ -4627,13 +4652,14 @@ pub fn with_hole<'a>(
Ok(elem_layout) => {
let expr = Expr::EmptyArray;
let list_layout = layout_cache
.put_in_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
.put_in_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
Stmt::Let(assigned, expr, list_layout, hole)
}
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
let expr = Expr::EmptyArray;
let list_layout = layout_cache
.put_in_no_semantic(LayoutRepr::Builtin(Builtin::List(Layout::VOID)));
let list_layout = layout_cache.put_in_direct_no_semantic(LayoutRepr::Builtin(
Builtin::List(Layout::VOID),
));
Stmt::Let(assigned, expr, list_layout, hole)
}
Err(LayoutProblem::Erroneous) => panic!("list element is error type"),
@ -4679,8 +4705,8 @@ pub fn with_hole<'a>(
elems: elements.into_bump_slice(),
};
let list_layout =
layout_cache.put_in_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
let list_layout = layout_cache
.put_in_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
let stmt = Stmt::Let(assigned, expr, list_layout, hole);
@ -4994,7 +5020,7 @@ pub fn with_hole<'a>(
.from_var(env.arena, record_var, env.subs)
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
let field_layouts = match layout_cache.get_in(record_layout).repr {
let field_layouts = match layout_cache.get_repr(record_layout) {
LayoutRepr::Struct(field_layouts) => field_layouts,
_ => arena.alloc([record_layout]),
};
@ -5620,6 +5646,53 @@ pub fn with_hole<'a>(
}
}
/// Compiles a `dbg` expression.
fn compile_dbg<'a>(
env: &mut Env<'a, '_>,
procs: &mut Procs<'a>,
layout_cache: &mut LayoutCache<'a>,
dbg_symbol: Symbol,
loc_condition: Loc<roc_can::expr::Expr>,
variable: Variable,
continuation: Stmt<'a>,
) -> Stmt<'a> {
let spec_var = env
.expectation_subs
.as_mut()
.unwrap()
.fresh_unnamed_flex_var();
let dbg_stmt = Stmt::Dbg {
symbol: dbg_symbol,
variable: spec_var,
remainder: env.arena.alloc(continuation),
};
// Now that the dbg value has been specialized, export its specialized type into the
// expectations subs.
store_specialized_expectation_lookups(env, [variable], &[spec_var]);
let symbol_is_reused = matches!(
can_reuse_symbol(env, layout_cache, procs, &loc_condition.value, variable),
ReuseSymbol::Value(_)
);
// skip evaluating the condition if it's just a symbol
if symbol_is_reused {
dbg_stmt
} else {
with_hole(
env,
loc_condition.value,
variable,
procs,
layout_cache,
dbg_symbol,
env.arena.alloc(dbg_stmt),
)
}
}
/// Compiles an access into a tuple or record.
fn compile_struct_like_access<'a>(
env: &mut Env<'a, '_>,
@ -5917,10 +5990,10 @@ where
combined.sort_by(|(_, layout1), (_, layout2)| {
let size1 = layout_cache
.get_in(**layout1)
.get_repr(**layout1)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
let size2 = layout_cache
.get_in(**layout2)
.get_repr(**layout2)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
size2.cmp(&size1)
@ -5951,10 +6024,10 @@ where
combined.sort_by(|(_, layout1), (_, layout2)| {
let size1 = layout_cache
.get_in(**layout1)
.get_repr(**layout1)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
let size2 = layout_cache
.get_in(**layout2)
.get_repr(**layout2)
.alignment_bytes(&layout_cache.interner, ptr_bytes);
size2.cmp(&size1)
@ -5967,9 +6040,7 @@ where
debug_assert_eq!(
LayoutRepr::struct_(field_layouts),
layout_cache
.get_in(lambda_set.runtime_representation())
.repr
layout_cache.get_repr(lambda_set.runtime_representation())
);
let expr = Expr::Struct(symbols);
@ -6170,7 +6241,7 @@ fn convert_tag_union<'a>(
layout_cache.from_var(env.arena, variant_var, env.subs),
"Wrapped"
);
let union_layout = match layout_cache.interner.chase_recursive(variant_layout).repr {
let union_layout = match layout_cache.interner.chase_recursive(variant_layout) {
LayoutRepr::Union(ul) => ul,
other => internal_error!(
"unexpected layout {:?} for {:?}",
@ -6301,7 +6372,8 @@ fn convert_tag_union<'a>(
}
};
let union_layout = layout_cache.put_in_no_semantic(LayoutRepr::Union(union_layout));
let union_layout =
layout_cache.put_in_direct_no_semantic(LayoutRepr::Union(union_layout));
let stmt = Stmt::Let(assigned, tag, union_layout, hole);
let iter = field_symbols_temp
@ -6440,7 +6512,7 @@ fn sorted_field_symbols<'a>(
};
let alignment = layout_cache
.get_in(layout)
.get_repr(layout)
.alignment_bytes(&layout_cache.interner, env.target_info);
let symbol = possible_reuse_symbol_or_specialize(env, procs, layout_cache, &arg.value, var);
@ -6824,41 +6896,15 @@ pub fn from_can<'a>(
} => {
let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
let spec_var = env
.expectation_subs
.as_mut()
.unwrap()
.fresh_unnamed_flex_var();
let dbg_stmt = Stmt::Dbg {
symbol: dbg_symbol,
variable: spec_var,
remainder: env.arena.alloc(rest),
};
// Now that the dbg value has been specialized, export its specialized type into the
// expectations subs.
store_specialized_expectation_lookups(env, [variable], &[spec_var]);
let symbol_is_reused = matches!(
can_reuse_symbol(env, layout_cache, procs, &loc_condition.value, variable),
ReuseSymbol::Value(_)
);
// skip evaluating the condition if it's just a symbol
if symbol_is_reused {
dbg_stmt
} else {
with_hole(
env,
loc_condition.value,
variable,
procs,
layout_cache,
dbg_symbol,
env.arena.alloc(dbg_stmt),
)
}
compile_dbg(
env,
procs,
layout_cache,
dbg_symbol,
*loc_condition,
variable,
rest,
)
}
LetRec(defs, cont, _cycle_mark) => {
@ -7887,7 +7933,7 @@ fn specialize_symbol<'a>(
let layout = match raw {
RawFunctionLayout::ZeroArgumentThunk(layout) => layout,
RawFunctionLayout::Function(_, lambda_set, _) => layout_cache
.put_in_no_semantic(LayoutRepr::LambdaSet(lambda_set)),
.put_in_direct_no_semantic(LayoutRepr::LambdaSet(lambda_set)),
};
let raw = RawFunctionLayout::ZeroArgumentThunk(layout);
@ -9764,7 +9810,7 @@ where
($tag_id:expr, $layout:expr, $union_layout:expr, $field_layouts: expr) => {{
if $field_layouts.iter().any(|l| {
layout_interner
.get(*l)
.get_repr(*l)
.has_varying_stack_size(layout_interner, arena)
}) {
let procs = generate_glue_procs_for_tag_fields(
@ -9789,7 +9835,7 @@ where
}
while let Some(layout) = stack.pop() {
match layout.repr {
match layout.repr(layout_interner) {
LayoutRepr::Builtin(builtin) => match builtin {
Builtin::Int(_)
| Builtin::Float(_)
@ -9801,7 +9847,7 @@ where
LayoutRepr::Struct(field_layouts) => {
if field_layouts.iter().any(|l| {
layout_interner
.get(*l)
.get_repr(*l)
.has_varying_stack_size(layout_interner, arena)
}) {
let procs = generate_glue_procs_for_struct_fields(
@ -9892,11 +9938,11 @@ where
{
let interned_unboxed_struct_layout = layout_interner.insert(*unboxed_struct_layout);
let boxed_struct_layout =
Layout::no_semantic(LayoutRepr::Boxed(interned_unboxed_struct_layout));
Layout::no_semantic(LayoutRepr::Boxed(interned_unboxed_struct_layout).direct());
let boxed_struct_layout = layout_interner.insert(boxed_struct_layout);
let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena);
let field_layouts = match layout_interner.get(interned_unboxed_struct_layout).repr {
let field_layouts = match layout_interner.get_repr(interned_unboxed_struct_layout) {
LayoutRepr::Struct(field_layouts) => field_layouts,
other => {
unreachable!(
@ -10003,7 +10049,7 @@ where
I: LayoutInterner<'a>,
{
let interned = layout_interner.insert(*unboxed_struct_layout);
let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Boxed(interned));
let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Boxed(interned).direct());
let boxed_struct_layout = layout_interner.insert(boxed_struct_layout);
let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena);

View file

@ -1014,7 +1014,7 @@ fn to_relevant_branch_help<'a>(
// the test matches the constructor of this pattern
match layout {
UnionLayout::NonRecursive([[arg]])
if matches!(interner.get(*arg).repr, LayoutRepr::Struct([_],)) =>
if matches!(interner.get_repr(*arg), LayoutRepr::Struct([_],)) =>
{
// a one-element record equivalent
// Theory: Unbox doesn't have any value for us
@ -1573,7 +1573,7 @@ fn path_to_expr_help<'a>(
PathInstruction::TagIndex { index, tag_id } => {
let index = *index;
match layout_interner.chase_recursive(layout).repr {
match layout_interner.chase_recursive(layout) {
LayoutRepr::Union(union_layout) => {
let inner_expr = Expr::UnionAtIndex {
tag_id: *tag_id,
@ -1626,7 +1626,7 @@ fn path_to_expr_help<'a>(
PathInstruction::ListIndex { index } => {
let list_sym = symbol;
match layout_interner.get(layout).repr {
match layout_interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::List(elem_layout)) => {
let (index_sym, new_stores) = build_list_index_probe(env, list_sym, index);
@ -1673,7 +1673,7 @@ fn test_to_comparison<'a>(
// (e.g. record pattern guard matches)
debug_assert!(union.alternatives.len() > 1);
match layout_interner.chase_recursive(test_layout).repr {
match layout_interner.chase_recursive(test_layout) {
LayoutRepr::Union(union_layout) => {
let lhs = Expr::Literal(Literal::Int((tag_id as i128).to_ne_bytes()));
@ -1763,7 +1763,7 @@ fn test_to_comparison<'a>(
let list_layout = test_layout;
let list_sym = rhs_symbol;
match layout_interner.get(list_layout).repr {
match layout_interner.get_repr(list_layout) {
LayoutRepr::Builtin(Builtin::List(_elem_layout)) => {
let real_len_expr = Expr::Call(Call {
call_type: CallType::LowLevel {
@ -2310,7 +2310,7 @@ fn decide_to_branching<'a>(
// We have learned more about the exact layout of the cond (based on the path)
// but tests are still relative to the original cond symbol
let inner_cond_layout_raw = layout_cache.interner.chase_recursive(inner_cond_layout);
let mut switch = if let LayoutRepr::Union(union_layout) = inner_cond_layout_raw.repr {
let mut switch = if let LayoutRepr::Union(union_layout) = inner_cond_layout_raw {
let tag_id_symbol = env.unique_symbol();
let temp = Stmt::Switch {
@ -2332,7 +2332,7 @@ fn decide_to_branching<'a>(
union_layout.tag_id_layout(),
env.arena.alloc(temp),
)
} else if let LayoutRepr::Builtin(Builtin::List(_)) = inner_cond_layout_raw.repr {
} else if let LayoutRepr::Builtin(Builtin::List(_)) = inner_cond_layout_raw {
let len_symbol = env.unique_symbol();
let switch = Stmt::Switch {

View file

@ -83,7 +83,7 @@ pub fn make_num_literal<'a>(
num_str: &str,
num_value: IntOrFloatValue,
) -> NumLiteral {
match interner.get(layout).repr {
match interner.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => match num_value {
IntOrFloatValue::Int(IntValue::I128(n)) => NumLiteral::Int(n, width),
IntOrFloatValue::Int(IntValue::U128(n)) => NumLiteral::U128(n),

View file

@ -344,7 +344,7 @@ fn from_can_pattern_help<'a>(
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
SingleQuote(var, _, c, _) => {
let layout = layout_cache.from_var(env.arena, *var, env.subs);
match layout.map(|l| layout_cache.get_in(l).repr) {
match layout.map(|l| layout_cache.get_repr(l)) {
Ok(LayoutRepr::Builtin(Builtin::Int(width))) => {
Ok(Pattern::IntLiteral((*c as i128).to_ne_bytes(), width))
}
@ -583,12 +583,11 @@ fn from_can_pattern_help<'a>(
// problems down the line because we hash layouts and an unrolled
// version is not the same as the minimal version.
let whole_var_layout = layout_cache.from_var(env.arena, *whole_var, env.subs);
let layout = match whole_var_layout
.map(|l| layout_cache.interner.chase_recursive(l).repr)
{
Ok(LayoutRepr::Union(ul)) => ul,
_ => internal_error!(),
};
let layout =
match whole_var_layout.map(|l| layout_cache.interner.chase_recursive(l)) {
Ok(LayoutRepr::Union(ul)) => ul,
_ => internal_error!(),
};
use WrappedVariant::*;
match variant {
@ -1207,8 +1206,8 @@ fn store_pattern_help<'a>(
let mut fields = Vec::with_capacity_in(arguments.len(), env.arena);
fields.extend(arguments.iter().map(|x| x.1));
let layout =
layout_cache.put_in_no_semantic(LayoutRepr::struct_(fields.into_bump_slice()));
let layout = layout_cache
.put_in_direct_no_semantic(LayoutRepr::struct_(fields.into_bump_slice()));
return store_newtype_pattern(
env,
@ -1552,9 +1551,9 @@ fn store_tag_pattern<'a>(
for (index, (argument, arg_layout)) in arguments.iter().enumerate().rev() {
let mut arg_layout = *arg_layout;
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_in(arg_layout).repr {
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_repr(arg_layout) {
// TODO(recursive-layouts): fix after disjoint rec ptrs
arg_layout = layout_cache.put_in_no_semantic(LayoutRepr::Union(union_layout));
arg_layout = layout_cache.put_in_direct_no_semantic(LayoutRepr::Union(union_layout));
}
let load = Expr::UnionAtIndex {
@ -1630,7 +1629,7 @@ fn store_newtype_pattern<'a>(
for (index, (argument, arg_layout)) in arguments.iter().enumerate().rev() {
let mut arg_layout = *arg_layout;
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_in(arg_layout).repr {
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_repr(arg_layout) {
arg_layout = layout;
}

View file

@ -328,12 +328,15 @@ impl<'a> LayoutCache<'a> {
pub fn get_in(&self, interned: InLayout<'a>) -> Layout<'a> {
self.interner.get(interned)
}
pub fn get_repr(&self, interned: InLayout<'a>) -> LayoutRepr<'a> {
self.interner.get_repr(interned)
}
pub fn put_in(&mut self, layout: Layout<'a>) -> InLayout<'a> {
self.interner.insert(layout)
}
pub fn put_in_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
self.interner.insert_no_semantic(repr)
pub(crate) fn put_in_direct_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
self.interner.insert_direct_no_semantic(repr)
}
#[cfg(debug_assertions)]
@ -656,10 +659,16 @@ impl<'a> RawFunctionLayout<'a> {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Layout<'a> {
pub repr: LayoutRepr<'a>,
repr: LayoutWrapper<'a>,
semantic: SemanticRepr<'a>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub(crate) enum LayoutWrapper<'a> {
Direct(LayoutRepr<'a>),
Newtype(InLayout<'a>),
}
/// Types for code gen must be monomorphic. No type variables allowed!
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum LayoutRepr<'a> {
@ -873,8 +882,8 @@ impl<'a> UnionLayout<'a> {
};
// TODO(recursive-layouts): simplify after we have disjoint recursive pointers
if let LayoutRepr::RecursivePointer(_) = interner.get(result).repr {
interner.insert_no_semantic(LayoutRepr::Union(self))
if let LayoutRepr::RecursivePointer(_) = interner.get_repr(result) {
interner.insert_direct_no_semantic(LayoutRepr::Union(self))
} else {
result
}
@ -1417,7 +1426,7 @@ impl<'a> LambdaSet<'a> {
None
} else {
let repr = self.representation;
match interner.get(repr).repr {
match interner.get_repr(repr) {
LayoutRepr::Struct(&[]) => None,
_ => Some(repr),
}
@ -1533,7 +1542,7 @@ impl<'a> LambdaSet<'a> {
let repr_layout = interner.chase_recursive(self.representation);
match repr_layout.repr {
match repr_layout {
LayoutRepr::Union(union) => {
// here we rely on the fact that a union in a closure would be stored in a one-element record.
// a closure representation that is itself union must be a of the shape `Closure1 ... | Closure2 ...`
@ -1660,9 +1669,9 @@ impl<'a> LambdaSet<'a> {
let repr_layout = interner.chase_recursive(self.representation);
match repr_layout.repr {
match repr_layout {
LayoutRepr::Union(union_layout) => {
if repr_layout == Layout::VOID_NAKED {
if repr_layout == Layout::VOID_NAKED.repr(interner) {
debug_assert!(self.set.is_empty());
return ClosureCallOptions::Void;
}
@ -1747,7 +1756,7 @@ impl<'a> LambdaSet<'a> {
Cacheable(result, criteria)
});
match result.map(|l| env.cache.interner.chase_recursive(l).repr) {
match result.map(|l| env.cache.interner.chase_recursive(l)) {
Ok(LayoutRepr::LambdaSet(lambda_set)) => Cacheable(Ok(lambda_set), criteria),
Err(err) => Cacheable(Err(err), criteria),
Ok(layout) => internal_error!("other layout found for lambda set: {:?}", layout),
@ -1923,7 +1932,7 @@ impl<'a> LambdaSet<'a> {
I: LayoutInterner<'a>,
{
interner
.get(self.representation)
.get_repr(self.representation)
.stack_size(interner, target_info)
}
pub fn contains_refcounted<I>(&self, interner: &I) -> bool
@ -1931,14 +1940,16 @@ impl<'a> LambdaSet<'a> {
I: LayoutInterner<'a>,
{
interner
.get(self.representation)
.get_repr(self.representation)
.contains_refcounted(interner)
}
pub fn safe_to_memcpy<I>(&self, interner: &I) -> bool
where
I: LayoutInterner<'a>,
{
interner.get(self.representation).safe_to_memcpy(interner)
interner
.get_repr(self.representation)
.safe_to_memcpy(interner)
}
pub fn alignment_bytes<I>(&self, interner: &I, target_info: TargetInfo) -> u32
@ -1946,7 +1957,7 @@ impl<'a> LambdaSet<'a> {
I: LayoutInterner<'a>,
{
interner
.get(self.representation)
.get_repr(self.representation)
.alignment_bytes(interner, target_info)
}
}
@ -2125,7 +2136,7 @@ pub enum Builtin<'a> {
#[macro_export]
macro_rules! list_element_layout {
($interner:expr, $list_layout:expr) => {
match $interner.get($list_layout).repr {
match $interner.get_repr($list_layout) {
LayoutRepr::Builtin(Builtin::List(list_layout)) => list_layout,
_ => internal_error!("invalid list layout"),
}
@ -2326,19 +2337,30 @@ pub fn is_any_float_range(subs: &Subs, var: Variable) -> bool {
}
impl<'a> Layout<'a> {
pub const fn new(repr: LayoutRepr<'a>, semantic: SemanticRepr<'a>) -> Self {
pub(crate) const fn new(repr: LayoutWrapper<'a>, semantic: SemanticRepr<'a>) -> Self {
Self { repr, semantic }
}
pub const fn no_semantic(repr: LayoutRepr<'a>) -> Self {
pub(crate) const fn no_semantic(repr: LayoutWrapper<'a>) -> Self {
Self {
repr,
semantic: SemanticRepr::NONE,
}
}
pub const fn semantic(&self) -> SemanticRepr<'a> {
self.semantic
pub(crate) fn repr<I>(&self, interner: &I) -> LayoutRepr<'a>
where
I: LayoutInterner<'a>,
{
let mut lay = *self;
loop {
match lay.repr {
LayoutWrapper::Direct(repr) => return repr,
LayoutWrapper::Newtype(real) => {
lay = interner.get(real);
}
}
}
}
fn new_help<'b>(
@ -2457,7 +2479,7 @@ impl<'a> Layout<'a> {
let mut total = 0;
for layout in tag.iter() {
let (stack_size, alignment) = interner
.get(*layout)
.get_repr(*layout)
.stack_size_and_alignment(interner, target_info);
total += stack_size;
data_align = data_align.max(alignment);
@ -2476,7 +2498,7 @@ impl<'a> Layout<'a> {
I: LayoutInterner<'a>,
{
use LayoutRepr::*;
match self.repr {
match self.repr(interner) {
LambdaSet(lambda_set) => interner.get(lambda_set.runtime_representation()),
_ => *self,
}
@ -2487,21 +2509,13 @@ impl<'a> Layout<'a> {
I: LayoutInterner<'a>,
{
use LayoutRepr::*;
match interner.get(layout).repr {
match interner.get_repr(layout) {
LambdaSet(lambda_set) => lambda_set.runtime_representation(),
_ => layout,
}
}
}
impl<'a> std::ops::Deref for Layout<'a> {
type Target = LayoutRepr<'a>;
fn deref(&self) -> &Self::Target {
&self.repr
}
}
impl<'a> LayoutRepr<'a> {
pub const UNIT: Self = LayoutRepr::struct_(&[]);
pub const BOOL: Self = LayoutRepr::Builtin(Builtin::Bool);
@ -2525,6 +2539,10 @@ impl<'a> LayoutRepr<'a> {
Self::Struct(field_layouts)
}
pub(crate) const fn direct(self) -> LayoutWrapper<'a> {
LayoutWrapper::Direct(self)
}
pub fn safe_to_memcpy<I>(&self, interner: &I) -> bool
where
I: LayoutInterner<'a>,
@ -2535,7 +2553,7 @@ impl<'a> LayoutRepr<'a> {
Builtin(builtin) => builtin.safe_to_memcpy(),
Struct(field_layouts) => field_layouts
.iter()
.all(|field_layout| interner.get(*field_layout).safe_to_memcpy(interner)),
.all(|field_layout| interner.get_repr(*field_layout).safe_to_memcpy(interner)),
Union(variant) => {
use UnionLayout::*;
@ -2543,7 +2561,7 @@ impl<'a> LayoutRepr<'a> {
NonRecursive(tags) => tags.iter().all(|tag_layout| {
tag_layout
.iter()
.all(|field| interner.get(*field).safe_to_memcpy(interner))
.all(|field| interner.get_repr(*field).safe_to_memcpy(interner))
}),
Recursive(_)
| NullableWrapped { .. }
@ -2555,7 +2573,7 @@ impl<'a> LayoutRepr<'a> {
}
}
LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.get_repr(lambda_set.runtime_representation())
.safe_to_memcpy(interner),
Boxed(_) | RecursivePointer(_) => {
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
@ -2592,7 +2610,7 @@ impl<'a> LayoutRepr<'a> {
}
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => true,
LayoutRepr::LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.get_repr(lambda_set.runtime_representation())
.is_passed_by_reference(interner, target_info),
_ => false,
}
@ -2633,7 +2651,7 @@ impl<'a> LayoutRepr<'a> {
for field_layout in *field_layouts {
sum += interner
.get(*field_layout)
.get_repr(*field_layout)
.stack_size(interner, target_info);
}
@ -2641,7 +2659,7 @@ impl<'a> LayoutRepr<'a> {
}
Union(variant) => variant.stack_size_without_alignment(interner, target_info),
LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.get_repr(lambda_set.runtime_representation())
.stack_size_without_alignment(interner, target_info),
RecursivePointer(_) => target_info.ptr_width() as u32,
Boxed(_) => target_info.ptr_width() as u32,
@ -2656,7 +2674,7 @@ impl<'a> LayoutRepr<'a> {
match self {
Struct(field_layouts) => field_layouts
.iter()
.map(|x| interner.get(*x).alignment_bytes(interner, target_info))
.map(|x| interner.get_repr(*x).alignment_bytes(interner, target_info))
.max()
.unwrap_or(0),
@ -2669,7 +2687,9 @@ impl<'a> LayoutRepr<'a> {
.iter()
.flat_map(|layouts| {
layouts.iter().map(|layout| {
interner.get(*layout).alignment_bytes(interner, target_info)
interner
.get_repr(*layout)
.alignment_bytes(interner, target_info)
})
})
.max();
@ -2693,7 +2713,7 @@ impl<'a> LayoutRepr<'a> {
}
}
LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.get_repr(lambda_set.runtime_representation())
.alignment_bytes(interner, target_info),
Builtin(builtin) => builtin.alignment_bytes(target_info),
RecursivePointer(_) => target_info.ptr_width() as u32,
@ -2713,14 +2733,16 @@ impl<'a> LayoutRepr<'a> {
Struct { .. } => self.alignment_bytes(interner, target_info).max(ptr_width),
Union(union_layout) => union_layout.allocation_alignment_bytes(interner, target_info),
LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.get_repr(lambda_set.runtime_representation())
.allocation_alignment_bytes(interner, target_info),
RecursivePointer(_) => {
unreachable!("should be looked up to get an actual layout")
}
Boxed(inner) => Ord::max(
ptr_width,
interner.get(*inner).alignment_bytes(interner, target_info),
interner
.get_repr(*inner)
.alignment_bytes(interner, target_info),
),
}
}
@ -2755,7 +2777,7 @@ impl<'a> LayoutRepr<'a> {
Builtin(builtin) => builtin.is_refcounted(),
Struct(field_layouts) => field_layouts
.iter()
.any(|f| interner.get(*f).contains_refcounted(interner)),
.any(|f| interner.get_repr(*f).contains_refcounted(interner)),
Union(variant) => {
use UnionLayout::*;
@ -2763,7 +2785,7 @@ impl<'a> LayoutRepr<'a> {
NonRecursive(fields) => fields
.iter()
.flat_map(|ls| ls.iter())
.any(|f| interner.get(*f).contains_refcounted(interner)),
.any(|f| interner.get_repr(*f).contains_refcounted(interner)),
Recursive(_)
| NullableWrapped { .. }
| NullableUnwrapped { .. }
@ -2771,7 +2793,7 @@ impl<'a> LayoutRepr<'a> {
}
}
LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.get_repr(lambda_set.runtime_representation())
.contains_refcounted(interner),
RecursivePointer(_) => true,
Boxed(_) => true,
@ -2805,27 +2827,27 @@ impl<'a> LayoutRepr<'a> {
Struct(field_layouts) => stack.extend(
field_layouts
.iter()
.map(|interned| interner.get(*interned).repr),
.map(|interned| interner.get_repr(*interned)),
),
Union(tag_union) => match tag_union {
UnionLayout::NonRecursive(tags) | UnionLayout::Recursive(tags) => {
for tag in tags {
stack.extend(tag.iter().map(|interned| interner.get(*interned).repr));
stack.extend(tag.iter().map(|interned| interner.get_repr(*interned)));
}
}
UnionLayout::NonNullableUnwrapped(fields) => {
stack.extend(fields.iter().map(|interned| interner.get(*interned).repr));
stack.extend(fields.iter().map(|interned| interner.get_repr(*interned)));
}
UnionLayout::NullableWrapped { other_tags, .. } => {
for tag in other_tags {
stack.extend(tag.iter().map(|interned| interner.get(*interned).repr));
stack.extend(tag.iter().map(|interned| interner.get_repr(*interned)));
}
}
UnionLayout::NullableUnwrapped { other_fields, .. } => {
stack.extend(
other_fields
.iter()
.map(|interned| interner.get(*interned).repr),
.map(|interned| interner.get_repr(*interned)),
);
}
},
@ -2894,9 +2916,12 @@ impl<'a> Layout<'a> {
}
}
pub fn is_recursive_tag_union(self) -> bool {
pub fn is_recursive_tag_union<I>(self, interner: &I) -> bool
where
I: LayoutInterner<'a>,
{
matches!(
self.repr,
self.repr(interner),
LayoutRepr::Union(
UnionLayout::NullableUnwrapped { .. }
| UnionLayout::Recursive(_)
@ -3044,7 +3069,7 @@ impl<'a> Builtin<'a> {
let allocation = match self {
Builtin::Str => ptr_width,
Builtin::List(e) => {
let e = interner.get(*e);
let e = interner.get_repr(*e);
e.alignment_bytes(interner, target_info).max(ptr_width)
}
// The following are usually not heap-allocated, but they might be when inside a Box.
@ -3157,7 +3182,7 @@ fn layout_from_flat_type<'a>(
let inner_layout =
cached!(Layout::from_var(env, inner_var), criteria, env.subs);
let boxed_layout = env.cache.put_in(Layout {
repr: LayoutRepr::Boxed(inner_layout),
repr: LayoutRepr::Boxed(inner_layout).direct(),
semantic: SemanticRepr::NONE,
});
@ -3233,22 +3258,22 @@ fn layout_from_flat_type<'a>(
.iter()
.map(|(label, _)| &*arena.alloc_str(label.as_str())),
arena,
);
)
.into_bump_slice();
let semantic = SemanticRepr::record(ordered_field_names);
let result = if sortables.len() == 1 {
let repr = if sortables.len() == 1 {
// If the record has only one field that isn't zero-sized,
// unwrap it.
Ok(sortables.pop().unwrap().1)
let inner_repr = sortables.pop().unwrap().1;
inner_repr.newtype()
} else {
let layouts = Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena);
let struct_layout = Layout {
repr: LayoutRepr::Struct(layouts.into_bump_slice()),
semantic: SemanticRepr::record(ordered_field_names.into_bump_slice()),
};
Ok(env.cache.put_in(struct_layout))
LayoutRepr::Struct(layouts.into_bump_slice()).direct()
};
let result = Ok(env.cache.put_in(Layout { repr, semantic }));
Cacheable(result, criteria)
}
Tuple(elems, ext_var) => {
@ -3285,7 +3310,7 @@ fn layout_from_flat_type<'a>(
let field_layouts =
Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena).into_bump_slice();
let struct_layout = Layout {
repr: LayoutRepr::Struct(field_layouts),
repr: LayoutRepr::Struct(field_layouts).direct(),
semantic: SemanticRepr::tuple(field_layouts.len()),
};
@ -3720,11 +3745,11 @@ where
layouts.sort_by(|layout1, layout2| {
let size1 = env
.cache
.get_in(*layout1)
.get_repr(*layout1)
.alignment_bytes(&env.cache.interner, env.target_info);
let size2 = env
.cache
.get_in(*layout2)
.get_repr(*layout2)
.alignment_bytes(&env.cache.interner, env.target_info);
size2.cmp(&size1)
@ -3782,11 +3807,11 @@ where
arg_layouts.sort_by(|layout1, layout2| {
let size1 = env
.cache
.get_in(*layout1)
.get_repr(*layout1)
.alignment_bytes(&env.cache.interner, env.target_info);
let size2 = env
.cache
.get_in(*layout2)
.get_repr(*layout2)
.alignment_bytes(&env.cache.interner, env.target_info);
size2.cmp(&size1)
@ -3964,7 +3989,7 @@ where
== env
.subs
.get_root_key_without_compacting(opt_rec_var.unwrap())
&& layout.is_recursive_tag_union();
&& layout.is_recursive_tag_union(&env.cache.interner);
let arg_layout = if self_recursion {
Layout::NAKED_RECURSIVE_PTR
@ -3994,11 +4019,11 @@ where
arg_layouts.sort_by(|layout1, layout2| {
let size1 = env
.cache
.get_in(*layout1)
.get_repr(*layout1)
.alignment_bytes(&env.cache.interner, env.target_info);
let size2 = env
.cache
.get_in(*layout2)
.get_repr(*layout2)
.alignment_bytes(&env.cache.interner, env.target_info);
size2.cmp(&size1)
@ -4133,13 +4158,13 @@ where
Never => Layout::VOID,
Unit => env
.cache
.put_in(Layout::new(LayoutRepr::UNIT, compute_semantic())),
.put_in(Layout::new(LayoutRepr::UNIT.direct(), compute_semantic())),
BoolUnion { .. } => env
.cache
.put_in(Layout::new(LayoutRepr::BOOL, compute_semantic())),
.put_in(Layout::new(LayoutRepr::BOOL.direct(), compute_semantic())),
ByteUnion(_) => env
.cache
.put_in(Layout::new(LayoutRepr::U8, compute_semantic())),
.put_in(Layout::new(LayoutRepr::U8.direct(), compute_semantic())),
Newtype {
arguments: field_layouts,
..
@ -4148,7 +4173,7 @@ where
field_layouts[0]
} else {
env.cache
.put_in_no_semantic(LayoutRepr::struct_(field_layouts.into_bump_slice()))
.put_in_direct_no_semantic(LayoutRepr::struct_(field_layouts.into_bump_slice()))
};
answer1
@ -4159,8 +4184,9 @@ where
if data_tag_arguments.len() == 1 {
data_tag_arguments[0]
} else {
env.cache
.put_in_no_semantic(LayoutRepr::struct_(data_tag_arguments.into_bump_slice()))
env.cache.put_in_direct_no_semantic(LayoutRepr::struct_(
data_tag_arguments.into_bump_slice(),
))
}
}
Wrapped(variant) => {
@ -4176,7 +4202,8 @@ where
let layout = Layout {
repr: LayoutRepr::Union(UnionLayout::NonRecursive(
tag_layouts.into_bump_slice(),
)),
))
.direct(),
semantic: SemanticRepr::NONE,
};
env.cache.put_in(layout)
@ -4292,14 +4319,14 @@ where
env.cache.interner.insert_recursive(
env.arena,
Layout {
repr: LayoutRepr::Union(union_layout),
repr: LayoutRepr::Union(union_layout).direct(),
semantic: SemanticRepr::NONE,
},
)
} else {
// There are no naked recursion pointers, so we can insert the layout as-is.
env.cache.interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
repr: LayoutRepr::Union(union_layout).direct(),
semantic: SemanticRepr::NONE,
})
};
@ -4435,7 +4462,7 @@ pub(crate) fn list_layout_from_elem<'a>(
};
let list_layout = env.cache.put_in(Layout {
repr: LayoutRepr::Builtin(Builtin::List(element_layout)),
repr: LayoutRepr::Builtin(Builtin::List(element_layout)).direct(),
semantic: SemanticRepr::NONE,
});
@ -4589,8 +4616,12 @@ pub fn cmp_fields<'a, L: Ord, I>(
where
I: LayoutInterner<'a>,
{
let size1 = interner.get(layout1).alignment_bytes(interner, target_info);
let size2 = interner.get(layout2).alignment_bytes(interner, target_info);
let size1 = interner
.get_repr(layout1)
.alignment_bytes(interner, target_info);
let size2 = interner
.get_repr(layout2)
.alignment_bytes(interner, target_info);
size2.cmp(&size1).then(label1.cmp(label2))
}
@ -4613,19 +4644,16 @@ mod test {
let a = &[Layout::UNIT] as &[_];
let b = &[interner.insert(Layout {
repr: LayoutRepr::LambdaSet(lambda_set),
repr: LayoutRepr::LambdaSet(lambda_set).direct(),
semantic: SemanticRepr::NONE,
})] as &[_];
let tt = [a, b];
let layout = Layout {
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&tt)),
semantic: SemanticRepr::NONE,
};
let repr = LayoutRepr::Union(UnionLayout::NonRecursive(&tt));
let target_info = TargetInfo::default_x86_64();
assert_eq!(layout.stack_size(&interner, target_info), 1);
assert_eq!(layout.alignment_bytes(&interner, target_info), 1);
assert_eq!(repr.stack_size(&interner, target_info), 1);
assert_eq!(repr.alignment_bytes(&interner, target_info), 1);
}
#[test]
@ -4633,29 +4661,28 @@ mod test {
let mut interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64());
let ok_tag = &[interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)),
repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)).direct(),
semantic: SemanticRepr::NONE,
})];
let err_tag = &[Layout::UNIT];
let tags = [ok_tag as &[_], err_tag as &[_]];
let union_layout = UnionLayout::NonRecursive(&tags as &[_]);
let layout = Layout {
repr: LayoutRepr::Union(union_layout),
semantic: SemanticRepr::NONE,
};
let repr = LayoutRepr::Union(union_layout);
let target_info = TargetInfo::default_x86_64();
assert_eq!(
layout.stack_size_without_alignment(&interner, target_info),
8
);
assert_eq!(repr.stack_size_without_alignment(&interner, target_info), 8);
}
#[test]
fn void_stack_size() {
let interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64());
let target_info = TargetInfo::default_x86_64();
assert_eq!(Layout::VOID_NAKED.stack_size(&interner, target_info), 0);
assert_eq!(
Layout::VOID_NAKED
.repr(&interner)
.stack_size(&interner, target_info),
0
);
}
#[test]

View file

@ -14,7 +14,7 @@ use roc_target::TargetInfo;
use crate::layout::LayoutRepr;
use super::{LambdaSet, Layout, SeenRecPtrs, SemanticRepr, UnionLayout};
use super::{LambdaSet, Layout, LayoutWrapper, SeenRecPtrs, SemanticRepr, UnionLayout};
macro_rules! cache_interned_layouts {
($($i:literal, $name:ident, $vis:vis, $layout:expr)*; $total_constants:literal) => {
@ -50,7 +50,7 @@ macro_rules! cache_interned_layouts {
macro_rules! nosema {
($r:expr) => {
Layout {
repr: $r,
repr: $r.direct(),
semantic: SemanticRepr::NONE,
}
};
@ -119,11 +119,11 @@ impl_to_from_int_width! {
impl<'a> Layout<'a> {
pub(super) const VOID_NAKED: Self = Layout {
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&[])),
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&[])).direct(),
semantic: SemanticRepr::NONE,
};
pub(super) const UNIT_NAKED: Self = Layout {
repr: LayoutRepr::Struct(&[]),
repr: LayoutRepr::Struct(&[]).direct(),
semantic: SemanticRepr::EMPTY_RECORD,
};
@ -154,8 +154,8 @@ pub trait LayoutInterner<'a>: Sized {
/// Interns a value with no semantic representation, returning its interned representation.
/// If the value has been interned before, the old interned representation will be re-used.
fn insert_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
self.insert(Layout::no_semantic(repr))
fn insert_direct_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
self.insert(Layout::no_semantic(repr.direct()))
}
/// Creates a [LambdaSet], including caching the [LayoutRepr::LambdaSet] representation of the
@ -181,60 +181,78 @@ pub trait LayoutInterner<'a>: Sized {
//
// Convenience methods
fn get_repr(&self, mut key: InLayout<'a>) -> LayoutRepr<'a> {
loop {
match self.get(key).repr {
LayoutWrapper::Direct(repr) => return repr,
LayoutWrapper::Newtype(inner) => key = inner,
}
}
}
fn get_semantic(&self, key: InLayout<'a>) -> SemanticRepr<'a> {
self.get(key).semantic
}
fn eq_repr(&self, a: InLayout<'a>, b: InLayout<'a>) -> bool {
self.get(a).repr == self.get(b).repr
self.get_repr(a) == self.get_repr(b)
}
fn target_info(&self) -> TargetInfo;
fn alignment_bytes(&self, layout: InLayout<'a>) -> u32 {
self.get(layout).alignment_bytes(self, self.target_info())
self.get_repr(layout)
.alignment_bytes(self, self.target_info())
}
fn allocation_alignment_bytes(&self, layout: InLayout<'a>) -> u32 {
self.get(layout)
self.get_repr(layout)
.allocation_alignment_bytes(self, self.target_info())
}
fn stack_size(&self, layout: InLayout<'a>) -> u32 {
self.get(layout).stack_size(self, self.target_info())
self.get_repr(layout).stack_size(self, self.target_info())
}
fn stack_size_and_alignment(&self, layout: InLayout<'a>) -> (u32, u32) {
self.get(layout)
self.get_repr(layout)
.stack_size_and_alignment(self, self.target_info())
}
fn stack_size_without_alignment(&self, layout: InLayout<'a>) -> u32 {
self.get(layout)
self.get_repr(layout)
.stack_size_without_alignment(self, self.target_info())
}
fn contains_refcounted(&self, layout: InLayout<'a>) -> bool {
self.get(layout).contains_refcounted(self)
self.get_repr(layout).contains_refcounted(self)
}
fn is_refcounted(&self, layout: InLayout<'a>) -> bool {
self.get(layout).is_refcounted()
self.get_repr(layout).is_refcounted()
}
fn is_passed_by_reference(&self, layout: InLayout<'a>) -> bool {
self.get(layout)
self.get_repr(layout)
.is_passed_by_reference(self, self.target_info())
}
fn runtime_representation(&self, layout: InLayout<'a>) -> Layout<'a> {
self.get(layout).runtime_representation(self)
fn runtime_representation(&self, layout: InLayout<'a>) -> LayoutRepr<'a> {
self.get_repr(self.runtime_representation_in(layout))
}
fn runtime_representation_in(&self, layout: InLayout<'a>) -> InLayout<'a> {
Layout::runtime_representation_in(layout, self)
}
fn chase_recursive(&self, mut layout: InLayout<'a>) -> Layout<'a> {
fn has_varying_stack_size(&self, layout: InLayout<'a>, arena: &'a Bump) -> bool {
self.get_repr(layout).has_varying_stack_size(self, arena)
}
fn chase_recursive(&self, mut layout: InLayout<'a>) -> LayoutRepr<'a> {
loop {
let lay = self.get(layout);
match lay.repr {
let lay = self.get_repr(layout);
match lay {
LayoutRepr::RecursivePointer(l) => layout = l,
_ => return lay,
}
@ -243,7 +261,7 @@ pub trait LayoutInterner<'a>: Sized {
fn chase_recursive_in(&self, mut layout: InLayout<'a>) -> InLayout<'a> {
loop {
match self.get(layout).repr {
match self.get_repr(layout) {
LayoutRepr::RecursivePointer(l) => layout = l,
_ => return layout,
}
@ -251,7 +269,7 @@ pub trait LayoutInterner<'a>: Sized {
}
fn safe_to_memcpy(&self, layout: InLayout<'a>) -> bool {
self.get(layout).safe_to_memcpy(self)
self.get_repr(layout).safe_to_memcpy(self)
}
/// Checks if two layouts are equivalent up to isomorphism.
@ -298,7 +316,7 @@ pub trait LayoutInterner<'a>: Sized {
{
use LayoutRepr::*;
match self.get(layout).repr {
match self.get_repr(layout) {
Builtin(builtin) => builtin.to_doc(alloc, self, seen_rec, parens),
Struct(field_layouts) => {
let fields_doc = field_layouts
@ -455,6 +473,10 @@ impl<'a> InLayout<'a> {
Self(index, PhantomData)
}
pub(crate) const fn newtype(self) -> LayoutWrapper<'a> {
LayoutWrapper::Newtype(self)
}
pub fn index(&self) -> usize {
self.0
}
@ -665,7 +687,7 @@ impl<'a> GlobalLayoutInterner<'a> {
..normalized
};
let lambda_set_layout = Layout {
repr: LayoutRepr::LambdaSet(full_lambda_set),
repr: LayoutRepr::LambdaSet(full_lambda_set).direct(),
semantic: SemanticRepr::NONE,
};
@ -974,7 +996,7 @@ macro_rules! st_impl {
full_layout: slot,
};
let lay = Layout {
repr: LayoutRepr::LambdaSet(lambda_set),
repr: LayoutRepr::LambdaSet(lambda_set).direct(),
semantic: SemanticRepr::NONE
};
self.vec[slot.0] = lay;
@ -1035,7 +1057,7 @@ mod reify {
use bumpalo::{collections::Vec, Bump};
use roc_module::symbol::Symbol;
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, UnionLayout};
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, LayoutWrapper, UnionLayout};
use super::{InLayout, LayoutInterner, NeedsRecursionPointerFixup};
@ -1046,7 +1068,24 @@ mod reify {
slot: InLayout<'a>,
normalized_layout: Layout<'a>,
) -> Layout<'a> {
let repr = match normalized_layout.repr {
let Layout { repr, semantic } = normalized_layout;
let reified_repr = match repr {
LayoutWrapper::Direct(repr) => {
reify_recursive_layout_repr(arena, interner, slot, repr).direct()
}
LayoutWrapper::Newtype(inner) => reify_layout(arena, interner, slot, inner).newtype(),
};
Layout::new(reified_repr, semantic)
}
fn reify_recursive_layout_repr<'a>(
arena: &'a Bump,
interner: &mut impl LayoutInterner<'a>,
slot: InLayout<'a>,
repr: LayoutRepr<'a>,
) -> LayoutRepr<'a> {
match repr {
LayoutRepr::Builtin(builtin) => {
LayoutRepr::Builtin(reify_builtin(arena, interner, slot, builtin))
}
@ -1063,10 +1102,6 @@ mod reify {
// another recursive union's layout, do not change it.
LayoutRepr::RecursivePointer(if l == Layout::VOID { slot } else { l })
}
};
Layout {
repr,
semantic: normalized_layout.semantic,
}
}
@ -1244,7 +1279,7 @@ mod equiv {
continue;
}
use LayoutRepr::*;
match (interner.get(l1).repr, interner.get(l2).repr) {
match (interner.get_repr(l1), interner.get_repr(l2)) {
(RecursivePointer(rec), _) => stack.push((rec, l2)),
(_, RecursivePointer(rec)) => stack.push((l1, rec)),
(Builtin(b1), Builtin(b2)) => {
@ -1340,7 +1375,7 @@ mod equiv {
pub mod dbg {
use roc_module::symbol::Symbol;
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, UnionLayout};
use crate::layout::{Builtin, LambdaSet, LayoutRepr, UnionLayout};
use super::{InLayout, LayoutInterner};
@ -1348,7 +1383,8 @@ pub mod dbg {
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for Dbg<'a, 'r, I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Layout { repr, semantic } = self.0.get(self.1);
let repr = self.0.get_repr(self.1);
let semantic = self.0.get_semantic(self.1);
f.debug_struct("Layout")
.field("repr", &DbgRepr(self.0, &repr))
@ -1544,7 +1580,7 @@ mod insert_lambda_set {
let lambda_set =
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, FIXUP, Layout::UNIT);
let lambda_set_layout_in = interner.insert(Layout {
repr: LayoutRepr::LambdaSet(lambda_set),
repr: LayoutRepr::LambdaSet(lambda_set).direct(),
semantic: SemanticRepr::NONE,
});
assert_eq!(lambda_set.full_layout, lambda_set_layout_in);
@ -1603,15 +1639,16 @@ mod insert_recursive_layout {
fn make_layout<'a>(arena: &'a Bump, interner: &mut impl LayoutInterner<'a>) -> Layout<'a> {
let list_rec = Layout {
repr: LayoutRepr::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR)),
repr: LayoutRepr::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR)).direct(),
semantic: SemanticRepr::NONE,
};
let repr = LayoutRepr::Union(UnionLayout::Recursive(&*arena.alloc([
&*arena.alloc([interner.insert(list_rec)]),
&*arena.alloc_slice_fill_iter([interner.insert_no_semantic(LayoutRepr::struct_(
&*arena.alloc([Layout::NAKED_RECURSIVE_PTR]),
))]),
])));
&*arena.alloc_slice_fill_iter([interner.insert_direct_no_semantic(
LayoutRepr::struct_(&*arena.alloc([Layout::NAKED_RECURSIVE_PTR])),
)]),
])))
.direct();
Layout {
repr,
semantic: SemanticRepr::NONE,
@ -1619,11 +1656,11 @@ mod insert_recursive_layout {
}
fn get_rec_ptr_index<'a>(interner: &impl LayoutInterner<'a>, layout: InLayout<'a>) -> usize {
match interner.chase_recursive(layout).repr {
match interner.chase_recursive(layout) {
LayoutRepr::Union(UnionLayout::Recursive(&[&[l1], &[l2]])) => {
match (interner.get(l1).repr, interner.get(l2).repr) {
match (interner.get_repr(l1), interner.get_repr(l2)) {
(LayoutRepr::Builtin(Builtin::List(l1)), LayoutRepr::Struct(&[l2])) => {
match (interner.get(l1).repr, interner.get(l2).repr) {
match (interner.get_repr(l1), interner.get_repr(l2)) {
(
LayoutRepr::RecursivePointer(i1),
LayoutRepr::RecursivePointer(i2),

View file

@ -1277,7 +1277,7 @@ fn symbol_layout_reusability<'a>(
symbol: &Symbol,
layout: &InLayout<'a>,
) -> Reuse<'a> {
match layout_interner.get(*layout).repr {
match layout_interner.get_repr(*layout) {
LayoutRepr::Union(union_layout) => {
can_reuse_union_layout_tag(union_layout, environment.get_symbol_tag(symbol))
}

View file

@ -3,7 +3,7 @@ use crate::parser::{BadInputError, EExpr, ParseResult, Parser};
use crate::state::State;
use bumpalo::collections::vec::Vec;
use bumpalo::Bump;
use roc_region::all::Position;
use roc_region::all::{Position, Region};
/// A tag, for example. Must start with an uppercase letter
/// and then contain only letters and numbers afterwards - no dots allowed!
@ -254,7 +254,14 @@ pub enum BadIdent {
Start(Position),
Space(BadInputError, Position),
Underscore(Position),
UnderscoreAlone(Position),
UnderscoreInMiddle(Position),
UnderscoreAtStart {
position: Position,
/// If this variable was already declared in a pattern (e.g. \_x -> _x),
/// then this is where it was declared.
declaration_region: Option<Region>,
},
QualifiedTag(Position),
WeirdAccessor(Position),
WeirdDotAccess(Position),
@ -529,7 +536,7 @@ fn chomp_identifier_chain<'a>(
// to give good error messages for this case
Err((
chomped as u32 + 1,
BadIdent::Underscore(pos.bump_column(chomped as u32 + 1)),
BadIdent::UnderscoreInMiddle(pos.bump_column(chomped as u32 + 1)),
))
} else if first_is_uppercase {
// just one segment, starting with an uppercase letter; that's a tag

View file

@ -335,7 +335,11 @@ impl Problem {
})
| Problem::RuntimeError(RuntimeError::UnsupportedPattern(region))
| Problem::RuntimeError(RuntimeError::MalformedPattern(_, region))
| Problem::RuntimeError(RuntimeError::LookupNotInScope(Loc { region, .. }, _))
| Problem::RuntimeError(RuntimeError::LookupNotInScope {
loc_name: Loc { region, .. },
suggestion_options: _,
underscored_suggestion_region: _,
})
| Problem::RuntimeError(RuntimeError::OpaqueNotDefined {
usage: Loc { region, .. },
..
@ -505,7 +509,14 @@ pub enum RuntimeError {
UnresolvedTypeVar,
ErroneousType,
LookupNotInScope(Loc<Ident>, MutSet<Box<str>>),
LookupNotInScope {
loc_name: Loc<Ident>,
/// All of the names in scope (for the error message)
suggestion_options: MutSet<Box<str>>,
/// If the unfound variable is `name` and there's an ignored variable called `_name`,
/// this is the region where `_name` is defined (for the error message)
underscored_suggestion_region: Option<Region>,
},
OpaqueNotDefined {
usage: Loc<Ident>,
opaques_in_scope: MutSet<Box<str>>,

View file

@ -932,6 +932,29 @@ fn encode_derived_generic_tag_with_different_field_types() {
)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn specialize_unique_newtype_records() {
assert_evals_to!(
indoc!(
r#"
app "test"
imports [Encode, Json]
provides [main] to "./platform"
main =
when Str.fromUtf8 (Encode.toBytes {a: Bool.true} Json.json) is
Ok s -> when Str.fromUtf8 (Encode.toBytes {b: Bool.true} Json.json) is
Ok t -> "\(s)\(t)"
_ -> "<bad>"
_ -> "<bad>"
"#
),
RocStr::from(r#"{"a":true}{"b":true}"#),
RocStr
)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn decode_use_stdlib() {

View file

@ -17,6 +17,8 @@ use roc_mono::layout::{LayoutRepr, STLayoutInterner};
#[cfg(test)]
use roc_std::{RocList, RocStr, U128};
use crate::helpers::with_larger_debug_stack;
#[test]
fn width_and_alignment_u8_u8() {
use roc_mono::layout::Layout;
@ -28,7 +30,7 @@ fn width_and_alignment_u8_u8() {
let t = &[Layout::U8] as &[_];
let tt = [t, t];
let layout = Layout::no_semantic(LayoutRepr::Union(UnionLayout::NonRecursive(&tt)));
let layout = LayoutRepr::Union(UnionLayout::NonRecursive(&tt));
assert_eq!(layout.alignment_bytes(&interner, target_info), 1);
assert_eq!(layout.stack_size(&interner, target_info), 2);
@ -2174,25 +2176,25 @@ fn issue_5162_recast_nested_nullable_unwrapped_layout() {
assert_evals_to!(
indoc!(
r###"
app "test" provides [main] to "./platform"
app "test" provides [main] to "./platform"
Concept : [
AtomicConcept,
ExistentialRestriction { role : Str, concept : Concept }
]
Concept : [
AtomicConcept,
ExistentialRestriction { role : Str, concept : Concept }
]
bottom : Concept
bottom = AtomicConcept
bottom : Concept
bottom = AtomicConcept
main =
when Dict.single bottom 0 is
_ -> Bool.true
"###
main =
when Dict.single bottom 0 is
_ -> Bool.true
"###
),
true,
bool
);
})
});
}
#[test]

View file

@ -97,7 +97,7 @@ procedure Test.2 (Test.6):
decref Test.6;
jump #Derived_gen.0;
else
let Test.9 : List [<r>C List *self, C *self] = UnionAtIndex (Id 0) (Index 0) Test.6;
let Test.9 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = UnionAtIndex (Id 0) (Index 0) Test.6;
joinpoint #Derived_gen.2:
let Test.24 : {} = Struct {};
let Test.23 : List Str = CallByName List.5 Test.9 Test.24;
@ -116,7 +116,7 @@ procedure Test.2 (Test.6):
jump #Derived_gen.2;
procedure Test.0 ():
let Test.32 : List [<r>C List *self, C *self] = Array [];
let Test.32 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = Array [];
let Test.15 : [<r>C List *self, C *self] = TagId(0) Test.32;
let Test.14 : Str = CallByName Test.2 Test.15;
ret Test.14;

View file

@ -0,0 +1,12 @@
procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Test.1 ():
let Test.0 : Str = "";
dbg Test.0;
dec Test.0;
let Test.3 : Int1 = CallByName Bool.2;
expect Test.3;
let Test.2 : {} = Struct {};
ret Test.2;

View file

@ -803,8 +803,8 @@ procedure Json.81 (Json.801, Json.802):
procedure Json.831 (Json.1492):
let Json.1867 : List Str = StructAtIndex 1 Json.1492;
let #Derived_gen.28 : List Str = StructAtIndex 0 Json.1492;
dec #Derived_gen.28;
let #Derived_gen.29 : List Str = StructAtIndex 0 Json.1492;
dec #Derived_gen.29;
ret Json.1867;
procedure Json.839 (Json.1213):
@ -1478,8 +1478,8 @@ procedure Str.9 (Str.79):
else
let Str.300 : U8 = StructAtIndex 3 Str.80;
let Str.301 : U64 = StructAtIndex 0 Str.80;
let #Derived_gen.29 : Str = StructAtIndex 1 Str.80;
dec #Derived_gen.29;
let #Derived_gen.28 : Str = StructAtIndex 1 Str.80;
dec #Derived_gen.28;
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
ret Str.298;

View file

@ -725,14 +725,14 @@ procedure Json.81 (Json.801, Json.802):
procedure Json.831 (Json.1492):
let Json.1493 : List Str = StructAtIndex 1 Json.1492;
let #Derived_gen.14 : List Str = StructAtIndex 0 Json.1492;
dec #Derived_gen.14;
let #Derived_gen.16 : List Str = StructAtIndex 0 Json.1492;
dec #Derived_gen.16;
ret Json.1493;
procedure Json.839 (Json.1213):
let Json.1214 : List Str = StructAtIndex 1 Json.1213;
let #Derived_gen.16 : List Str = StructAtIndex 0 Json.1213;
dec #Derived_gen.16;
let #Derived_gen.15 : List Str = StructAtIndex 0 Json.1213;
dec #Derived_gen.15;
ret Json.1214;
procedure Json.86 (Json.808):
@ -1362,8 +1362,8 @@ procedure Str.9 (Str.79):
else
let Str.300 : U8 = StructAtIndex 3 Str.80;
let Str.301 : U64 = StructAtIndex 0 Str.80;
let #Derived_gen.15 : Str = StructAtIndex 1 Str.80;
dec #Derived_gen.15;
let #Derived_gen.14 : Str = StructAtIndex 1 Str.80;
dec #Derived_gen.14;
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
ret Str.298;

View file

@ -732,14 +732,14 @@ procedure Json.81 (Json.801, Json.802):
procedure Json.831 (Json.1492):
let Json.1493 : List Str = StructAtIndex 1 Json.1492;
let #Derived_gen.19 : List Str = StructAtIndex 0 Json.1492;
dec #Derived_gen.19;
let #Derived_gen.20 : List Str = StructAtIndex 0 Json.1492;
dec #Derived_gen.20;
ret Json.1493;
procedure Json.839 (Json.1213):
let Json.1214 : List Str = StructAtIndex 1 Json.1213;
let #Derived_gen.20 : List Str = StructAtIndex 0 Json.1213;
dec #Derived_gen.20;
let #Derived_gen.19 : List Str = StructAtIndex 0 Json.1213;
dec #Derived_gen.19;
ret Json.1214;
procedure Json.86 (Json.808):

View file

@ -1,7 +1,13 @@
procedure Test.1 (Test.4):
ret Test.4;
let Test.13 : [C Str, C Str] = TagId(0) Test.4;
ret Test.13;
procedure Test.5 (Test.12, Test.4):
procedure Test.1 (Test.4):
let Test.18 : [C Str, C Str] = TagId(0) Test.4;
ret Test.18;
procedure Test.5 (Test.12, #Attr.12):
let Test.4 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12;
dec Test.4;
let Test.14 : Str = "";
ret Test.14;
@ -11,13 +17,13 @@ procedure Test.0 ():
joinpoint Test.9 Test.3:
ret Test.3;
in
let Test.19 : Int1 = true;
let Test.20 : Int1 = lowlevel Eq Test.19 Test.2;
if Test.20 then
let Test.20 : Int1 = true;
let Test.21 : Int1 = lowlevel Eq Test.20 Test.2;
if Test.21 then
let Test.15 : Str = "";
let Test.10 : Str = CallByName Test.1 Test.15;
let Test.10 : [C Str, C Str] = CallByName Test.1 Test.15;
jump Test.9 Test.10;
else
let Test.18 : Str = "";
let Test.16 : Str = CallByName Test.1 Test.18;
let Test.19 : Str = "";
let Test.16 : [C Str, C Str] = CallByName Test.1 Test.19;
jump Test.9 Test.16;

View file

@ -1854,8 +1854,7 @@ fn instantiate_annotated_as_recursive_alias_multiple_polymorphic_expr() {
)
}
#[mono_test]
#[cfg(not(debug_assertions))]
#[mono_test(large_stack = "true")]
fn encode_derived_record_one_field_string() {
indoc!(
r#"
@ -1872,8 +1871,7 @@ fn encode_derived_record_one_field_string() {
)
}
#[mono_test]
#[cfg(not(debug_assertions))]
#[mono_test(large_stack = "true")]
fn encode_derived_record_two_field_strings() {
indoc!(
r#"
@ -1890,8 +1888,7 @@ fn encode_derived_record_two_field_strings() {
)
}
#[mono_test]
#[cfg(not(debug_assertions))]
#[mono_test(large_stack = "true")]
fn encode_derived_nested_record_string() {
indoc!(
r#"
@ -3078,3 +3075,16 @@ fn record_update() {
"#
)
}
#[mono_test(mode = "test")]
fn dbg_in_expect() {
indoc!(
r###"
interface Test exposes [] imports []
expect
dbg ""
Bool.true
"###
)
}

View file

@ -9,6 +9,7 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream {
let mut no_check = false;
let mut allow_type_errors = false;
let mut mode = "exec".to_owned();
let mut large_stack = false;
for arg in syn::parse_macro_input!(args as syn::AttributeArgs) {
use syn::{Lit, Meta, MetaNameValue, NestedMeta};
if let NestedMeta::Meta(Meta::NameValue(MetaNameValue {
@ -26,6 +27,9 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream {
if path.is_ident("allow_type_errors") {
allow_type_errors = true;
}
if path.is_ident("large_stack") {
large_stack = true;
}
}
}
@ -44,8 +48,11 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream {
#[test]
#(#attributes)*
#visibility fn #name(#args) {
compiles_to_ir(#name_str, #body, &#mode, #allow_type_errors, #no_check);
if #large_stack {
with_larger_debug_stack(|| compiles_to_ir(#name_str, #body, &#mode, #allow_type_errors, #no_check));
} else {
compiles_to_ir(#name_str, #body, &#mode, #allow_type_errors, #no_check);
}
}
};
result.into()

View file

@ -2,7 +2,7 @@ Closure(
[
@1-11 MalformedIdent(
"the_answer",
Underscore(
UnderscoreInMiddle(
@5,
),
),

View file

@ -31,7 +31,7 @@ Defs(
@5-8 SpaceBefore(
MalformedIdent(
"n_p",
Underscore(
UnderscoreInMiddle(
@7,
),
),

View file

@ -416,9 +416,10 @@ pub fn load_types(
let layout = layout_cache.interner.get(in_layout);
// dbg!(layout);
if layout.has_varying_stack_size(&layout_cache.interner, arena) {
if layout_cache
.interner
.has_varying_stack_size(in_layout, arena)
{
let ident_ids = interns.all_ident_ids.get_mut(&home).unwrap();
let answer = generate_glue_procs(
home,

View file

@ -1383,28 +1383,26 @@ fn add_type_help<'a>(
add_tag_union(env, opt_name, tags, var, types, layout, Some(rec_root))
}
Content::Structure(FlatType::Apply(symbol, _)) => {
match env.layout_cache.get_in(layout).repr {
LayoutRepr::Builtin(builtin) => {
add_builtin_type(env, builtin, var, opt_name, types, layout)
}
_ => {
if symbol.is_builtin() {
todo!(
"Handle Apply for builtin symbol {:?} and layout {:?}",
symbol,
layout
)
} else {
todo!(
"Handle non-builtin Apply for symbol {:?} and layout {:?}",
symbol,
layout
)
}
Content::Structure(FlatType::Apply(symbol, _)) => match env.layout_cache.get_repr(layout) {
LayoutRepr::Builtin(builtin) => {
add_builtin_type(env, builtin, var, opt_name, types, layout)
}
_ => {
if symbol.is_builtin() {
todo!(
"Handle Apply for builtin symbol {:?} and layout {:?}",
symbol,
layout
)
} else {
todo!(
"Handle non-builtin Apply for symbol {:?} and layout {:?}",
symbol,
layout
)
}
}
}
},
Content::Structure(FlatType::Func(args, closure_var, ret_var)) => {
let is_toplevel = false; // or in any case, we cannot assume that we are
@ -1432,7 +1430,7 @@ fn add_type_help<'a>(
}
Content::Alias(name, alias_vars, real_var, _) => {
if name.is_builtin() {
match env.layout_cache.get_in(layout).repr {
match env.layout_cache.get_repr(layout) {
LayoutRepr::Builtin(builtin) => {
add_builtin_type(env, builtin, var, opt_name, types, layout)
}
@ -1687,7 +1685,7 @@ fn add_builtin_type<'a>(
Alias(Symbol::DICT_DICT, _alias_variables, alias_var, AliasKind::Opaque),
) => {
match (
env.layout_cache.get_in(elem_layout).repr,
env.layout_cache.get_repr(elem_layout),
env.subs.get_content_without_compacting(*alias_var),
) {
(
@ -1737,7 +1735,7 @@ fn add_builtin_type<'a>(
Alias(Symbol::SET_SET, _alias_vars, alias_var, AliasKind::Opaque),
) => {
match (
env.layout_cache.get_in(elem_layout).repr,
env.layout_cache.get_repr(elem_layout),
env.subs.get_content_without_compacting(*alias_var),
) {
(
@ -1842,7 +1840,10 @@ where
let layout = env.layout_cache.interner.get(in_layout);
let struct_fields = match env.glue_procs_by_layout.get(&layout) {
Some(&glue_procs) => {
debug_assert!(layout.has_varying_stack_size(&env.layout_cache.interner, arena));
debug_assert!(env
.layout_cache
.interner
.has_varying_stack_size(in_layout, arena));
let fields: Vec<(String, TypeId, Accessors)> = sortables
.into_iter()
@ -1910,7 +1911,7 @@ fn tag_union_type_from_layout<'a>(
) -> RocTagUnion {
let subs = env.subs;
match env.layout_cache.get_in(layout).repr {
match env.layout_cache.get_repr(layout) {
_ if union_tags.is_newtype_wrapper(subs)
&& matches!(
subs.get_content_without_compacting(var),
@ -2228,7 +2229,9 @@ fn single_tag_payload_fields<'a, 'b>(
// anyway just so we have some warning in case that relationship somehow didn't hold!
debug_assert_eq!(
env.glue_procs_by_layout.get(&layout).is_some(),
layout.has_varying_stack_size(&env.layout_cache.interner, env.arena)
env.layout_cache
.interner
.has_varying_stack_size(in_layout, env.arena)
);
let (tag_name, payload_vars) = single_tag_payload(union_tags, subs);
@ -2309,7 +2312,7 @@ fn struct_fields_needed<I: IntoIterator<Item = Variable>>(env: &mut Env<'_>, var
vars.into_iter().fold(0, |count, var| {
let layout = env.layout_cache.from_var(arena, var, subs).unwrap();
if env.layout_cache.get_in(layout).is_dropped_because_empty() {
if env.layout_cache.get_repr(layout).is_dropped_because_empty() {
count
} else {
count + 1

View file

@ -353,7 +353,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
};
}
let expr = match env.layout_cache.get_in(layout).repr {
let expr = match env.layout_cache.get_repr(layout) {
LayoutRepr::Builtin(Builtin::Bool) => {
app.call_function(main_fn_name, |_mem: &A::Memory, num: bool| {
bool_to_ast(env, num, env.subs.get_content_without_compacting(raw_var))
@ -475,7 +475,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
env,
mem,
addr,
layout,
env.layout_cache.get_repr(layout),
WhenRecursive::Unreachable,
env.subs.get_root_key_without_compacting(raw_var),
)
@ -496,7 +496,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
env,
mem,
addr,
layout,
env.layout_cache.get_repr(layout),
WhenRecursive::Loop(layout),
env.subs.get_root_key_without_compacting(raw_var),
)
@ -515,7 +515,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
env,
mem,
addr,
layout,
env.layout_cache.get_repr(layout),
WhenRecursive::Unreachable,
env.subs.get_root_key_without_compacting(raw_var),
)
@ -542,7 +542,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
env: &mut Env<'a, '_>,
mem: &'a M,
addr: usize,
layout: InLayout<'a>,
layout: LayoutRepr<'a>,
when_recursive: WhenRecursive<'a>,
var: Variable,
) -> Expr<'a> {
@ -557,7 +557,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
let (newtype_containers, _alias_content, raw_var) = unroll_newtypes_and_aliases(env, var);
let raw_content = env.subs.get_content_without_compacting(raw_var);
let expr = match (raw_content, env.layout_cache.get_in(layout).repr) {
let expr = match (raw_content, layout) {
(Content::Structure(FlatType::Func(_, _, _)), _) | (_, LayoutRepr::LambdaSet(_)) => {
OPAQUE_FUNCTION
}
@ -650,7 +650,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
},
WhenRecursive::Loop(union_layout),
) => {
addr_to_ast(env, mem, addr, union_layout, when_recursive, *structure)
addr_to_ast(env, mem, addr, env.layout_cache.get_repr(union_layout), when_recursive, *structure)
}
(
@ -665,9 +665,9 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
let union_layout = env.layout_cache
.from_var(env.arena, *structure, env.subs)
.expect("no layout for structure");
debug_assert!(matches!(env.layout_cache.get_in(union_layout).repr, LayoutRepr::Union(..)));
debug_assert!(matches!(env.layout_cache.get_repr(union_layout), LayoutRepr::Union(..)));
let when_recursive = WhenRecursive::Loop(union_layout);
addr_to_ast(env, mem, addr, union_layout, when_recursive, *structure)
addr_to_ast(env, mem, addr, env.layout_cache.get_repr(union_layout), when_recursive, *structure)
}
other => unreachable!("Something had a RecursivePointer layout, but instead of being a RecursionVar and having a known recursive layout, I found {:?}", other),
},
@ -873,7 +873,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
env,
mem,
addr_of_inner,
inner_layout,
env.layout_cache.get_repr(inner_layout),
WhenRecursive::Unreachable,
inner_var,
);
@ -930,7 +930,7 @@ fn list_to_ast<'a, M: ReplAppMemory>(
env,
mem,
elem_addr,
elem_layout,
env.layout_cache.get_repr(elem_layout),
WhenRecursive::Unreachable,
elem_content,
);
@ -993,7 +993,14 @@ where
let mut field_addr = addr;
for (var, layout) in sequence {
let expr = addr_to_ast(env, mem, field_addr, *layout, when_recursive, var);
let expr = addr_to_ast(
env,
mem,
field_addr,
env.layout_cache.get_repr(*layout),
when_recursive,
var,
);
let loc_expr = Loc::at_zero(expr);
output.push(&*arena.alloc(loc_expr));
@ -1029,9 +1036,7 @@ fn struct_to_ast<'a, M: ReplAppMemory>(
.unwrap();
let inner_layouts = arena.alloc([field_layout]);
let struct_layout = env
.layout_cache
.put_in_no_semantic(LayoutRepr::struct_(inner_layouts));
let struct_layout = LayoutRepr::struct_(inner_layouts);
let loc_expr = &*arena.alloc(Loc {
value: addr_to_ast(
env,
@ -1094,7 +1099,7 @@ fn struct_to_ast<'a, M: ReplAppMemory>(
env,
mem,
field_addr,
field_layout,
env.layout_cache.get_repr(field_layout),
WhenRecursive::Unreachable,
field_var,
),
@ -1175,7 +1180,7 @@ fn struct_to_ast_tuple<'a, M: ReplAppMemory>(
env,
mem,
field_addr,
elem_layout,
env.layout_cache.get_repr(elem_layout),
WhenRecursive::Unreachable,
elem_var,
),

View file

@ -1256,19 +1256,49 @@ fn to_bad_ident_expr_report<'b>(
])
}
Underscore(pos) => {
let region = Region::new(surroundings.start(), pos);
UnderscoreAlone(_pos) => {
alloc.stack([
alloc.reflow("An underscore is being used as a variable here:"),
alloc.region(lines.convert_region(surroundings)),
alloc.concat([alloc
.reflow(r"An underscore can be used to ignore a value when pattern matching, but it cannot be used as a variable.")]),
])
}
UnderscoreInMiddle(_pos) => {
alloc.stack([
alloc.reflow("Underscores are not allowed in identifier names:"),
alloc.region_with_subregion(
lines.convert_region(surroundings),
lines.convert_region(region),
),
alloc.region(lines.convert_region(surroundings)),
alloc.concat([alloc
.reflow(r"I recommend using camelCase. It's the standard style in Roc code!")]),
])
}
UnderscoreAtStart {
position: _pos,
declaration_region,
} => {
let line = "This variable's name starts with an underscore:";
alloc.stack([
match declaration_region {
None => alloc.reflow(line),
Some(declaration_region) => alloc.stack([
alloc.reflow(line),
alloc.region(lines.convert_region(declaration_region)),
alloc.reflow("But then it is used here:"),
])
},
alloc.region(lines.convert_region(surroundings)),
alloc.concat([
alloc.reflow(r"A variable's name can only start with an underscore if the variable is unused. "),
match declaration_region {
None => alloc.reflow(r"But it looks like the variable is being used here!"),
Some(_) => alloc.reflow(r"Since you are using this variable, you could remove the underscore from its name in both places."),
}
]),
])
}
BadOpaqueRef(pos) => {
use BadIdentNext::*;
let kind = "an opaque reference";
@ -1411,7 +1441,13 @@ fn to_bad_ident_pattern_report<'b>(
])
}
Underscore(pos) => {
UnderscoreAlone(..) | UnderscoreAtStart { .. } => {
unreachable!(
"it's fine to have an underscore at the beginning of an identifier in a pattern"
)
}
UnderscoreInMiddle(pos) => {
let region = Region::from_pos(pos.sub(1));
alloc.stack([
@ -1582,8 +1618,19 @@ fn pretty_runtime_error<'b>(
(title, doc) = report_shadowing(alloc, lines, original_region, shadow, kind);
}
RuntimeError::LookupNotInScope(loc_name, options) => {
doc = not_found(alloc, lines, loc_name.region, &loc_name.value, options);
RuntimeError::LookupNotInScope {
loc_name,
suggestion_options: options,
underscored_suggestion_region,
} => {
doc = not_found(
alloc,
lines,
loc_name.region,
&loc_name.value,
options,
underscored_suggestion_region,
);
title = UNRECOGNIZED_NAME;
}
RuntimeError::CircularDef(entries) => {
@ -2221,6 +2268,7 @@ fn not_found<'b>(
region: roc_region::all::Region,
name: &Ident,
options: MutSet<Box<str>>,
underscored_suggestion_region: Option<Region>,
) -> RocDocBuilder<'b> {
let mut suggestions = suggest::sort(
name.as_inline_str().as_str(),
@ -2236,7 +2284,15 @@ fn not_found<'b>(
alloc.reflow(" missing up-top"),
]);
let default_yes = alloc.reflow("Did you mean one of these?");
let default_yes = match underscored_suggestion_region {
Some(underscored_region) => alloc.stack([
alloc.reflow("There is an ignored identifier of a similar name here:"),
alloc.region(lines.convert_region(underscored_region)),
alloc.reflow("Did you mean to remove the leading underscore?"),
alloc.reflow("If not, did you mean one of these?"),
]),
None => alloc.reflow("Did you mean one of these?"),
};
let to_details = |no_suggestion_details, yes_suggestion_details| {
if suggestions.is_empty() {

View file

@ -10152,6 +10152,41 @@ In roc, functions are always written as a lambda, like{}
"###
);
test_report!(
forgot_to_remove_underscore,
indoc!(
r#"
\_foo -> foo
"#
),
|golden| pretty_assertions::assert_eq!(
golden,
indoc!(
r###"── UNRECOGNIZED NAME ───────────────────────────────────── /code/proj/Main.roc ─
Nothing is named `foo` in this scope.
4 \_foo -> foo
^^^
There is an ignored identifier of a similar name here:
4 \_foo -> foo
^^^^
Did you mean to remove the leading underscore?
If not, did you mean one of these?
Box
Bool
U8
F64
"###
),
)
);
test_report!(
call_with_underscore_identifier,
indoc!(
@ -10163,17 +10198,102 @@ In roc, functions are always written as a lambda, like{}
),
|golden| pretty_assertions::assert_eq!(
golden,
&format!(
indoc!(
r###"── SYNTAX PROBLEM ──────────────────────────────────────── /code/proj/Main.roc ─
Underscores are not allowed in identifier names:
An underscore is being used as a variable here:
6 f 1 _ 1
{}
6 f 1 _ 1
^
I recommend using camelCase. It's the standard style in Roc code!
"###,
" " // TODO make the reporter not insert extraneous spaces here in the first place!
An underscore can be used to ignore a value when pattern matching, but
it cannot be used as a variable.
"###
),
)
);
test_report!(
call_with_declared_identifier_starting_with_underscore,
indoc!(
r#"
f = \x, y, z -> x + y + z
\a, _b -> f a _b 1
"#
),
|golden| pretty_assertions::assert_eq!(
golden,
indoc!(
r###"── SYNTAX PROBLEM ──────────────────────────────────────── /code/proj/Main.roc ─
This variable's name starts with an underscore:
6 \a, _b -> f a _b 1
^^
But then it is used here:
6 \a, _b -> f a _b 1
^^
A variable's name can only start with an underscore if the variable is
unused. Since you are using this variable, you could remove the
underscore from its name in both places.
"###
),
)
);
test_report!(
call_with_undeclared_identifier_starting_with_underscore,
indoc!(
r#"
f = \x, y, z -> x + y + z
\a, _b -> f a _r 1
"#
),
|golden| pretty_assertions::assert_eq!(
golden,
indoc!(
r###"
SYNTAX PROBLEM /code/proj/Main.roc
This variable's name starts with an underscore:
6 \a, _b -> f a _r 1
^^
A variable's name can only start with an underscore if the variable is
unused. But it looks like the variable is being used here!
"###
),
)
);
test_report!(
underscore_in_middle_of_identifier,
indoc!(
r#"
f = \x, y, z -> x + y + z
\a, _b -> f a var_name 1
"#
),
|golden| pretty_assertions::assert_eq!(
golden,
indoc!(
r###"
SYNTAX PROBLEM /code/proj/Main.roc
Underscores are not allowed in identifier names:
6 \a, _b -> f a var_name 1
^^^^^^^^
I recommend using camelCase. It's the standard style in Roc code!
"###
),
)
);