switching constraint order fixes things

This commit is contained in:
Folkert 2023-07-24 21:24:21 +02:00
parent 557c3987e0
commit 2756c9af35
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
5 changed files with 74 additions and 106 deletions

1
Cargo.lock generated
View file

@ -3776,7 +3776,6 @@ dependencies = [
"roc_module",
"roc_problem",
"roc_region",
"roc_solve",
"roc_solve_schema",
"roc_std",
"roc_target",

View file

@ -2527,13 +2527,6 @@ pub fn constrain_decls(
match tag {
Value => {
constraint = add_host_annotation(
types,
constraints,
declarations.host_exposed_annotations.get(&index),
constraint,
);
constraint = constrain_value_def(
types,
constraints,
@ -2542,15 +2535,15 @@ pub fn constrain_decls(
index,
constraint,
);
}
Function(function_def_index) => {
constraint = add_host_annotation(
types,
constraints,
declarations.host_exposed_annotations.get(&index),
constraint,
);
}
Function(function_def_index) => {
constraint = constrain_function_def(
types,
constraints,
@ -2560,6 +2553,13 @@ pub fn constrain_decls(
function_def_index,
constraint,
);
constraint = add_host_annotation(
types,
constraints,
declarations.host_exposed_annotations.get(&index),
constraint,
);
}
Recursive(_) | TailRecursive(_) => {
constraint = add_host_annotation(

View file

@ -5649,8 +5649,6 @@ fn build_pending_specializations<'a>(
let is_host_exposed = exposed_to_host.top_level_values.contains_key(&symbol);
// TODO remove clones (with drain)
let annotation = declarations.annotations[index].clone();
let body = declarations.expressions[index].clone();
let tag = declarations.declarations[index];

View file

@ -24,7 +24,6 @@ roc_std = { path = "../../roc_std" }
roc_target = { path = "../roc_target" }
roc_tracing = { path = "../../tracing" }
roc_types = { path = "../types" }
roc_solve = { path = "../solve" }
roc_solve_schema = { path = "../solve_schema" }
roc_unify = { path = "../unify" }
ven_pretty = { path = "../../vendor/pretty" }

View file

@ -11,8 +11,7 @@ use crate::layout::{
};
use bumpalo::collections::{CollectIn, Vec};
use bumpalo::Bump;
use roc_can::abilities::{AbilitiesStore, SpecializationId};
use roc_can::constraint::Constraints;
use roc_can::abilities::SpecializationId;
use roc_can::expr::{AnnotatedMark, ClosureData, ExpectLookup};
use roc_can::module::ExposedByModule;
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
@ -32,15 +31,12 @@ use roc_module::low_level::{LowLevel, LowLevelWrapperType};
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_problem::can::{RuntimeError, ShadowKind};
use roc_region::all::{Loc, Region};
use roc_solve::ability::ObligationCache;
use roc_solve::{Aliases, DerivedEnv, InferenceEnv, Pools};
use roc_std::RocDec;
use roc_target::TargetInfo;
use roc_types::subs::{
instantiate_rigids, storage_copy_var_to, Content, ExhaustiveMark, FlatType, Rank,
RedundantMark, StorageSubs, Subs, SubsFmtContent, Variable, VariableSubsSlice,
instantiate_rigids, storage_copy_var_to, Content, ExhaustiveMark, FlatType,
RedundantMark, StorageSubs, Subs, Variable, VariableSubsSlice,
};
use roc_types::types::Types;
use std::collections::HashMap;
use ven_pretty::{text, BoxAllocator, DocAllocator, DocBuilder};
@ -753,32 +749,43 @@ impl<'a> Specialized<'a> {
}
}
fn insert_specialized(&mut self, symbol: Symbol, layout: ProcLayout<'a>, proc: Proc<'a>) {
fn insert_specialized(
&mut self,
symbol: Symbol,
layout: ProcLayout<'a>,
proc: Proc<'a>,
) -> SpecializedIndex {
for (i, s) in self.symbols.iter().enumerate() {
if *s == symbol && self.proc_layouts[i] == layout {
match &self.procedures[i] {
InProgressProc::InProgress => {
self.procedures[i] = InProgressProc::Done(proc);
return;
return SpecializedIndex(i);
}
InProgressProc::Done(_) => {
// overwrite existing! this is important in practice
// TODO investigate why we generate the wrong proc in some cases and then
// correct later
self.procedures[i] = InProgressProc::Done(proc);
return;
return SpecializedIndex(i);
}
}
}
}
// the key/layout combo was not found; insert it
let i = self.symbols.len();
self.symbols.push(symbol);
self.proc_layouts.push(layout);
self.procedures.push(InProgressProc::Done(proc));
SpecializedIndex(i)
}
}
struct SpecializedIndex(usize);
/// Uniquely determines the specialization of a polymorphic (non-proc) value symbol.
/// Two specializations are equivalent if their [`SpecializationMark`]s are equal.
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
@ -3069,33 +3076,16 @@ fn specialize_host_specializations<'a>(
let offset_variable = StorageSubs::merge_into(store, env.subs);
for (symbol, ls_from_app, from_platform) in it {
dbg!(symbol);
specialize_external_help(
env,
procs,
layout_cache,
symbol,
offset_variable(ls_from_app),
);
let from_app = offset_variable(ls_from_app);
for (symbol, from_app, from_platform) in it {
let from_app = offset_variable(from_app);
let index = specialize_external_help(env, procs, layout_cache, symbol, from_app);
// now run the lambda set numbering scheme
let mut layout_env =
layout::Env::from_components(layout_cache, env.subs, env.arena, env.target_info);
let hels = find_lambda_sets(&mut layout_env, from_platform);
dbg!(&hels);
// now unify
let content = env.subs.get_without_compacting(from_app).content;
dbg!(SubsFmtContent(&content, env.subs,));
let content = env.subs.get_without_compacting(from_platform).content;
dbg!(SubsFmtContent(&content, env.subs,));
let mut unify_env = roc_unify::Env::new(
env.subs,
#[cfg(debug_assertions)]
@ -3119,10 +3109,45 @@ fn specialize_host_specializations<'a>(
}
}
for (id, unified_variable, _) in hels {
let content = env.subs.get_without_compacting(unified_variable).content;
let mut aliases = BumpMap::default();
dbg!(SubsFmtContent(&content, env.subs,));
for (id, _, raw_function_layout) in hels {
let symbol = env.unique_symbol();
let lambda_name = LambdaName::no_niche(symbol);
let (key, (top_level, proc)) = generate_host_exposed_function(
env,
procs,
layout_cache,
lambda_name,
raw_function_layout,
);
procs
.specialized
.insert_specialized(symbol, top_level, proc);
let hels = HostExposedLambdaSet {
id,
symbol,
proc_layout: top_level,
raw_function_layout,
};
aliases.insert(key, hels);
}
let in_progress = &mut procs.specialized.procedures[index.0];
let InProgressProc::Done(proc) = in_progress else { unreachable!() };
match &mut proc.host_exposed_layouts {
HostExposedLayouts::HostExposed { aliases: old, .. } => old.extend(aliases),
hep @ HostExposedLayouts::NotHostExposed => {
*hep = HostExposedLayouts::HostExposed {
aliases,
rigids: Default::default(),
};
}
}
}
}
@ -3148,7 +3173,7 @@ fn specialize_external_specializations<'a>(
// duplicate specializations, and the insertion into a hash map
// below will deduplicate them.
specialize_external_help(env, procs, layout_cache, symbol, imported_variable)
specialize_external_help(env, procs, layout_cache, symbol, imported_variable);
}
}
}
@ -3159,7 +3184,7 @@ fn specialize_external_help<'a>(
layout_cache: &mut LayoutCache<'a>,
name: LambdaName<'a>,
variable: Variable,
) {
) -> SpecializedIndex {
let partial_proc_id = match procs.partial_procs.symbol_to_id(name.name()) {
Some(v) => v,
None => {
@ -3171,7 +3196,7 @@ fn specialize_external_help<'a>(
specialize_variable(env, procs, name, layout_cache, variable, partial_proc_id);
match specialization_result {
Ok((mut proc, layout)) => {
Ok((proc, layout)) => {
let top_level = ProcLayout::from_raw_named(env.arena, name, layout);
if procs.is_module_thunk(name.name()) {
@ -3218,64 +3243,11 @@ fn specialize_external_help<'a>(
}
}
}
// Now, let's generate the host-exposed lambda set wrappers from the type of the
// host-exported function.
{
let extern_names = {
let mut layout_env = layout::Env::from_components(
layout_cache,
env.subs,
env.arena,
env.target_info,
);
find_lambda_sets(&mut layout_env, variable)
};
let mut aliases = BumpMap::default();
for (id, _, raw_function_layout) in extern_names {
let symbol = env.unique_symbol();
let lambda_name = LambdaName::no_niche(symbol);
let (key, (top_level, proc)) = generate_host_exposed_function(
env,
procs,
layout_cache,
lambda_name,
raw_function_layout,
);
procs
.specialized
.insert_specialized(symbol, top_level, proc);
let hels = HostExposedLambdaSet {
id,
symbol,
proc_layout: top_level,
raw_function_layout,
};
aliases.insert(key, hels);
}
match &mut proc.host_exposed_layouts {
HostExposedLayouts::HostExposed { aliases: old, .. } => old.extend(aliases),
hep @ HostExposedLayouts::NotHostExposed => {
*hep = HostExposedLayouts::HostExposed {
aliases,
rigids: Default::default(),
};
}
}
}
}
procs
.specialized
.insert_specialized(name.name(), top_level, proc);
.insert_specialized(name.name(), top_level, proc)
}
Err(SpecializeFailure { attempted_layout }) => {
let proc = generate_runtime_error_function(env, name, attempted_layout);
@ -3284,7 +3256,7 @@ fn specialize_external_help<'a>(
procs
.specialized
.insert_specialized(name.name(), top_level, proc);
.insert_specialized(name.name(), top_level, proc)
}
}
}
@ -5359,7 +5331,7 @@ pub fn with_hole<'a>(
if let Err(e) = inserted {
return runtime_error(
env,
env.arena.alloc(format!("RuntimeError: {:?}", e,)),
env.arena.alloc(format!("RuntimeError: {e:?}")),
);
}
drop(inserted);