mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Revert "Do some checked SoA stuff"
This reverts commit c79d7745f6eb345fd50a7cb4a2a7dd6fb6f8f1fc.
This commit is contained in:
parent
a8d3280b02
commit
b2ea0b842c
19 changed files with 432 additions and 764 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2900,7 +2900,6 @@ dependencies = [
|
||||||
"roc_error_macros",
|
"roc_error_macros",
|
||||||
"roc_module",
|
"roc_module",
|
||||||
"roc_region",
|
"roc_region",
|
||||||
"soa",
|
|
||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@ use std::sync::Arc;
|
||||||
use crate::abilities::SpecializationId;
|
use crate::abilities::SpecializationId;
|
||||||
use crate::exhaustive::{ExhaustiveContext, SketchedRows};
|
use crate::exhaustive::{ExhaustiveContext, SketchedRows};
|
||||||
use crate::expected::{Expected, PExpected};
|
use crate::expected::{Expected, PExpected};
|
||||||
|
use roc_collections::soa::{EitherIndex, Index, Slice};
|
||||||
use roc_module::ident::TagName;
|
use roc_module::ident::TagName;
|
||||||
use roc_module::symbol::{ModuleId, Symbol};
|
use roc_module::symbol::{ModuleId, Symbol};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, Variable};
|
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, Variable};
|
||||||
use roc_types::types::{Category, PatternCategory, TypeTag, Types};
|
use roc_types::types::{Category, PatternCategory, TypeTag, Types};
|
||||||
use soa::{EitherIndex, Index, Slice};
|
|
||||||
|
|
||||||
pub struct Constraints {
|
pub struct Constraints {
|
||||||
pub constraints: Vec<Constraint>,
|
pub constraints: Vec<Constraint>,
|
||||||
|
@ -131,36 +131,36 @@ impl Constraints {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const EMPTY_RECORD: Index<Cell<Index<TypeTag>>> = unsafe_index(0);
|
pub const EMPTY_RECORD: Index<Cell<Index<TypeTag>>> = Index::new(0);
|
||||||
pub const EMPTY_TAG_UNION: Index<Cell<Index<TypeTag>>> = unsafe_index(1);
|
pub const EMPTY_TAG_UNION: Index<Cell<Index<TypeTag>>> = Index::new(1);
|
||||||
pub const STR: Index<Cell<Index<TypeTag>>> = unsafe_index(2);
|
pub const STR: Index<Cell<Index<TypeTag>>> = Index::new(2);
|
||||||
|
|
||||||
pub const CATEGORY_RECORD: Index<Category> = unsafe_index(0);
|
pub const CATEGORY_RECORD: Index<Category> = Index::new(0);
|
||||||
pub const CATEGORY_FOREIGNCALL: Index<Category> = unsafe_index(1);
|
pub const CATEGORY_FOREIGNCALL: Index<Category> = Index::new(1);
|
||||||
pub const CATEGORY_OPAQUEARG: Index<Category> = unsafe_index(2);
|
pub const CATEGORY_OPAQUEARG: Index<Category> = Index::new(2);
|
||||||
pub const CATEGORY_LAMBDA: Index<Category> = unsafe_index(3);
|
pub const CATEGORY_LAMBDA: Index<Category> = Index::new(3);
|
||||||
pub const CATEGORY_CLOSURESIZE: Index<Category> = unsafe_index(4);
|
pub const CATEGORY_CLOSURESIZE: Index<Category> = Index::new(4);
|
||||||
pub const CATEGORY_STRINTERPOLATION: Index<Category> = unsafe_index(5);
|
pub const CATEGORY_STRINTERPOLATION: Index<Category> = Index::new(5);
|
||||||
pub const CATEGORY_IF: Index<Category> = unsafe_index(6);
|
pub const CATEGORY_IF: Index<Category> = Index::new(6);
|
||||||
pub const CATEGORY_WHEN: Index<Category> = unsafe_index(7);
|
pub const CATEGORY_WHEN: Index<Category> = Index::new(7);
|
||||||
pub const CATEGORY_FLOAT: Index<Category> = unsafe_index(8);
|
pub const CATEGORY_FLOAT: Index<Category> = Index::new(8);
|
||||||
pub const CATEGORY_INT: Index<Category> = unsafe_index(9);
|
pub const CATEGORY_INT: Index<Category> = Index::new(9);
|
||||||
pub const CATEGORY_NUM: Index<Category> = unsafe_index(10);
|
pub const CATEGORY_NUM: Index<Category> = Index::new(10);
|
||||||
pub const CATEGORY_LIST: Index<Category> = unsafe_index(11);
|
pub const CATEGORY_LIST: Index<Category> = Index::new(11);
|
||||||
pub const CATEGORY_STR: Index<Category> = unsafe_index(12);
|
pub const CATEGORY_STR: Index<Category> = Index::new(12);
|
||||||
pub const CATEGORY_CHARACTER: Index<Category> = unsafe_index(13);
|
pub const CATEGORY_CHARACTER: Index<Category> = Index::new(13);
|
||||||
|
|
||||||
pub const PCATEGORY_RECORD: Index<PatternCategory> = unsafe_index(0);
|
pub const PCATEGORY_RECORD: Index<PatternCategory> = Index::new(0);
|
||||||
pub const PCATEGORY_EMPTYRECORD: Index<PatternCategory> = unsafe_index(1);
|
pub const PCATEGORY_EMPTYRECORD: Index<PatternCategory> = Index::new(1);
|
||||||
pub const PCATEGORY_PATTERNGUARD: Index<PatternCategory> = unsafe_index(2);
|
pub const PCATEGORY_PATTERNGUARD: Index<PatternCategory> = Index::new(2);
|
||||||
pub const PCATEGORY_PATTERNDEFAULT: Index<PatternCategory> = unsafe_index(3);
|
pub const PCATEGORY_PATTERNDEFAULT: Index<PatternCategory> = Index::new(3);
|
||||||
pub const PCATEGORY_SET: Index<PatternCategory> = unsafe_index(4);
|
pub const PCATEGORY_SET: Index<PatternCategory> = Index::new(4);
|
||||||
pub const PCATEGORY_MAP: Index<PatternCategory> = unsafe_index(5);
|
pub const PCATEGORY_MAP: Index<PatternCategory> = Index::new(5);
|
||||||
pub const PCATEGORY_STR: Index<PatternCategory> = unsafe_index(6);
|
pub const PCATEGORY_STR: Index<PatternCategory> = Index::new(6);
|
||||||
pub const PCATEGORY_NUM: Index<PatternCategory> = unsafe_index(7);
|
pub const PCATEGORY_NUM: Index<PatternCategory> = Index::new(7);
|
||||||
pub const PCATEGORY_INT: Index<PatternCategory> = unsafe_index(8);
|
pub const PCATEGORY_INT: Index<PatternCategory> = Index::new(8);
|
||||||
pub const PCATEGORY_FLOAT: Index<PatternCategory> = unsafe_index(9);
|
pub const PCATEGORY_FLOAT: Index<PatternCategory> = Index::new(9);
|
||||||
pub const PCATEGORY_CHARACTER: Index<PatternCategory> = unsafe_index(10);
|
pub const PCATEGORY_CHARACTER: Index<PatternCategory> = Index::new(10);
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_type(&mut self, types: &Types, typ: Index<TypeTag>) -> TypeOrVar {
|
pub fn push_type(&mut self, types: &Types, typ: Index<TypeTag>) -> TypeOrVar {
|
||||||
|
@ -199,7 +199,7 @@ impl Constraints {
|
||||||
const fn push_type_variable(var: Variable) -> TypeOrVar {
|
const fn push_type_variable(var: Variable) -> TypeOrVar {
|
||||||
// that's right, we use the variable's integer value as the index
|
// that's right, we use the variable's integer value as the index
|
||||||
// that way, we don't need to push anything onto a vector
|
// that way, we don't need to push anything onto a vector
|
||||||
let index: Index<Variable> = Index::new(var.index(), self.type_slices.as_slice());
|
let index: Index<Variable> = Index::new(var.index());
|
||||||
|
|
||||||
EitherIndex::from_right(index)
|
EitherIndex::from_right(index)
|
||||||
}
|
}
|
||||||
|
@ -337,16 +337,7 @@ impl Constraints {
|
||||||
category: PatternCategory,
|
category: PatternCategory,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let category_index = {
|
let category_index = Index::push_new(&mut self.pattern_categories, category);
|
||||||
let index = Index::new(
|
|
||||||
self.pattern_categories.len() as u32,
|
|
||||||
self.pattern_categories.as_slice(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.pattern_categories.push(category);
|
|
||||||
|
|
||||||
index
|
|
||||||
};
|
|
||||||
|
|
||||||
let includes_tag = IncludesTag {
|
let includes_tag = IncludesTag {
|
||||||
type_index,
|
type_index,
|
||||||
|
@ -356,16 +347,7 @@ impl Constraints {
|
||||||
region,
|
region,
|
||||||
};
|
};
|
||||||
|
|
||||||
let includes_tag_index = {
|
let includes_tag_index = Index::push_new(&mut self.includes_tags, includes_tag);
|
||||||
let index = Index::new(
|
|
||||||
self.includes_tags.len() as u32,
|
|
||||||
self.includes_tags.as_slice(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.includes_tags.push(includes_tag);
|
|
||||||
|
|
||||||
index
|
|
||||||
};
|
|
||||||
|
|
||||||
Constraint::IncludesTag(includes_tag_index)
|
Constraint::IncludesTag(includes_tag_index)
|
||||||
}
|
}
|
||||||
|
@ -378,7 +360,7 @@ impl Constraints {
|
||||||
self.variables.extend(it);
|
self.variables.extend(it);
|
||||||
let length = self.variables.len() - start;
|
let length = self.variables.len() - start;
|
||||||
|
|
||||||
Slice::new(start as u32, length as u16, self.variables.as_slice())
|
Slice::new(start as _, length as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_types_slice<I>(&mut self, it: I) -> DefTypes
|
fn def_types_slice<I>(&mut self, it: I) -> DefTypes
|
||||||
|
@ -405,8 +387,8 @@ impl Constraints {
|
||||||
}
|
}
|
||||||
|
|
||||||
DefTypes {
|
DefTypes {
|
||||||
types: Slice::new(types_start as u32, length as u16, &self.type_slices),
|
types: Slice::new(types_start as _, length as _),
|
||||||
loc_symbols: Slice::new(loc_symbols_start as u32, length as u16, &self.loc_symbols),
|
loc_symbols: Slice::new(loc_symbols_start as _, length as _),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +399,7 @@ impl Constraints {
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Variable>,
|
I: IntoIterator<Item = Variable>,
|
||||||
{
|
{
|
||||||
let defs_and_ret_constraint = Index::new(self.constraints.len() as u32, &self.constraints);
|
let defs_and_ret_constraint = Index::new(self.constraints.len() as _);
|
||||||
|
|
||||||
self.constraints.push(defs_constraint);
|
self.constraints.push(defs_constraint);
|
||||||
self.constraints.push(Constraint::True);
|
self.constraints.push(Constraint::True);
|
||||||
|
@ -433,7 +415,7 @@ impl Constraints {
|
||||||
generalizable: Generalizable(false),
|
generalizable: Generalizable(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
let let_index = Index::new(self.let_constraints.len() as u32, &self.let_constraints);
|
let let_index = Index::new(self.let_constraints.len() as _);
|
||||||
self.let_constraints.push(let_contraint);
|
self.let_constraints.push(let_contraint);
|
||||||
|
|
||||||
Constraint::Let(let_index, Slice::default())
|
Constraint::Let(let_index, Slice::default())
|
||||||
|
@ -448,7 +430,7 @@ impl Constraints {
|
||||||
{
|
{
|
||||||
let defs_constraint = self.and_constraint(defs_constraint);
|
let defs_constraint = self.and_constraint(defs_constraint);
|
||||||
|
|
||||||
let defs_and_ret_constraint = Index::new(self.constraints.len() as u32, &self.constraints);
|
let defs_and_ret_constraint = Index::new(self.constraints.len() as _);
|
||||||
self.constraints.push(defs_constraint);
|
self.constraints.push(defs_constraint);
|
||||||
self.constraints.push(Constraint::True);
|
self.constraints.push(Constraint::True);
|
||||||
|
|
||||||
|
@ -460,7 +442,7 @@ impl Constraints {
|
||||||
generalizable: Generalizable(false),
|
generalizable: Generalizable(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
let let_index = Index::new(self.let_constraints.len() as u32, &self.let_constraints);
|
let let_index = Index::new(self.let_constraints.len() as _);
|
||||||
self.let_constraints.push(let_contraint);
|
self.let_constraints.push(let_contraint);
|
||||||
|
|
||||||
Constraint::Let(let_index, Slice::default())
|
Constraint::Let(let_index, Slice::default())
|
||||||
|
@ -483,7 +465,7 @@ impl Constraints {
|
||||||
I3::IntoIter: ExactSizeIterator,
|
I3::IntoIter: ExactSizeIterator,
|
||||||
{
|
{
|
||||||
// defs and ret constraint are stored consequtively, so we only need to store one index
|
// defs and ret constraint are stored consequtively, so we only need to store one index
|
||||||
let defs_and_ret_constraint = Index::new(self.constraints.len() as u32, &self.constraints);
|
let defs_and_ret_constraint = Index::new(self.constraints.len() as _);
|
||||||
|
|
||||||
self.constraints.push(defs_constraint);
|
self.constraints.push(defs_constraint);
|
||||||
self.constraints.push(ret_constraint);
|
self.constraints.push(ret_constraint);
|
||||||
|
@ -496,7 +478,7 @@ impl Constraints {
|
||||||
generalizable,
|
generalizable,
|
||||||
};
|
};
|
||||||
|
|
||||||
let let_index = Index::new(self.let_constraints.len() as u32, &self.let_constraints);
|
let let_index = Index::new(self.let_constraints.len() as _);
|
||||||
self.let_constraints.push(let_constraint);
|
self.let_constraints.push(let_constraint);
|
||||||
|
|
||||||
Constraint::Let(let_index, Slice::default())
|
Constraint::Let(let_index, Slice::default())
|
||||||
|
@ -532,7 +514,7 @@ impl Constraints {
|
||||||
I3::IntoIter: ExactSizeIterator,
|
I3::IntoIter: ExactSizeIterator,
|
||||||
{
|
{
|
||||||
// defs and ret constraint are stored consequtively, so we only need to store one index
|
// defs and ret constraint are stored consequtively, so we only need to store one index
|
||||||
let defs_and_ret_constraint = Index::new(self.constraints.len() as u32, &self.constraints);
|
let defs_and_ret_constraint = Index::new(self.constraints.len() as _);
|
||||||
|
|
||||||
self.constraints.push(Constraint::True);
|
self.constraints.push(Constraint::True);
|
||||||
self.constraints.push(module_constraint);
|
self.constraints.push(module_constraint);
|
||||||
|
@ -547,7 +529,7 @@ impl Constraints {
|
||||||
generalizable: Generalizable(true),
|
generalizable: Generalizable(true),
|
||||||
};
|
};
|
||||||
|
|
||||||
let let_index = Index::new(self.let_constraints.len() as u32, &self.let_constraints);
|
let let_index = Index::new(self.let_constraints.len() as _);
|
||||||
self.let_constraints.push(let_contraint);
|
self.let_constraints.push(let_contraint);
|
||||||
|
|
||||||
let pool_slice = self.variable_slice(pool_variables.iter().copied());
|
let pool_slice = self.variable_slice(pool_variables.iter().copied());
|
||||||
|
@ -568,9 +550,12 @@ impl Constraints {
|
||||||
1 => it.next().unwrap(),
|
1 => it.next().unwrap(),
|
||||||
_ => {
|
_ => {
|
||||||
let start = self.constraints.len() as u32;
|
let start = self.constraints.len() as u32;
|
||||||
|
|
||||||
self.constraints.extend(it);
|
self.constraints.extend(it);
|
||||||
|
|
||||||
let end = self.constraints.len() as u32;
|
let end = self.constraints.len() as u32;
|
||||||
let slice = Slice::new(start, (end - start) as u16, &self.constraints);
|
|
||||||
|
let slice = Slice::new(start, (end - start) as u16);
|
||||||
|
|
||||||
Constraint::And(slice)
|
Constraint::And(slice)
|
||||||
}
|
}
|
||||||
|
@ -590,9 +575,8 @@ impl Constraints {
|
||||||
match constraint {
|
match constraint {
|
||||||
Constraint::SaveTheEnvironment => true,
|
Constraint::SaveTheEnvironment => true,
|
||||||
Constraint::Let(index, _) => {
|
Constraint::Let(index, _) => {
|
||||||
let let_constraint = index.get_in(&self.let_constraints);
|
let let_constraint = &self.let_constraints[index.index()];
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let offset = let_constraint.defs_and_ret_constraint.index();
|
let offset = let_constraint.defs_and_ret_constraint.index();
|
||||||
let defs_constraint = &self.constraints[offset];
|
let defs_constraint = &self.constraints[offset];
|
||||||
let ret_constraint = &self.constraints[offset + 1];
|
let ret_constraint = &self.constraints[offset + 1];
|
||||||
|
@ -600,9 +584,8 @@ impl Constraints {
|
||||||
self.contains_save_the_environment(defs_constraint)
|
self.contains_save_the_environment(defs_constraint)
|
||||||
|| self.contains_save_the_environment(ret_constraint)
|
|| self.contains_save_the_environment(ret_constraint)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Constraint::And(slice) => {
|
Constraint::And(slice) => {
|
||||||
let constraints = slice.get_slice(&self.constraints);
|
let constraints = &self.constraints[slice.indices()];
|
||||||
|
|
||||||
constraints
|
constraints
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -684,11 +667,7 @@ impl Constraints {
|
||||||
// we add a dummy symbol to these regions, so we can store the data in the loc_symbols vec
|
// we add a dummy symbol to these regions, so we can store the data in the loc_symbols vec
|
||||||
let it = expr_regions.into_iter().map(|r| (Symbol::ATTR_ATTR, r));
|
let it = expr_regions.into_iter().map(|r| (Symbol::ATTR_ATTR, r));
|
||||||
let expr_regions = Slice::extend_new(&mut self.loc_symbols, it);
|
let expr_regions = Slice::extend_new(&mut self.loc_symbols, it);
|
||||||
let expr_regions = Slice::new(
|
let expr_regions = Slice::new(expr_regions.start() as _, expr_regions.len() as _);
|
||||||
expr_regions.start() as u32,
|
|
||||||
expr_regions.len() as u16,
|
|
||||||
&expr_regions,
|
|
||||||
);
|
|
||||||
|
|
||||||
let cycle = Cycle {
|
let cycle = Cycle {
|
||||||
def_names,
|
def_names,
|
||||||
|
@ -725,7 +704,7 @@ impl std::ops::Index<ExpectedTypeIndex> for Constraints {
|
||||||
type Output = Expected<TypeOrVar>;
|
type Output = Expected<TypeOrVar>;
|
||||||
|
|
||||||
fn index(&self, index: ExpectedTypeIndex) -> &Self::Output {
|
fn index(&self, index: ExpectedTypeIndex) -> &Self::Output {
|
||||||
index.get_in(&self.expectations)
|
&self.expectations[index.index()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,7 +712,7 @@ impl std::ops::Index<PExpectedTypeIndex> for Constraints {
|
||||||
type Output = PExpected<TypeOrVar>;
|
type Output = PExpected<TypeOrVar>;
|
||||||
|
|
||||||
fn index(&self, index: PExpectedTypeIndex) -> &Self::Output {
|
fn index(&self, index: PExpectedTypeIndex) -> &Self::Output {
|
||||||
index.get_in(&self.pattern_expectations)
|
&self.pattern_expectations[index.index()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,7 +882,3 @@ impl std::fmt::Debug for Constraint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn unsafe_index<T, U>(index: u32) -> Index<T, U> {
|
|
||||||
unsafe { Index::new_unchecked(index) }
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::pattern::{canonicalize_pattern, BindingsFromPattern, Pattern, PermitS
|
||||||
use crate::procedure::{QualifiedReference, References};
|
use crate::procedure::{QualifiedReference, References};
|
||||||
use crate::scope::{Scope, SymbolLookup};
|
use crate::scope::{Scope, SymbolLookup};
|
||||||
use crate::traverse::{walk_expr, Visitor};
|
use crate::traverse::{walk_expr, Visitor};
|
||||||
|
use roc_collections::soa::Index;
|
||||||
use roc_collections::{SendMap, VecMap, VecSet};
|
use roc_collections::{SendMap, VecMap, VecSet};
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::called_via::CalledVia;
|
use roc_module::called_via::CalledVia;
|
||||||
|
@ -26,7 +27,6 @@ use roc_region::all::{Loc, Region};
|
||||||
use roc_types::num::SingleQuoteBound;
|
use roc_types::num::SingleQuoteBound;
|
||||||
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, RedundantMark, VarStore, Variable};
|
use roc_types::subs::{ExhaustiveMark, IllegalCycleMark, RedundantMark, VarStore, Variable};
|
||||||
use roc_types::types::{Alias, Category, IndexOrField, LambdaSet, OptAbleVar, Type};
|
use roc_types::types::{Alias, Category, IndexOrField, LambdaSet, OptAbleVar, Type};
|
||||||
use soa::Index;
|
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub mod all;
|
||||||
mod reference_matrix;
|
mod reference_matrix;
|
||||||
mod small_string_interner;
|
mod small_string_interner;
|
||||||
mod small_vec;
|
mod small_vec;
|
||||||
|
pub mod soa;
|
||||||
mod vec_map;
|
mod vec_map;
|
||||||
mod vec_set;
|
mod vec_set;
|
||||||
|
|
||||||
|
|
193
crates/compiler/collections/src/soa.rs
Normal file
193
crates/compiler/collections/src/soa.rs
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
use std::usize;
|
||||||
|
|
||||||
|
/// DEPRECATED - use crates/soa instead!
|
||||||
|
|
||||||
|
pub struct Index<T> {
|
||||||
|
index: u32,
|
||||||
|
_marker: std::marker::PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Eq for Index<T> {}
|
||||||
|
|
||||||
|
impl<T> PartialEq for Index<T> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.index == other.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::hash::Hash for Index<T> {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.index.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Clone for Index<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for Index<T> {}
|
||||||
|
|
||||||
|
impl<T> std::fmt::Debug for Index<T> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Index({})", self.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Index<T> {
|
||||||
|
pub const fn new(index: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
index,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn index(self) -> usize {
|
||||||
|
self.index as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_new(vector: &mut Vec<T>, value: T) -> Index<T> {
|
||||||
|
let index = Self::new(vector.len() as _);
|
||||||
|
|
||||||
|
vector.push(value);
|
||||||
|
|
||||||
|
index
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn as_slice(self) -> Slice<T> {
|
||||||
|
Slice::new(self.index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub struct Slice<T> {
|
||||||
|
length: u16,
|
||||||
|
start: u32,
|
||||||
|
_marker: std::marker::PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Clone for Slice<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for Slice<T> {}
|
||||||
|
|
||||||
|
impl<T> std::fmt::Debug for Slice<T> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Slice(start = {}, length = {})", self.start, self.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Slice<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Slice<T> {
|
||||||
|
pub const fn empty() -> Self {
|
||||||
|
Self::new(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn new(start: u32, length: u16) -> Self {
|
||||||
|
Self {
|
||||||
|
start,
|
||||||
|
length,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_new<I>(vector: &mut Vec<T>, values: I) -> Slice<T>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = T>,
|
||||||
|
{
|
||||||
|
let start = vector.len() as u32;
|
||||||
|
|
||||||
|
vector.extend(values);
|
||||||
|
|
||||||
|
let end = vector.len() as u32;
|
||||||
|
|
||||||
|
Self::new(start, (end - start) as u16)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn len(&self) -> usize {
|
||||||
|
self.length as _
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn start(&self) -> usize {
|
||||||
|
self.start as _
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn is_empty(&self) -> bool {
|
||||||
|
self.length == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn indices(&self) -> std::ops::Range<usize> {
|
||||||
|
self.start as usize..(self.start as usize + self.length as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_iter(&self) -> impl Iterator<Item = Index<T>> {
|
||||||
|
self.indices().map(|i| Index::new(i as _))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn at(&self, i: usize) -> Index<T> {
|
||||||
|
Index::new(self.start + i as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub struct EitherIndex<T, U> {
|
||||||
|
index: u32,
|
||||||
|
_marker: std::marker::PhantomData<(T, U)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U> Clone for EitherIndex<T, U> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U> Copy for EitherIndex<T, U> {}
|
||||||
|
|
||||||
|
impl<T, U> std::fmt::Debug for EitherIndex<T, U> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Index({})", self.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U> EitherIndex<T, U> {
|
||||||
|
const MASK: u32 = 1 << 31;
|
||||||
|
|
||||||
|
pub const fn from_left(input: Index<T>) -> Self {
|
||||||
|
assert!(input.index & Self::MASK == 0);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
index: input.index,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn from_right(input: Index<U>) -> Self {
|
||||||
|
assert!(input.index & Self::MASK == 0);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
index: input.index | Self::MASK,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn split(self) -> Result<Index<T>, Index<U>> {
|
||||||
|
if self.index & Self::MASK == 0 {
|
||||||
|
Ok(Index::new(self.index))
|
||||||
|
} else {
|
||||||
|
Err(Index::new(self.index ^ Self::MASK))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrement_index(&mut self) {
|
||||||
|
self.index = self.index.saturating_sub(1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ use roc_can::expr::{
|
||||||
use roc_can::pattern::Pattern;
|
use roc_can::pattern::Pattern;
|
||||||
use roc_can::traverse::symbols_introduced_from_pattern;
|
use roc_can::traverse::symbols_introduced_from_pattern;
|
||||||
use roc_collections::all::{HumanIndex, MutMap, SendMap};
|
use roc_collections::all::{HumanIndex, MutMap, SendMap};
|
||||||
|
use roc_collections::soa::{Index, Slice};
|
||||||
use roc_collections::VecMap;
|
use roc_collections::VecMap;
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_module::symbol::{ModuleId, Symbol};
|
use roc_module::symbol::{ModuleId, Symbol};
|
||||||
|
@ -32,7 +33,6 @@ use roc_types::types::{
|
||||||
AliasKind, AnnotationSource, Category, IndexOrField, OptAbleType, PReason, Reason, RecordField,
|
AliasKind, AnnotationSource, Category, IndexOrField, OptAbleType, PReason, Reason, RecordField,
|
||||||
TypeExtension, TypeTag, Types,
|
TypeExtension, TypeTag, Types,
|
||||||
};
|
};
|
||||||
use soa::{Index, Slice};
|
|
||||||
|
|
||||||
/// This is for constraining Defs
|
/// This is for constraining Defs
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
|
|
@ -5,6 +5,7 @@ use roc_can::expected::{Expected, PExpected};
|
||||||
use roc_can::pattern::Pattern::{self, *};
|
use roc_can::pattern::Pattern::{self, *};
|
||||||
use roc_can::pattern::{DestructType, ListPatterns, RecordDestruct, TupleDestruct};
|
use roc_can::pattern::{DestructType, ListPatterns, RecordDestruct, TupleDestruct};
|
||||||
use roc_collections::all::{HumanIndex, SendMap};
|
use roc_collections::all::{HumanIndex, SendMap};
|
||||||
|
use roc_collections::soa::Index;
|
||||||
use roc_collections::VecMap;
|
use roc_collections::VecMap;
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
@ -14,7 +15,6 @@ use roc_types::types::{
|
||||||
AliasKind, AliasShared, Category, OptAbleType, PReason, PatternCategory, Reason, RecordField,
|
AliasKind, AliasShared, Category, OptAbleType, PReason, PatternCategory, Reason, RecordField,
|
||||||
Type, TypeExtension, TypeTag, Types,
|
Type, TypeExtension, TypeTag, Types,
|
||||||
};
|
};
|
||||||
use soa::Index;
|
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct PatternState {
|
pub struct PatternState {
|
||||||
|
|
|
@ -19,8 +19,6 @@ roc_error_macros = { path = "../../error_macros" }
|
||||||
bumpalo.workspace = true
|
bumpalo.workspace = true
|
||||||
encode_unicode.workspace = true
|
encode_unicode.workspace = true
|
||||||
|
|
||||||
soa.workspace = true
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion.workspace = true
|
criterion.workspace = true
|
||||||
indoc.workspace = true
|
indoc.workspace = true
|
||||||
|
|
|
@ -8,11 +8,11 @@ use crate::ident::Accessor;
|
||||||
use crate::parser::ESingleQuote;
|
use crate::parser::ESingleQuote;
|
||||||
use bumpalo::collections::{String, Vec};
|
use bumpalo::collections::{String, Vec};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
use roc_collections::soa::{EitherIndex, Index, Slice};
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
||||||
use roc_module::ident::QualifiedModuleName;
|
use roc_module::ident::QualifiedModuleName;
|
||||||
use roc_region::all::{Loc, Position, Region};
|
use roc_region::all::{Loc, Position, Region};
|
||||||
use soa::{EitherIndex, Index, Slice};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FullAst<'a> {
|
pub struct FullAst<'a> {
|
||||||
|
@ -623,7 +623,7 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
||||||
Expr::Defs(defs, expr) => {
|
Expr::Defs(defs, expr) => {
|
||||||
let any_defs_suffixed = defs.tags.iter().any(|tag| match tag.split() {
|
let any_defs_suffixed = defs.tags.iter().any(|tag| match tag.split() {
|
||||||
Ok(_) => false,
|
Ok(_) => false,
|
||||||
Err(value_index) => match value_index.get_in(&defs.value_defs) {
|
Err(value_index) => match defs.value_defs[value_index.index()] {
|
||||||
ValueDef::Body(_, loc_expr) => is_expr_suffixed(&loc_expr.value),
|
ValueDef::Body(_, loc_expr) => is_expr_suffixed(&loc_expr.value),
|
||||||
ValueDef::AnnotatedBody { body_expr, .. } => is_expr_suffixed(&body_expr.value),
|
ValueDef::AnnotatedBody { body_expr, .. } => is_expr_suffixed(&body_expr.value),
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -1025,7 +1025,7 @@ impl<'a, 'b> Iterator for RecursiveValueDefIter<'a, 'b> {
|
||||||
match self.current.tags.get(self.index) {
|
match self.current.tags.get(self.index) {
|
||||||
Some(tag) => {
|
Some(tag) => {
|
||||||
if let Err(def_index) = tag.split() {
|
if let Err(def_index) = tag.split() {
|
||||||
let def = def_index.get_in(&self.current.value_defs);
|
let def = &self.current.value_defs[def_index.index()];
|
||||||
let region = &self.current.regions[self.index];
|
let region = &self.current.regions[self.index];
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
|
@ -1195,8 +1195,8 @@ impl<'a> Defs<'a> {
|
||||||
|
|
||||||
pub fn defs(&self) -> impl Iterator<Item = Result<&TypeDef<'a>, &ValueDef<'a>>> {
|
pub fn defs(&self) -> impl Iterator<Item = Result<&TypeDef<'a>, &ValueDef<'a>>> {
|
||||||
self.tags.iter().map(|tag| match tag.split() {
|
self.tags.iter().map(|tag| match tag.split() {
|
||||||
Ok(type_index) => Ok(type_index.get_in(&self.type_defs)),
|
Ok(type_index) => Ok(&self.type_defs[type_index.index()]),
|
||||||
Err(value_index) => Err(value_index.get_in(&self.value_defs)),
|
Err(value_index) => Err(&self.value_defs[value_index.index()]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1207,13 +1207,10 @@ impl<'a> Defs<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, tag)| match tag.split() {
|
.map(|(i, tag)| match tag.split() {
|
||||||
Ok(type_index) => Ok(Loc::at(
|
Ok(type_index) => Ok(Loc::at(self.regions[i], self.type_defs[type_index.index()])),
|
||||||
self.regions[i],
|
|
||||||
*type_index.get_in(&self.type_defs),
|
|
||||||
)),
|
|
||||||
Err(value_index) => Err(Loc::at(
|
Err(value_index) => Err(Loc::at(
|
||||||
self.regions[i],
|
self.regions[i],
|
||||||
*value_index.get_in(&self.value_defs),
|
self.value_defs[value_index.index()],
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1224,14 +1221,14 @@ impl<'a> Defs<'a> {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(tag_index, tag)| match tag.split() {
|
.filter_map(|(tag_index, tag)| match tag.split() {
|
||||||
Ok(_) => None,
|
Ok(_) => None,
|
||||||
Err(value_index) => Some((tag_index, value_index.get_in(&self.value_defs))),
|
Err(value_index) => Some((tag_index, &self.value_defs[value_index.index()])),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last(&self) -> Option<Result<&TypeDef<'a>, &ValueDef<'a>>> {
|
pub fn last(&self) -> Option<Result<&TypeDef<'a>, &ValueDef<'a>>> {
|
||||||
self.tags.last().map(|tag| match tag.split() {
|
self.tags.last().map(|tag| match tag.split() {
|
||||||
Ok(type_index) => Ok(type_index.get_in(&self.type_defs)),
|
Ok(type_index) => Ok(&self.type_defs[type_index.index()]),
|
||||||
Err(value_index) => Err(value_index.get_in(&self.value_defs)),
|
Err(value_index) => Err(&self.value_defs[value_index.index()]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1243,7 +1240,7 @@ impl<'a> Defs<'a> {
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(tag_index, tag)| match tag.split() {
|
.find_map(|(tag_index, tag)| match tag.split() {
|
||||||
Ok(_) => None,
|
Ok(_) => None,
|
||||||
Err(value_index) => match *value_index.get_in(&self.value_defs) {
|
Err(value_index) => match self.value_defs[value_index.index()] {
|
||||||
ValueDef::Body(
|
ValueDef::Body(
|
||||||
Loc {
|
Loc {
|
||||||
value: Pattern::RecordDestructure(collection),
|
value: Pattern::RecordDestructure(collection),
|
||||||
|
@ -1273,7 +1270,7 @@ impl<'a> Defs<'a> {
|
||||||
{
|
{
|
||||||
Ok(type_index) => {
|
Ok(type_index) => {
|
||||||
// remove from vec
|
// remove from vec
|
||||||
unsafe { self.type_defs.remove(type_index.index()) };
|
self.type_defs.remove(type_index.index());
|
||||||
|
|
||||||
// update all of the remaining indexes in type_defs
|
// update all of the remaining indexes in type_defs
|
||||||
for (current_tag_index, tag) in self.tags.iter_mut().enumerate() {
|
for (current_tag_index, tag) in self.tags.iter_mut().enumerate() {
|
||||||
|
@ -1285,7 +1282,7 @@ impl<'a> Defs<'a> {
|
||||||
}
|
}
|
||||||
Err(value_index) => {
|
Err(value_index) => {
|
||||||
// remove from vec
|
// remove from vec
|
||||||
unsafe { self.value_defs.remove(value_index.index()) };
|
self.value_defs.remove(value_index.index());
|
||||||
|
|
||||||
// update all of the remaining indexes in value_defs
|
// update all of the remaining indexes in value_defs
|
||||||
for (current_tag_index, tag) in self.tags.iter_mut().enumerate() {
|
for (current_tag_index, tag) in self.tags.iter_mut().enumerate() {
|
||||||
|
@ -1314,17 +1311,11 @@ impl<'a> Defs<'a> {
|
||||||
|
|
||||||
self.regions.push(region);
|
self.regions.push(region);
|
||||||
|
|
||||||
self.space_before.push({
|
let before = Slice::extend_new(&mut self.spaces, spaces_before.iter().copied());
|
||||||
let start = self.spaces.len() as u32;
|
self.space_before.push(before);
|
||||||
self.spaces.extend(spaces_before.iter().copied());
|
|
||||||
Slice::new(start, spaces_before.len() as u16, &self.spaces)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.space_after.push({
|
let after = Slice::extend_new(&mut self.spaces, spaces_after.iter().copied());
|
||||||
let start = self.spaces.len() as u32;
|
self.space_after.push(after);
|
||||||
self.spaces.extend(spaces_after.iter().copied());
|
|
||||||
Slice::new(start, spaces_after.len() as u16, &self.spaces)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_value_def(
|
pub fn push_value_def(
|
||||||
|
@ -1334,11 +1325,7 @@ impl<'a> Defs<'a> {
|
||||||
spaces_before: &[CommentOrNewline<'a>],
|
spaces_before: &[CommentOrNewline<'a>],
|
||||||
spaces_after: &[CommentOrNewline<'a>],
|
spaces_after: &[CommentOrNewline<'a>],
|
||||||
) {
|
) {
|
||||||
let value_def_index = {
|
let value_def_index = Index::push_new(&mut self.value_defs, value_def);
|
||||||
let index = Index::new(self.value_defs.len() as u32, &self.value_defs);
|
|
||||||
self.value_defs.push(value_def);
|
|
||||||
index
|
|
||||||
};
|
|
||||||
let tag = EitherIndex::from_right(value_def_index);
|
let tag = EitherIndex::from_right(value_def_index);
|
||||||
self.push_def_help(tag, region, spaces_before, spaces_after)
|
self.push_def_help(tag, region, spaces_before, spaces_after)
|
||||||
}
|
}
|
||||||
|
@ -1360,7 +1347,7 @@ impl<'a> Defs<'a> {
|
||||||
}
|
}
|
||||||
Err(value_index) => {
|
Err(value_index) => {
|
||||||
self.regions[tag_index] = region;
|
self.regions[tag_index] = region;
|
||||||
*value_index.get_in_mut(&mut self.value_defs) = value_def;
|
self.value_defs[value_index.index()] = value_def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1372,11 +1359,7 @@ impl<'a> Defs<'a> {
|
||||||
spaces_before: &[CommentOrNewline<'a>],
|
spaces_before: &[CommentOrNewline<'a>],
|
||||||
spaces_after: &[CommentOrNewline<'a>],
|
spaces_after: &[CommentOrNewline<'a>],
|
||||||
) {
|
) {
|
||||||
let type_def_index = {
|
let type_def_index = Index::push_new(&mut self.type_defs, type_def);
|
||||||
let index = Index::new(self.type_defs.len() as u32, &self.type_defs);
|
|
||||||
self.type_defs.push(type_def);
|
|
||||||
index
|
|
||||||
};
|
|
||||||
let tag = EitherIndex::from_left(type_def_index);
|
let tag = EitherIndex::from_left(type_def_index);
|
||||||
self.push_def_help(tag, region, spaces_before, spaces_after)
|
self.push_def_help(tag, region, spaces_before, spaces_after)
|
||||||
}
|
}
|
||||||
|
@ -1390,13 +1373,13 @@ impl<'a> Defs<'a> {
|
||||||
|
|
||||||
for (tag_index, tag) in self.tags.iter().enumerate() {
|
for (tag_index, tag) in self.tags.iter().enumerate() {
|
||||||
let region = self.regions[tag_index];
|
let region = self.regions[tag_index];
|
||||||
let space_before = unsafe {
|
let space_before = {
|
||||||
let start = self.space_before[tag_index].start();
|
let start = self.space_before[tag_index].start();
|
||||||
let len = self.space_before[tag_index].len();
|
let len = self.space_before[tag_index].len();
|
||||||
|
|
||||||
&self.spaces[start..(start + len)]
|
&self.spaces[start..(start + len)]
|
||||||
};
|
};
|
||||||
let space_after = unsafe {
|
let space_after = {
|
||||||
let start = self.space_after[tag_index].start();
|
let start = self.space_after[tag_index].start();
|
||||||
let len = self.space_after[tag_index].len();
|
let len = self.space_after[tag_index].len();
|
||||||
|
|
||||||
|
@ -1405,28 +1388,18 @@ impl<'a> Defs<'a> {
|
||||||
|
|
||||||
match tag.split() {
|
match tag.split() {
|
||||||
Ok(type_def_index) => {
|
Ok(type_def_index) => {
|
||||||
let type_def = *type_def_index.get_in(&self.type_defs);
|
let type_def = self.type_defs[type_def_index.index()];
|
||||||
|
|
||||||
match tag_index.cmp(&target) {
|
match tag_index.cmp(&target) {
|
||||||
std::cmp::Ordering::Less => {
|
std::cmp::Ordering::Less => {
|
||||||
// before
|
// before
|
||||||
let type_def_index = {
|
let type_def_index = Index::push_new(&mut before.type_defs, type_def);
|
||||||
let index =
|
|
||||||
Index::new(before.type_defs.len() as u32, &before.type_defs);
|
|
||||||
before.type_defs.push(type_def);
|
|
||||||
index
|
|
||||||
};
|
|
||||||
let tag = EitherIndex::from_left(type_def_index);
|
let tag = EitherIndex::from_left(type_def_index);
|
||||||
before.push_def_help(tag, region, space_before, space_after);
|
before.push_def_help(tag, region, space_before, space_after);
|
||||||
}
|
}
|
||||||
std::cmp::Ordering::Greater => {
|
std::cmp::Ordering::Greater => {
|
||||||
// after
|
// after
|
||||||
let type_def_index = {
|
let type_def_index = Index::push_new(&mut after.type_defs, type_def);
|
||||||
let index =
|
|
||||||
Index::new(after.type_defs.len() as u32, &after.type_defs);
|
|
||||||
after.type_defs.push(type_def);
|
|
||||||
index
|
|
||||||
};
|
|
||||||
let tag = EitherIndex::from_left(type_def_index);
|
let tag = EitherIndex::from_left(type_def_index);
|
||||||
after.push_def_help(tag, region, space_before, space_after);
|
after.push_def_help(tag, region, space_before, space_after);
|
||||||
}
|
}
|
||||||
|
@ -1436,28 +1409,20 @@ impl<'a> Defs<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(value_def_index) => {
|
Err(value_def_index) => {
|
||||||
let value_def = *value_def_index.get_in(&self.value_defs);
|
let value_def = self.value_defs[value_def_index.index()];
|
||||||
|
|
||||||
match tag_index.cmp(&target) {
|
match tag_index.cmp(&target) {
|
||||||
std::cmp::Ordering::Less => {
|
std::cmp::Ordering::Less => {
|
||||||
// before
|
// before
|
||||||
let new_value_def_index = {
|
let new_value_def_index =
|
||||||
let index =
|
Index::push_new(&mut before.value_defs, value_def);
|
||||||
Index::new(before.value_defs.len() as u32, &before.value_defs);
|
|
||||||
before.value_defs.push(value_def);
|
|
||||||
index
|
|
||||||
};
|
|
||||||
let tag = EitherIndex::from_right(new_value_def_index);
|
let tag = EitherIndex::from_right(new_value_def_index);
|
||||||
before.push_def_help(tag, region, space_before, space_after);
|
before.push_def_help(tag, region, space_before, space_after);
|
||||||
}
|
}
|
||||||
std::cmp::Ordering::Greater => {
|
std::cmp::Ordering::Greater => {
|
||||||
// after
|
// after
|
||||||
let new_value_def_index = {
|
let new_value_def_index =
|
||||||
let index =
|
Index::push_new(&mut after.value_defs, value_def);
|
||||||
Index::new(after.value_defs.len() as u32, &after.value_defs);
|
|
||||||
after.value_defs.push(value_def);
|
|
||||||
index
|
|
||||||
};
|
|
||||||
let tag = EitherIndex::from_right(new_value_def_index);
|
let tag = EitherIndex::from_right(new_value_def_index);
|
||||||
after.push_def_help(tag, region, space_before, space_after);
|
after.push_def_help(tag, region, space_before, space_after);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,10 @@ use crate::type_annotation;
|
||||||
use crate::{header, keyword};
|
use crate::{header, keyword};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
use roc_collections::soa::Slice;
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
||||||
use roc_region::all::{Loc, Position, Region};
|
use roc_region::all::{Loc, Position, Region};
|
||||||
use soa::Slice;
|
|
||||||
|
|
||||||
use crate::parser::Progress::{self, *};
|
use crate::parser::Progress::{self, *};
|
||||||
|
|
||||||
|
@ -2286,11 +2286,7 @@ pub fn parse_top_level_defs<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
if output.tags.len() > existing_len {
|
if output.tags.len() > existing_len {
|
||||||
let after = {
|
let after = Slice::extend_new(&mut output.spaces, last_space.iter().copied());
|
||||||
let start = output.spaces.len() as u32;
|
|
||||||
output.spaces.extend(last_space.iter().copied());
|
|
||||||
Slice::new(start, last_space.len() as u16, &output.spaces)
|
|
||||||
};
|
|
||||||
let last = output.tags.len() - 1;
|
let last = output.tags.len() - 1;
|
||||||
debug_assert!(output.space_after[last].is_empty() || after.is_empty());
|
debug_assert!(output.space_after[last].is_empty() || after.is_empty());
|
||||||
output.space_after[last] = after;
|
output.space_after[last] = after;
|
||||||
|
|
|
@ -2,7 +2,6 @@ use bumpalo::collections::{String, Vec};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_module::called_via::{BinOp, UnaryOp};
|
use roc_module::called_via::{BinOp, UnaryOp};
|
||||||
use roc_region::all::{Loc, Position, Region};
|
use roc_region::all::{Loc, Position, Region};
|
||||||
use soa::Slice;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
|
@ -723,8 +722,8 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
||||||
Expr::Crash => Expr::Crash,
|
Expr::Crash => Expr::Crash,
|
||||||
Expr::Defs(a, b) => {
|
Expr::Defs(a, b) => {
|
||||||
let mut defs = a.clone();
|
let mut defs = a.clone();
|
||||||
defs.space_before = vec![Slice::empty(&defs.spaces); defs.len()];
|
defs.space_before = vec![Default::default(); defs.len()];
|
||||||
defs.space_after = vec![Slice::empty(&defs.spaces); defs.len()];
|
defs.space_after = vec![Default::default(); defs.len()];
|
||||||
defs.regions = vec![Region::zero(); defs.len()];
|
defs.regions = vec![Region::zero(); defs.len()];
|
||||||
defs.spaces.clear();
|
defs.spaces.clear();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use roc_can::{abilities::AbilitiesStore, constraint::TypeOrVar, expected::Expected};
|
use roc_can::{abilities::AbilitiesStore, constraint::TypeOrVar, expected::Expected};
|
||||||
|
use roc_collections::soa::{Index, Slice};
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::{ident::TagName, symbol::Symbol};
|
use roc_module::{ident::TagName, symbol::Symbol};
|
||||||
use roc_region::all::Loc;
|
use roc_region::all::Loc;
|
||||||
|
@ -18,7 +19,6 @@ use roc_types::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use roc_unify::unify::{unify, Unified};
|
use roc_unify::unify::{unify, Unified};
|
||||||
use soa::{Index, Slice};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ability::{AbilityImplError, ObligationCache},
|
ability::{AbilityImplError, ObligationCache},
|
||||||
|
|
|
@ -152,7 +152,7 @@ fn find_names_needed(
|
||||||
|
|
||||||
// User-defined names are already taken.
|
// User-defined names are already taken.
|
||||||
// We must not accidentally generate names that collide with them!
|
// We must not accidentally generate names that collide with them!
|
||||||
let name = name_index.get_in(&subs.field_names).clone();
|
let name = subs.field_names[name_index.index as usize].clone();
|
||||||
match names_taken.get(&name) {
|
match names_taken.get(&name) {
|
||||||
Some(var) if *var == root => {}
|
Some(var) if *var == root => {}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
|
@ -680,24 +680,24 @@ fn write_content<'a>(
|
||||||
|
|
||||||
match subs.get_content_without_compacting(var) {
|
match subs.get_content_without_compacting(var) {
|
||||||
FlexVar(Some(name_index)) => {
|
FlexVar(Some(name_index)) => {
|
||||||
let name = name_index.get_in(&subs.field_names);
|
let name = &subs.field_names[name_index.index as usize];
|
||||||
buf.push_str(name.as_str())
|
buf.push_str(name.as_str())
|
||||||
}
|
}
|
||||||
FlexVar(None) => buf.push_str(WILDCARD),
|
FlexVar(None) => buf.push_str(WILDCARD),
|
||||||
RigidVar(name_index) => {
|
RigidVar(name_index) => {
|
||||||
let name = name_index.get_in(&subs.field_names);
|
let name = &subs.field_names[name_index.index as usize];
|
||||||
buf.push_str(name.as_str())
|
buf.push_str(name.as_str())
|
||||||
}
|
}
|
||||||
FlexAbleVar(opt_name_index, abilities) => {
|
FlexAbleVar(opt_name_index, abilities) => {
|
||||||
let name = opt_name_index
|
let name = opt_name_index
|
||||||
.map(|name_index| name_index.get_in(&subs.field_names).as_str())
|
.map(|name_index| subs.field_names[name_index.index as usize].as_str())
|
||||||
.unwrap_or(WILDCARD);
|
.unwrap_or(WILDCARD);
|
||||||
let abilities = AbilitySet::from_iter(subs.get_subs_slice(*abilities).iter().copied());
|
let abilities = AbilitySet::from_iter(subs.get_subs_slice(*abilities).iter().copied());
|
||||||
ctx.able_variables.push((name, abilities));
|
ctx.able_variables.push((name, abilities));
|
||||||
buf.push_str(name);
|
buf.push_str(name);
|
||||||
}
|
}
|
||||||
RigidAbleVar(name_index, abilities) => {
|
RigidAbleVar(name_index, abilities) => {
|
||||||
let name = name_index.get_in(&subs.field_names).as_str();
|
let name = subs.field_names[name_index.index as usize].as_str();
|
||||||
let abilities = AbilitySet::from_iter(subs.get_subs_slice(*abilities).iter().copied());
|
let abilities = AbilitySet::from_iter(subs.get_subs_slice(*abilities).iter().copied());
|
||||||
ctx.able_variables.push((name, abilities));
|
ctx.able_variables.push((name, abilities));
|
||||||
buf.push_str(name);
|
buf.push_str(name);
|
||||||
|
@ -713,7 +713,7 @@ fn write_content<'a>(
|
||||||
|
|
||||||
ctx.recursion_structs_to_expand.insert(structure_root);
|
ctx.recursion_structs_to_expand.insert(structure_root);
|
||||||
} else {
|
} else {
|
||||||
let name = name_index.get_in(&subs.field_names);
|
let name = &subs.field_names[name_index.index as usize];
|
||||||
buf.push_str(name.as_str())
|
buf.push_str(name.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,37 +15,9 @@ use std::iter::{once, Iterator};
|
||||||
|
|
||||||
// if your changes cause this number to go down, great!
|
// if your changes cause this number to go down, great!
|
||||||
// please change it to the lower number.
|
// please change it to the lower number.
|
||||||
// if it went up, maybe check that the change is really required.
|
// if it went up, maybe check that the change is really required
|
||||||
roc_error_macros::assert_sizeof_all!(
|
roc_error_macros::assert_sizeof_all!(Descriptor, 5 * 8 + 4);
|
||||||
Descriptor,
|
roc_error_macros::assert_sizeof_all!(FlatType, 3 * 8 + 4);
|
||||||
5 * 8 + 4 + {
|
|
||||||
// extra bytes in debug builds for extra Index/Slice array pointer storage for verification
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
20
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
{
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
roc_error_macros::assert_sizeof_all!(
|
|
||||||
FlatType,
|
|
||||||
3 * 8 + 4 + {
|
|
||||||
// extra bytes in debug builds for extra Index/Slice array pointer storage for verification
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
12
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
{
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
roc_error_macros::assert_sizeof_all!(UnionTags, 12);
|
roc_error_macros::assert_sizeof_all!(UnionTags, 12);
|
||||||
roc_error_macros::assert_sizeof_all!(RecordFields, 2 * 8);
|
roc_error_macros::assert_sizeof_all!(RecordFields, 2 * 8);
|
||||||
|
|
||||||
|
@ -297,7 +269,7 @@ impl Subs {
|
||||||
|
|
||||||
let mut lowercases = Vec::with_capacity(length);
|
let mut lowercases = Vec::with_capacity(length);
|
||||||
for subs_slice in slices {
|
for subs_slice in slices {
|
||||||
let bytes = subs_slice.get_slice(&string_slice);
|
let bytes = &string_slice[subs_slice.indices()];
|
||||||
offset += bytes.len();
|
offset += bytes.len();
|
||||||
let string = unsafe { std::str::from_utf8_unchecked(bytes) };
|
let string = unsafe { std::str::from_utf8_unchecked(bytes) };
|
||||||
|
|
||||||
|
@ -315,7 +287,7 @@ impl Subs {
|
||||||
|
|
||||||
let mut tag_names = Vec::with_capacity(length);
|
let mut tag_names = Vec::with_capacity(length);
|
||||||
for SerializedTagName(subs_slice) in slices {
|
for SerializedTagName(subs_slice) in slices {
|
||||||
let bytes = subs_slice.get_slice(&string_slice);
|
let bytes = &string_slice[subs_slice.indices()];
|
||||||
offset += bytes.len();
|
offset += bytes.len();
|
||||||
let string = unsafe { std::str::from_utf8_unchecked(bytes) };
|
let string = unsafe { std::str::from_utf8_unchecked(bytes) };
|
||||||
|
|
||||||
|
@ -441,10 +413,10 @@ impl Default for Subs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A slice into the Vec<T> of subs
|
/// A slice into the Vec<T> of subs
|
||||||
pub type SubsSlice<T> = Slice<T>;
|
pub type SubsSlice<T> = Slice<Subs, T>;
|
||||||
|
|
||||||
/// An index into the Vec<T> of subs
|
/// An index into the Vec<T> of subs
|
||||||
pub type SubsIndex<T> = Index<T>;
|
pub type SubsIndex<T> = Index<Subs, T>;
|
||||||
|
|
||||||
// make `subs[some_index]` work. The types/trait resolution make sure we get the
|
// make `subs[some_index]` work. The types/trait resolution make sure we get the
|
||||||
// element from the right vector
|
// element from the right vector
|
||||||
|
@ -453,13 +425,13 @@ impl std::ops::Index<SubsIndex<Variable>> for Subs {
|
||||||
type Output = Variable;
|
type Output = Variable;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<Variable>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<Variable>) -> &Self::Output {
|
||||||
index.get_in(&self.variables)
|
&self.variables[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::IndexMut<SubsIndex<Variable>> for Subs {
|
impl std::ops::IndexMut<SubsIndex<Variable>> for Subs {
|
||||||
fn index_mut(&mut self, index: SubsIndex<Variable>) -> &mut Self::Output {
|
fn index_mut(&mut self, index: SubsIndex<Variable>) -> &mut Self::Output {
|
||||||
index.get_in_mut(&mut self.variables)
|
&mut self.variables[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +439,7 @@ impl std::ops::Index<SubsIndex<Lowercase>> for Subs {
|
||||||
type Output = Lowercase;
|
type Output = Lowercase;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<Lowercase>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<Lowercase>) -> &Self::Output {
|
||||||
index.get_in(&self.field_names)
|
&self.field_names[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +447,7 @@ impl std::ops::Index<SubsIndex<usize>> for Subs {
|
||||||
type Output = usize;
|
type Output = usize;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<usize>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<usize>) -> &Self::Output {
|
||||||
index.get_in(&self.tuple_elem_indices)
|
&self.tuple_elem_indices[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,13 +455,13 @@ impl std::ops::Index<SubsIndex<TagName>> for Subs {
|
||||||
type Output = TagName;
|
type Output = TagName;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<TagName>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<TagName>) -> &Self::Output {
|
||||||
index.get_in(&self.tag_names)
|
&self.tag_names[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::IndexMut<SubsIndex<TagName>> for Subs {
|
impl std::ops::IndexMut<SubsIndex<TagName>> for Subs {
|
||||||
fn index_mut(&mut self, index: SubsIndex<TagName>) -> &mut Self::Output {
|
fn index_mut(&mut self, index: SubsIndex<TagName>) -> &mut Self::Output {
|
||||||
index.get_in_mut(&mut self.tag_names)
|
&mut self.tag_names[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,13 +469,13 @@ impl std::ops::Index<SubsIndex<Symbol>> for Subs {
|
||||||
type Output = Symbol;
|
type Output = Symbol;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<Symbol>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<Symbol>) -> &Self::Output {
|
||||||
index.get_in(&self.symbol_names)
|
&self.symbol_names[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::IndexMut<SubsIndex<Symbol>> for Subs {
|
impl std::ops::IndexMut<SubsIndex<Symbol>> for Subs {
|
||||||
fn index_mut(&mut self, index: SubsIndex<Symbol>) -> &mut Self::Output {
|
fn index_mut(&mut self, index: SubsIndex<Symbol>) -> &mut Self::Output {
|
||||||
index.get_in_mut(&mut self.symbol_names)
|
&mut self.symbol_names[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,19 +483,19 @@ impl std::ops::Index<SubsIndex<Uls>> for Subs {
|
||||||
type Output = Uls;
|
type Output = Uls;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<Uls>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<Uls>) -> &Self::Output {
|
||||||
index.get_in(&self.unspecialized_lambda_sets)
|
&self.unspecialized_lambda_sets[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::IndexMut<SubsIndex<Uls>> for Subs {
|
impl std::ops::IndexMut<SubsIndex<Uls>> for Subs {
|
||||||
fn index_mut(&mut self, index: SubsIndex<Uls>) -> &mut Self::Output {
|
fn index_mut(&mut self, index: SubsIndex<Uls>) -> &mut Self::Output {
|
||||||
index.get_in_mut(&mut self.unspecialized_lambda_sets)
|
&mut self.unspecialized_lambda_sets[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::IndexMut<SubsIndex<Lowercase>> for Subs {
|
impl std::ops::IndexMut<SubsIndex<Lowercase>> for Subs {
|
||||||
fn index_mut(&mut self, index: SubsIndex<Lowercase>) -> &mut Self::Output {
|
fn index_mut(&mut self, index: SubsIndex<Lowercase>) -> &mut Self::Output {
|
||||||
index.get_in_mut(&mut self.field_names)
|
&mut self.field_names[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,13 +503,13 @@ impl std::ops::Index<SubsIndex<RecordField<()>>> for Subs {
|
||||||
type Output = RecordField<()>;
|
type Output = RecordField<()>;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<RecordField<()>>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<RecordField<()>>) -> &Self::Output {
|
||||||
index.get_in(&self.record_fields)
|
&self.record_fields[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::IndexMut<SubsIndex<RecordField<()>>> for Subs {
|
impl std::ops::IndexMut<SubsIndex<RecordField<()>>> for Subs {
|
||||||
fn index_mut(&mut self, index: SubsIndex<RecordField<()>>) -> &mut Self::Output {
|
fn index_mut(&mut self, index: SubsIndex<RecordField<()>>) -> &mut Self::Output {
|
||||||
index.get_in_mut(&mut self.record_fields)
|
&mut self.record_fields[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,13 +517,13 @@ impl std::ops::Index<SubsIndex<VariableSubsSlice>> for Subs {
|
||||||
type Output = VariableSubsSlice;
|
type Output = VariableSubsSlice;
|
||||||
|
|
||||||
fn index(&self, index: SubsIndex<VariableSubsSlice>) -> &Self::Output {
|
fn index(&self, index: SubsIndex<VariableSubsSlice>) -> &Self::Output {
|
||||||
index.get_in(&self.variable_slices)
|
&self.variable_slices[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::IndexMut<SubsIndex<VariableSubsSlice>> for Subs {
|
impl std::ops::IndexMut<SubsIndex<VariableSubsSlice>> for Subs {
|
||||||
fn index_mut(&mut self, index: SubsIndex<VariableSubsSlice>) -> &mut Self::Output {
|
fn index_mut(&mut self, index: SubsIndex<VariableSubsSlice>) -> &mut Self::Output {
|
||||||
index.get_in_mut(&mut self.variable_slices)
|
&mut self.variable_slices[index.index as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1520,41 +1492,33 @@ pub struct SubsSnapshot {
|
||||||
uls_of_var_snapshot: UlsOfVarSnapshot,
|
uls_of_var_snapshot: UlsOfVarSnapshot,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unchecked_slice<T>(start: u32, len: u16) -> SubsSlice<T> {
|
|
||||||
unsafe { SubsSlice::new_unchecked(start, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unchecked_index<T>(index: u32) -> SubsIndex<T> {
|
|
||||||
unsafe { SubsIndex::new_unchecked(index) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Subs {
|
impl Subs {
|
||||||
// IFTTT INIT-TagNames
|
// IFTTT INIT-TagNames
|
||||||
pub const RESULT_TAG_NAMES: SubsSlice<TagName> = unchecked_slice(0, 2);
|
pub const RESULT_TAG_NAMES: SubsSlice<TagName> = SubsSlice::new(0, 2);
|
||||||
pub const TAG_NAME_ERR: SubsIndex<TagName> = unchecked_index(0);
|
pub const TAG_NAME_ERR: SubsIndex<TagName> = SubsIndex::new(0);
|
||||||
pub const TAG_NAME_OK: SubsIndex<TagName> = unchecked_index(1);
|
pub const TAG_NAME_OK: SubsIndex<TagName> = SubsIndex::new(1);
|
||||||
pub const TAG_NAME_INVALID_NUM_STR: SubsIndex<TagName> = unchecked_index(2);
|
pub const TAG_NAME_INVALID_NUM_STR: SubsIndex<TagName> = SubsIndex::new(2);
|
||||||
pub const TAG_NAME_BAD_UTF_8: SubsIndex<TagName> = unchecked_index(3);
|
pub const TAG_NAME_BAD_UTF_8: SubsIndex<TagName> = SubsIndex::new(3);
|
||||||
pub const TAG_NAME_OUT_OF_BOUNDS: SubsIndex<TagName> = unchecked_index(4);
|
pub const TAG_NAME_OUT_OF_BOUNDS: SubsIndex<TagName> = SubsIndex::new(4);
|
||||||
// END INIT-TagNames
|
// END INIT-TagNames
|
||||||
|
|
||||||
// IFTTT INIT-VariableSubsSlice
|
// IFTTT INIT-VariableSubsSlice
|
||||||
pub const STR_SLICE: VariableSubsSlice = unchecked_slice(0, 1);
|
pub const STR_SLICE: VariableSubsSlice = SubsSlice::new(0, 1);
|
||||||
// END INIT-VariableSubsSlice
|
// END INIT-VariableSubsSlice
|
||||||
|
|
||||||
// IFTTT INIT-SymbolSubsSlice
|
// IFTTT INIT-SymbolSubsSlice
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub const AB_ENCODING: SubsSlice<Symbol> = unchecked_slice(0, 1);
|
pub const AB_ENCODING: SubsSlice<Symbol> = SubsSlice::new(0, 1);
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub const AB_DECODING: SubsSlice<Symbol> = unchecked_slice(1, 1);
|
pub const AB_DECODING: SubsSlice<Symbol> = SubsSlice::new(1, 1);
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub const AB_HASHER: SubsSlice<Symbol> = unchecked_slice(2, 1);
|
pub const AB_HASHER: SubsSlice<Symbol> = SubsSlice::new(2, 1);
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub const AB_HASH: SubsSlice<Symbol> = unchecked_slice(3, 1);
|
pub const AB_HASH: SubsSlice<Symbol> = SubsSlice::new(3, 1);
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub const AB_EQ: SubsSlice<Symbol> = unchecked_slice(4, 1);
|
pub const AB_EQ: SubsSlice<Symbol> = SubsSlice::new(4, 1);
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub const AB_INSPECT: SubsSlice<Symbol> = unchecked_slice(5, 1);
|
pub const AB_INSPECT: SubsSlice<Symbol> = SubsSlice::new(5, 1);
|
||||||
// END INIT-SymbolSubsSlice
|
// END INIT-SymbolSubsSlice
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
@ -1684,7 +1648,7 @@ impl Subs {
|
||||||
self.variables
|
self.variables
|
||||||
.extend(std::iter::repeat(Variable::NULL).take(length));
|
.extend(std::iter::repeat(Variable::NULL).take(length));
|
||||||
|
|
||||||
Slice::new(start, length as u16, &self.variables)
|
Slice::new(start, length as u16)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_into_vars<I>(&mut self, input: I) -> VariableSubsSlice
|
pub fn insert_into_vars<I>(&mut self, input: I) -> VariableSubsSlice
|
||||||
|
@ -1697,7 +1661,7 @@ impl Subs {
|
||||||
|
|
||||||
let length = (self.variables.len() as u32 - start) as u16;
|
let length = (self.variables.len() as u32 - start) as u16;
|
||||||
|
|
||||||
Slice::new(start, length as u16, &self.variables)
|
Slice::new(start, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_variable_slices(&mut self, length: usize) -> SubsSlice<VariableSubsSlice> {
|
pub fn reserve_variable_slices(&mut self, length: usize) -> SubsSlice<VariableSubsSlice> {
|
||||||
|
@ -1710,7 +1674,7 @@ impl Subs {
|
||||||
self.variable_slices.push(value);
|
self.variable_slices.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Slice::new(start, length as u16, &self.variable_slices)
|
Slice::new(start, length as u16)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_tag_names(&mut self, length: usize) -> SubsSlice<TagName> {
|
pub fn reserve_tag_names(&mut self, length: usize) -> SubsSlice<TagName> {
|
||||||
|
@ -1719,7 +1683,7 @@ impl Subs {
|
||||||
self.tag_names
|
self.tag_names
|
||||||
.extend(std::iter::repeat(TagName(Uppercase::default())).take(length));
|
.extend(std::iter::repeat(TagName(Uppercase::default())).take(length));
|
||||||
|
|
||||||
Slice::new(start, length as u16, &self.tag_names)
|
Slice::new(start, length as u16)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_uls_slice(&mut self, length: usize) -> SubsSlice<Uls> {
|
pub fn reserve_uls_slice(&mut self, length: usize) -> SubsSlice<Uls> {
|
||||||
|
@ -1728,7 +1692,7 @@ impl Subs {
|
||||||
self.unspecialized_lambda_sets
|
self.unspecialized_lambda_sets
|
||||||
.extend(std::iter::repeat(Uls(Variable::NULL, Symbol::UNDERSCORE, 0)).take(length));
|
.extend(std::iter::repeat(Uls(Variable::NULL, Symbol::UNDERSCORE, 0)).take(length));
|
||||||
|
|
||||||
Slice::new(start, length as u16, &self.unspecialized_lambda_sets)
|
Slice::new(start, length as u16)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -2245,53 +2209,11 @@ impl From<Content> for Descriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
roc_error_macros::assert_sizeof_all!(
|
roc_error_macros::assert_sizeof_all!(Content, 4 * 8);
|
||||||
Content,
|
|
||||||
4 * 8 + {
|
|
||||||
// extra bytes in debug builds for extra Index/Slice array pointer storage for verification
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
16
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
{
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
roc_error_macros::assert_sizeof_all!((Symbol, AliasVariables, Variable), 8 + 12 + 4);
|
roc_error_macros::assert_sizeof_all!((Symbol, AliasVariables, Variable), 8 + 12 + 4);
|
||||||
roc_error_macros::assert_sizeof_all!(AliasVariables, 12);
|
roc_error_macros::assert_sizeof_all!(AliasVariables, 12);
|
||||||
roc_error_macros::assert_sizeof_all!(
|
roc_error_macros::assert_sizeof_all!(FlatType, 3 * 8 + 4);
|
||||||
FlatType,
|
roc_error_macros::assert_sizeof_all!(LambdaSet, 3 * 8 + 4);
|
||||||
3 * 8 + 4 + {
|
|
||||||
// extra bytes in debug builds for extra Index/Slice array pointer storage for verification
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
12
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
{
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
roc_error_macros::assert_sizeof_all!(
|
|
||||||
LambdaSet,
|
|
||||||
3 * 8 + 4 + {
|
|
||||||
// extra bytes in debug builds for extra Index/Slice array pointer storage for verification
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
12
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
{
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
roc_error_macros::assert_sizeof_aarch64!((Variable, Option<Lowercase>), 4 * 8);
|
roc_error_macros::assert_sizeof_aarch64!((Variable, Option<Lowercase>), 4 * 8);
|
||||||
roc_error_macros::assert_sizeof_wasm!((Variable, Option<Lowercase>), 4 * 4);
|
roc_error_macros::assert_sizeof_wasm!((Variable, Option<Lowercase>), 4 * 4);
|
||||||
|
@ -2390,16 +2312,16 @@ pub struct AliasVariables {
|
||||||
|
|
||||||
impl AliasVariables {
|
impl AliasVariables {
|
||||||
pub const fn all_variables(&self) -> VariableSubsSlice {
|
pub const fn all_variables(&self) -> VariableSubsSlice {
|
||||||
unsafe { SubsSlice::new_unchecked(self.variables_start, self.all_variables_len) }
|
SubsSlice::new(self.variables_start, self.all_variables_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn type_variables(&self) -> VariableSubsSlice {
|
pub const fn type_variables(&self) -> VariableSubsSlice {
|
||||||
unsafe { SubsSlice::new_unchecked(self.variables_start, self.type_variables_len) }
|
SubsSlice::new(self.variables_start, self.type_variables_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn lambda_set_variables(&self) -> VariableSubsSlice {
|
pub const fn lambda_set_variables(&self) -> VariableSubsSlice {
|
||||||
let start = self.variables_start + self.type_variables_len as u32;
|
let start = self.variables_start + self.type_variables_len as u32;
|
||||||
unsafe { SubsSlice::new_unchecked(start, self.lambda_set_variables_len) }
|
SubsSlice::new(start, self.lambda_set_variables_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn infer_ext_in_output_variables(&self) -> VariableSubsSlice {
|
pub const fn infer_ext_in_output_variables(&self) -> VariableSubsSlice {
|
||||||
|
@ -2407,7 +2329,7 @@ impl AliasVariables {
|
||||||
self.type_variables_len as u32 + self.lambda_set_variables_len as u32;
|
self.type_variables_len as u32 + self.lambda_set_variables_len as u32;
|
||||||
let start = self.variables_start + infer_ext_vars_offset;
|
let start = self.variables_start + infer_ext_vars_offset;
|
||||||
let infer_ext_vars_len = self.all_variables_len - infer_ext_vars_offset as u16;
|
let infer_ext_vars_len = self.all_variables_len - infer_ext_vars_offset as u16;
|
||||||
unsafe { SubsSlice::new_unchecked(start, infer_ext_vars_len) }
|
SubsSlice::new(start, infer_ext_vars_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn len(&self) -> usize {
|
pub const fn len(&self) -> usize {
|
||||||
|
@ -2724,7 +2646,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let slice = subs.variable_slices[self.values_start as usize];
|
let slice = subs.variable_slices[self.values_start as usize];
|
||||||
slice.len() == 1
|
slice.length == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_tag_name_index(index: SubsIndex<L>) -> Self {
|
pub fn from_tag_name_index(index: SubsIndex<L>) -> Self {
|
||||||
|
@ -2743,8 +2665,8 @@ where
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
length: labels.len() as u16,
|
length: labels.len() as u16,
|
||||||
labels_start: labels.start(),
|
labels_start: labels.start,
|
||||||
values_start: variables.start(),
|
values_start: variables.start,
|
||||||
_marker: Default::default(),
|
_marker: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3072,25 +2994,24 @@ impl RecordFields {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn variables(&self) -> SubsSlice<Variable> {
|
pub const fn variables(&self) -> SubsSlice<Variable> {
|
||||||
unsafe { SubsSlice::new_unchecked(self.variables_start, self.length) }
|
SubsSlice::new(self.variables_start, self.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn field_names(&self) -> SubsSlice<Lowercase> {
|
pub const fn field_names(&self) -> SubsSlice<Lowercase> {
|
||||||
unsafe { SubsSlice::new_unchecked(self.field_names_start, self.length) }
|
SubsSlice::new(self.field_names_start, self.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn record_fields(&self) -> SubsSlice<RecordField<()>> {
|
pub const fn record_fields(&self) -> SubsSlice<RecordField<()>> {
|
||||||
unsafe { SubsSlice::new_unchecked(self.field_types_start, self.length) }
|
SubsSlice::new(self.field_types_start, self.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_variables(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
|
pub fn iter_variables(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
|
||||||
let slice = unsafe { SubsSlice::new_unchecked(self.variables_start, self.length) };
|
let slice = SubsSlice::new(self.variables_start, self.length);
|
||||||
slice.into_iter()
|
slice.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_only_optional_fields(&self, subs: &Subs) -> bool {
|
pub fn has_only_optional_fields(&self, subs: &Subs) -> bool {
|
||||||
let slice: SubsSlice<RecordField<()>> =
|
let slice: SubsSlice<RecordField<()>> = SubsSlice::new(self.field_types_start, self.length);
|
||||||
unsafe { SubsSlice::new_unchecked(self.field_types_start, self.length) };
|
|
||||||
|
|
||||||
subs.get_subs_slice(slice)
|
subs.get_subs_slice(slice)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -3223,15 +3144,7 @@ impl RecordFields {
|
||||||
|
|
||||||
let it = range1.into_iter().zip(range2).zip(range3);
|
let it = range1.into_iter().zip(range2).zip(range3);
|
||||||
|
|
||||||
unsafe {
|
it.map(|((i1, i2), i3)| (SubsIndex::new(i1), SubsIndex::new(i2), SubsIndex::new(i3)))
|
||||||
it.map(|((i1, i2), i3)| {
|
|
||||||
(
|
|
||||||
SubsIndex::new_unchecked(i1),
|
|
||||||
SubsIndex::new_unchecked(i2),
|
|
||||||
SubsIndex::new_unchecked(i3),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3292,15 +3205,15 @@ impl TupleElems {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn variables(&self) -> SubsSlice<Variable> {
|
pub const fn variables(&self) -> SubsSlice<Variable> {
|
||||||
unsafe { SubsSlice::new_unchecked(self.variables_start, self.length) }
|
SubsSlice::new(self.variables_start, self.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn elem_indices(&self) -> SubsSlice<usize> {
|
pub const fn elem_indices(&self) -> SubsSlice<usize> {
|
||||||
unsafe { SubsSlice::new_unchecked(self.elem_index_start, self.length) }
|
SubsSlice::new(self.elem_index_start, self.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_variables(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
|
pub fn iter_variables(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
|
||||||
let slice = unsafe { SubsSlice::new_unchecked(self.variables_start, self.length) };
|
let slice = SubsSlice::new(self.variables_start, self.length);
|
||||||
slice.into_iter()
|
slice.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3312,7 +3225,7 @@ impl TupleElems {
|
||||||
|
|
||||||
let it = range1.into_iter().zip(range2);
|
let it = range1.into_iter().zip(range2);
|
||||||
|
|
||||||
unsafe { it.map(|(i1, i2)| (SubsIndex::new_unchecked(i1), SubsIndex::new_unchecked(i2))) }
|
it.map(|(i1, i2)| (SubsIndex::new(i1), SubsIndex::new(i2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_into_subs<I>(subs: &mut Subs, input: I) -> Self
|
pub fn insert_into_subs<I>(subs: &mut Subs, input: I) -> Self
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::subs::{
|
||||||
VariableSubsSlice,
|
VariableSubsSlice,
|
||||||
};
|
};
|
||||||
use roc_collections::all::{HumanIndex, ImMap, ImSet, MutMap, MutSet, SendMap};
|
use roc_collections::all::{HumanIndex, ImMap, ImSet, MutMap, MutSet, SendMap};
|
||||||
|
use roc_collections::soa::{Index, Slice};
|
||||||
use roc_collections::VecMap;
|
use roc_collections::VecMap;
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::called_via::CalledVia;
|
use roc_module::called_via::CalledVia;
|
||||||
|
@ -12,7 +13,6 @@ use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use soa::{Index, Slice};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -486,17 +486,17 @@ impl Default for Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Types {
|
impl Types {
|
||||||
pub const EMPTY_RECORD: Index<TypeTag> = unsafe { Index::new_unchecked(0) };
|
pub const EMPTY_RECORD: Index<TypeTag> = Index::new(0);
|
||||||
const EMPTY_RECORD_TAG: TypeTag = TypeTag::Variable(Variable::EMPTY_RECORD);
|
const EMPTY_RECORD_TAG: TypeTag = TypeTag::Variable(Variable::EMPTY_RECORD);
|
||||||
const EMPTY_RECORD_ARGS: Slice<TypeTag> = unsafe { Slice::empty_unchecked() };
|
const EMPTY_RECORD_ARGS: Slice<TypeTag> = Slice::empty();
|
||||||
|
|
||||||
pub const EMPTY_TAG_UNION: Index<TypeTag> = unsafe { Index::new_unchecked(1) };
|
pub const EMPTY_TAG_UNION: Index<TypeTag> = Index::new(1);
|
||||||
const EMPTY_TAG_UNION_TAG: TypeTag = TypeTag::Variable(Variable::EMPTY_TAG_UNION);
|
const EMPTY_TAG_UNION_TAG: TypeTag = TypeTag::Variable(Variable::EMPTY_TAG_UNION);
|
||||||
const EMPTY_TAG_UNION_ARGS: Slice<TypeTag> = unsafe { Slice::empty_unchecked() };
|
const EMPTY_TAG_UNION_ARGS: Slice<TypeTag> = Slice::empty();
|
||||||
|
|
||||||
pub const STR: Index<TypeTag> = unsafe { Index::new_unchecked(1) };
|
pub const STR: Index<TypeTag> = Index::new(2);
|
||||||
const STR_TAG: TypeTag = TypeTag::Variable(Variable::STR);
|
const STR_TAG: TypeTag = TypeTag::Variable(Variable::STR);
|
||||||
const STR_ARGS: Slice<TypeTag> = unsafe { Slice::empty_unchecked() };
|
const STR_ARGS: Slice<TypeTag> = Slice::empty();
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -1280,8 +1280,8 @@ mod debug_types {
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{TypeTag, Types};
|
use super::{TypeTag, Types};
|
||||||
|
use roc_collections::soa::{Index, Slice};
|
||||||
use roc_module::ident::TagName;
|
use roc_module::ident::TagName;
|
||||||
use soa::{Index, Slice};
|
|
||||||
use ven_pretty::{text, Arena, DocAllocator, DocBuilder};
|
use ven_pretty::{text, Arena, DocAllocator, DocBuilder};
|
||||||
|
|
||||||
pub struct DebugTag<'a>(pub &'a Types, pub Index<TypeTag>);
|
pub struct DebugTag<'a>(pub &'a Types, pub Index<TypeTag>);
|
||||||
|
@ -4558,7 +4558,3 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn unsafe_index<T>(index: u32) -> Index<T> {
|
|
||||||
unsafe { Index::new_unchecked(index) }
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
use core::{
|
|
||||||
fmt::{self, Formatter},
|
|
||||||
marker::PhantomData,
|
|
||||||
ptr::NonNull,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::soa_index::Index;
|
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
|
||||||
pub struct EitherIndex<T, U> {
|
|
||||||
index: u32,
|
|
||||||
_marker: PhantomData<(T, U)>,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
pub(crate) array_start: Result<Option<NonNull<T>>, Option<NonNull<U>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, U> Clone for EitherIndex<T, U> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, U> Copy for EitherIndex<T, U> {}
|
|
||||||
|
|
||||||
impl<T, U> fmt::Debug for EitherIndex<T, U> {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "Index({})", self.index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, U> EitherIndex<T, U> {
|
|
||||||
const MASK: u32 = 1 << 31;
|
|
||||||
|
|
||||||
pub const fn from_left(input: Index<T>) -> Self {
|
|
||||||
assert!(input.index & Self::MASK == 0);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
index: input.index,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: Ok(input.array_start),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn from_right(input: Index<U>) -> Self {
|
|
||||||
assert!(input.index & Self::MASK == 0);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
index: input.index | Self::MASK,
|
|
||||||
_marker: std::marker::PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: Err(input.array_start),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn split(self) -> Result<Index<T>, Index<U>> {
|
|
||||||
if self.index & Self::MASK == 0 {
|
|
||||||
Ok(Index {
|
|
||||||
index: self.index,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: {
|
|
||||||
match self.array_start {
|
|
||||||
Ok(array) => array,
|
|
||||||
Err(_) => {
|
|
||||||
panic!("Tried to split an EitherIndex that was created with from_right, but ended up with a mask that indicates it was created with from_left");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(Index {
|
|
||||||
index: self.index ^ Self::MASK,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: {
|
|
||||||
match self.array_start {
|
|
||||||
Err(array) => array,
|
|
||||||
Ok(_) => {
|
|
||||||
panic!("Tried to split an EitherIndex that was created with from_left, but ended up with a mask that indicates it was created with from_right");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decrement_index(&mut self) {
|
|
||||||
self.index = self.index.saturating_sub(1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,5 @@
|
||||||
#![cfg_attr(not(any(debug_assertions, test)), no_std)]
|
|
||||||
|
|
||||||
mod either_index;
|
|
||||||
mod soa_index;
|
mod soa_index;
|
||||||
mod soa_slice;
|
mod soa_slice;
|
||||||
|
|
||||||
pub use either_index::*;
|
|
||||||
pub use soa_index::*;
|
pub use soa_index::*;
|
||||||
pub use soa_slice::*;
|
pub use soa_slice::*;
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
use core::{
|
use core::fmt;
|
||||||
any,
|
|
||||||
cmp::Ordering,
|
|
||||||
fmt::{self, Formatter},
|
|
||||||
hash::{Hash, Hasher},
|
|
||||||
marker::PhantomData,
|
|
||||||
ptr::NonNull,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::soa_slice::Slice;
|
use crate::soa_slice::Slice;
|
||||||
|
|
||||||
|
@ -14,174 +7,50 @@ use crate::soa_slice::Slice;
|
||||||
///
|
///
|
||||||
/// Unlike a Rust pointer, this is a u32 offset
|
/// Unlike a Rust pointer, this is a u32 offset
|
||||||
/// rather than usize.
|
/// rather than usize.
|
||||||
pub struct Index<T> {
|
pub struct Index<Array, Elem> {
|
||||||
pub(crate) index: u32,
|
pub index: u32,
|
||||||
pub(crate) _marker: PhantomData<T>,
|
pub(crate) _marker: core::marker::PhantomData<(Array, Elem)>,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
pub(crate) array_start: Option<NonNull<T>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> PartialEq for Index<T> {
|
impl<Array, Elem> fmt::Debug for Index<Array, Elem> {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(debug_assertions)]
|
write!(
|
||||||
self.verify_array(other.array_start.map(NonNull::as_ptr), ".eq()");
|
f,
|
||||||
|
"Index<{}, {}>({})",
|
||||||
self.index == other.index
|
core::any::type_name::<Array>(),
|
||||||
}
|
core::any::type_name::<Elem>(),
|
||||||
}
|
self.index
|
||||||
|
)
|
||||||
impl<T> Eq for Index<T> {}
|
|
||||||
|
|
||||||
impl<T> PartialOrd for Index<T> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
self.verify_array(other.array_start.map(NonNull::as_ptr), ".partial_cmp()");
|
|
||||||
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Ord for Index<T> {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
self.verify_array(other.array_start.map(NonNull::as_ptr), ".cmp()");
|
|
||||||
|
|
||||||
self.index.cmp(&other.index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> fmt::Debug for Index<T> {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "Index<{}>({})", any::type_name::<T>(), self.index)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// derive of copy and clone does not play well with PhantomData
|
// derive of copy and clone does not play well with PhantomData
|
||||||
|
|
||||||
impl<T> Copy for Index<T> {}
|
impl<Array, Elem> Copy for Index<Array, Elem> {}
|
||||||
|
|
||||||
impl<T> Clone for Index<T> {
|
impl<Array, Elem> Clone for Index<Array, Elem> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Hash for Index<T> {
|
impl<Array, Elem> Index<Array, Elem> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
pub const fn new(start: u32) -> Self {
|
||||||
self.index.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Index<T> {
|
|
||||||
pub const fn new(
|
|
||||||
start: u32,
|
|
||||||
_array: &[T], // only used in debug builds
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
index: start,
|
index: start,
|
||||||
_marker: PhantomData,
|
_marker: core::marker::PhantomData,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: Some(
|
|
||||||
// Safety: this is safe beccause references are never to null pointers.
|
|
||||||
// Once NonNull::new is const on stable Rust, use that instead. Docs to check for const-ness:
|
|
||||||
// https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.new
|
|
||||||
unsafe { NonNull::new_unchecked(_array.as_ptr() as *mut T) },
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new index that isn't associated with any particular array.
|
pub fn push_new(vector: &mut Vec<Elem>, value: Elem) -> Self {
|
||||||
/// This is marked as unsafe because it omits the runtime checks (in debug builds)
|
let index = Self::new(vector.len() as _);
|
||||||
/// which verify in debug builds that indices are dereferened into the original array.
|
|
||||||
pub const unsafe fn new_unchecked(start: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
index: start,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
vector.push(value);
|
||||||
array_start: None,
|
|
||||||
}
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn as_slice(self) -> Slice<T> {
|
pub const fn as_slice(self) -> Slice<Array, Elem> {
|
||||||
Slice {
|
Slice::new(self.index, 1)
|
||||||
start: self.index,
|
|
||||||
length: 1,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: self.array_start,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given the original slice this indexes into, return the equivalent of slice.get_unchecked(index)
|
|
||||||
/// (except that in debug build it actually does do a bounds check, and panics if it's out of bounds,
|
|
||||||
/// but that should never happen since this is an Index into a known slice - basically, a reference).
|
|
||||||
pub fn get_in(self, slice: &[T]) -> &T {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
self.verify_array(Some(slice.as_ptr() as *mut T), "get_in");
|
|
||||||
slice.get(self.index as usize).expect("Accessing an Index in its original slice went out of bounds. This should never happen!")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
unsafe {
|
|
||||||
slice.get_unchecked(self.index as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given the original slice this indexes into, return the equivalent of slice.get_unchecked_mut(index)
|
|
||||||
/// (except that in debug build it actually does do a bounds check, and panics if it's out of bounds,
|
|
||||||
/// but that should never happen since this is an Index into a known slice - basically, a reference).
|
|
||||||
pub fn get_in_mut(self, slice: &mut [T]) -> &mut T {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
self.verify_array(Some(slice.as_ptr() as *mut T), "get_in");
|
|
||||||
slice.get_mut(self.index as usize).expect("Accessing an Index in its original slice went out of bounds. This should never happen!")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
unsafe {
|
|
||||||
slice.get_unchecked_mut(self.index as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is unsafe because it doesn't verify that the index being returned is being used with the original
|
|
||||||
/// slice it was created with. Self::get_in is the safe alternative to this.
|
|
||||||
pub const unsafe fn index(self) -> usize {
|
|
||||||
self.index as usize
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
fn verify_array(&self, other: Option<*mut T>, operation: &'static str) {
|
|
||||||
match (self.array_start, other) {
|
|
||||||
(Some(array_start), Some(other_array_start))
|
|
||||||
if other_array_start != array_start.as_ptr() =>
|
|
||||||
{
|
|
||||||
panic!(
|
|
||||||
"Tried to {} an index from one array to the index of a different array!",
|
|
||||||
operation
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Either one of them was None, meaning this is unchecked, or they point to the same memory - as expected!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> core::ops::Index<Index<T>> for [T] {
|
|
||||||
type Output = T;
|
|
||||||
|
|
||||||
fn index(&self, index: Index<T>) -> &Self::Output {
|
|
||||||
index.get_in(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> core::ops::IndexMut<Index<T>> for [T] {
|
|
||||||
fn index_mut(&mut self, index: Index<T>) -> &mut Self::Output {
|
|
||||||
index.get_in_mut(self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::{fmt, marker::PhantomData, ops::Range, ptr::NonNull};
|
use core::fmt;
|
||||||
|
use core::iter::Map;
|
||||||
|
|
||||||
use crate::soa_index::Index;
|
use crate::soa_index::Index;
|
||||||
|
|
||||||
|
@ -7,22 +8,19 @@ use crate::soa_index::Index;
|
||||||
///
|
///
|
||||||
/// Unlike a Rust slice, this is a u32 offset
|
/// Unlike a Rust slice, this is a u32 offset
|
||||||
/// rather than a pointer, and the length is u16.
|
/// rather than a pointer, and the length is u16.
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
pub struct Slice<Array, Elem> {
|
||||||
pub struct Slice<T> {
|
pub start: u32,
|
||||||
pub(crate) start: u32,
|
pub length: u16,
|
||||||
pub(crate) length: u16,
|
_marker: core::marker::PhantomData<(Array, Elem)>,
|
||||||
pub(crate) _marker: core::marker::PhantomData<T>,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
pub(crate) array_start: Option<NonNull<T>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> fmt::Debug for Slice<T> {
|
impl<T, U> fmt::Debug for Slice<T, U> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Slice<{}> {{ start: {}, length: {} }}",
|
"Slice<{}, {}> {{ start: {}, length: {} }}",
|
||||||
core::any::type_name::<T>(),
|
core::any::type_name::<T>(),
|
||||||
|
core::any::type_name::<U>(),
|
||||||
self.start,
|
self.start,
|
||||||
self.length
|
self.length
|
||||||
)
|
)
|
||||||
|
@ -31,89 +29,42 @@ impl<T> fmt::Debug for Slice<T> {
|
||||||
|
|
||||||
// derive of copy and clone does not play well with PhantomData
|
// derive of copy and clone does not play well with PhantomData
|
||||||
|
|
||||||
impl<T> Copy for Slice<T> {}
|
impl<T, U> Copy for Slice<T, U> {}
|
||||||
|
|
||||||
impl<T> Clone for Slice<T> {
|
impl<T, U> Clone for Slice<T, U> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Slice<T> {
|
impl<T, U> Default for Slice<T, U> {
|
||||||
pub fn empty(_array: &[T]) -> Self {
|
fn default() -> Self {
|
||||||
|
Self::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Array, Elem> Slice<Array, Elem> {
|
||||||
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
start: 0,
|
start: 0,
|
||||||
length: 0,
|
length: 0,
|
||||||
_marker: Default::default(),
|
_marker: Default::default(),
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: NonNull::new(_array.as_ptr() as *mut T),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an empty slice that isn't associated with any particular array.
|
pub fn get_slice<'a>(&self, slice: &'a [Elem]) -> &'a [Elem] {
|
||||||
/// This is marked as unsafe because it omits the runtime checks (in debug builds)
|
&slice[self.indices()]
|
||||||
/// which verify that indices made from this slice are compared with other
|
|
||||||
/// indices into the original array.
|
|
||||||
pub unsafe fn empty_unchecked() -> Self {
|
|
||||||
Self {
|
|
||||||
start: 0,
|
|
||||||
length: 0,
|
|
||||||
_marker: Default::default(),
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is unsafe because it doesn't verify that the start index being returned is being used with the original
|
pub fn get_slice_mut<'a>(&self, slice: &'a mut [Elem]) -> &'a mut [Elem] {
|
||||||
/// slice it was created with. Self::get_in is the safe alternative to this.
|
&mut slice[self.indices()]
|
||||||
pub const unsafe fn start(self) -> usize {
|
|
||||||
self.start as usize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_slice<'a>(&self, slice: &'a [T]) -> &'a [T] {
|
|
||||||
&slice[self.as_range()]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_slice_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
|
|
||||||
&mut slice[self.as_range()]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is unsafe because it doesn't verify that the start index being returned is being used with the original
|
|
||||||
/// slice it was created with. Self::get_in is the safe alternative to this.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn indices(&self) -> Range<usize> {
|
pub fn indices(&self) -> core::ops::Range<usize> {
|
||||||
self.as_range()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given the original &[T] that this Slice<T> was based on,
|
|
||||||
/// return the &[T] representation of this Slice<T>.
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn slice_from<'a>(&self, original: &'a [T]) -> &'a [T] {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
self.verify_array(Some(original.as_ptr() as *mut T), "slice_from");
|
|
||||||
|
|
||||||
&original[self.as_range()]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The pub version of this is indices() and it's marked as unsafe. This one isn't marked as unsafe,
|
|
||||||
/// for internal convenience.
|
|
||||||
#[inline(always)]
|
|
||||||
fn as_range(&self) -> Range<usize> {
|
|
||||||
self.start as usize..(self.start as usize + self.length as usize)
|
self.start as usize..(self.start as usize + self.length as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the original &mut [T] that this Slice<T> was based on,
|
|
||||||
/// return the &mut [T] representation of this Slice<T>.
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn slice_from_mut<'a>(&self, original: &'a mut [T]) -> &'a mut [T] {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
self.verify_array(Some(original.as_ptr() as *mut T), "slice_from");
|
|
||||||
|
|
||||||
&mut original[self.start as usize..(self.start as usize + self.length as usize)]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn len(&self) -> usize {
|
pub const fn len(&self) -> usize {
|
||||||
self.length as usize
|
self.length as usize
|
||||||
}
|
}
|
||||||
|
@ -122,130 +73,43 @@ impl<T> Slice<T> {
|
||||||
self.len() == 0
|
self.len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn at_start(&self, array: &[T]) -> Index<T> {
|
pub const fn new(start: u32, length: u16) -> Self {
|
||||||
self.at(0, array)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn at(&self, i: usize, _array: &[T]) -> Index<T> {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
if !self.matches_stored_array(_array) {
|
|
||||||
panic!("Tried to call .at() on a slice passing an array that was different from the array it was created with!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Index {
|
|
||||||
index: self.start + i as u32,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: self.array_start,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
fn matches_stored_array(&self, other_array: &[T]) -> bool {
|
|
||||||
match self.array_start {
|
|
||||||
Some(self_array) => other_array.as_ptr() == self_array.as_ptr(),
|
|
||||||
None => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn new(start: u32, length: u16, _array: &[T]) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
start,
|
start,
|
||||||
length,
|
length,
|
||||||
_marker: PhantomData,
|
_marker: std::marker::PhantomData,
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: Some(
|
|
||||||
// Safety: this is safe beccause references are never to null pointers.
|
|
||||||
// Once NonNull::new is const on stable Rust, use that instead. Docs to check for const-ness:
|
|
||||||
// https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.new
|
|
||||||
unsafe { NonNull::new_unchecked(_array.as_ptr() as *mut T) },
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new slice that isn't associated with any particular array.
|
pub fn extend_new(vec: &mut Vec<Elem>, it: impl IntoIterator<Item = Elem>) -> Self {
|
||||||
/// This is marked as unsafe because it omits the runtime checks (in debug builds)
|
let start = vec.len();
|
||||||
/// which verify in debug builds that indices made from this slice are compared with other
|
|
||||||
/// indices into the original array.
|
|
||||||
pub const unsafe fn new_unchecked(start: u32, length: u16) -> Self {
|
|
||||||
Self {
|
|
||||||
start,
|
|
||||||
length,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
vec.extend(it);
|
||||||
array_start: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
let end = vec.len();
|
||||||
fn verify_array(&self, other: Option<*mut T>, operation: &'static str) {
|
|
||||||
match (self.array_start, other) {
|
Self::new(start as u32, (end - start) as u16)
|
||||||
(Some(array_start), Some(other_array_start))
|
|
||||||
if other_array_start != array_start.as_ptr() =>
|
|
||||||
{
|
|
||||||
panic!(
|
|
||||||
"Tried to {} an index from one array to the index of a different array!",
|
|
||||||
operation
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Either one of them was None, meaning this is unchecked, or they point to the same memory - as expected!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IntoIterator for Slice<T> {
|
impl<Array, Elem> IntoIterator for Slice<Array, Elem> {
|
||||||
type Item = Index<T>;
|
type Item = Index<Array, Elem>;
|
||||||
type IntoIter = SliceIterator<T>;
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
type IntoIter = Map<core::ops::Range<u32>, fn(u32) -> Self::Item>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
SliceIterator {
|
(self.start..(self.start + self.length as u32)).map(u32_to_index)
|
||||||
slice: self,
|
|
||||||
current: self.start,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SliceIterator<T> {
|
fn u32_to_index<T, U>(i: u32) -> Index<T, U> {
|
||||||
slice: Slice<T>,
|
Index {
|
||||||
current: u32,
|
index: i,
|
||||||
}
|
_marker: core::marker::PhantomData,
|
||||||
|
|
||||||
impl<T> Iterator for SliceIterator<T> {
|
|
||||||
type Item = Index<T>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.current < self.slice.start + self.slice.length as u32 {
|
|
||||||
let index = Index {
|
|
||||||
index: self.current,
|
|
||||||
_marker: PhantomData,
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
array_start: self.slice.array_start,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.current += 1;
|
|
||||||
|
|
||||||
Some(index)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
||||||
let remaining = (self.slice.start + self.slice.length as u32 - self.current) as usize;
|
|
||||||
(remaining, Some(remaining))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ExactSizeIterator for SliceIterator<T> {}
|
pub trait GetSlice<Array, Elem> {
|
||||||
|
fn get_slice(&self, slice: Slice<Array, Elem>) -> &[Elem];
|
||||||
pub trait GetSlice<T> {
|
|
||||||
fn get_slice(&self, slice: Slice<T>) -> &[T];
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue