Resolve ability specializations looked up in expects

This commit is contained in:
Ayaz Hafiz 2022-10-17 17:56:48 -05:00
parent 8aee32830a
commit d26e9c81e0
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
8 changed files with 108 additions and 31 deletions

1
Cargo.lock generated
View file

@ -3959,6 +3959,7 @@ dependencies = [
"pretty_assertions", "pretty_assertions",
"roc_build", "roc_build",
"roc_builtins", "roc_builtins",
"roc_can",
"roc_collections", "roc_collections",
"roc_gen_llvm", "roc_gen_llvm",
"roc_intern", "roc_intern",

View file

@ -230,14 +230,14 @@ pub enum Expr {
Expect { Expect {
loc_condition: Box<Loc<Expr>>, loc_condition: Box<Loc<Expr>>,
loc_continuation: Box<Loc<Expr>>, loc_continuation: Box<Loc<Expr>>,
lookups_in_cond: Vec<(Symbol, Variable)>, lookups_in_cond: Vec<ExpectLookup>,
}, },
// not parsed, but is generated when lowering toplevel effectful expects // not parsed, but is generated when lowering toplevel effectful expects
ExpectFx { ExpectFx {
loc_condition: Box<Loc<Expr>>, loc_condition: Box<Loc<Expr>>,
loc_continuation: Box<Loc<Expr>>, loc_continuation: Box<Loc<Expr>>,
lookups_in_cond: Vec<(Symbol, Variable)>, lookups_in_cond: Vec<ExpectLookup>,
}, },
/// Rendered as empty box in editor /// Rendered as empty box in editor
@ -247,6 +247,13 @@ pub enum Expr {
RuntimeError(RuntimeError), RuntimeError(RuntimeError),
} }
#[derive(Clone, Copy, Debug)]
pub struct ExpectLookup {
pub symbol: Symbol,
pub var: Variable,
pub ability_info: Option<SpecializationId>,
}
impl Expr { impl Expr {
pub fn category(&self) -> Category { pub fn category(&self) -> Category {
match self { match self {
@ -2541,7 +2548,7 @@ impl Declarations {
}) })
} }
pub fn expects(&self) -> VecMap<Region, Vec<(Symbol, Variable)>> { pub fn expects(&self) -> VecMap<Region, Vec<ExpectLookup>> {
let mut collector = ExpectCollector { let mut collector = ExpectCollector {
expects: VecMap::default(), expects: VecMap::default(),
}; };
@ -2625,9 +2632,9 @@ pub struct DestructureDef {
pub pattern_vars: VecMap<Symbol, Variable>, pub pattern_vars: VecMap<Symbol, Variable>,
} }
fn get_lookup_symbols(expr: &Expr) -> Vec<(Symbol, Variable)> { fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
let mut stack: Vec<&Expr> = vec![expr]; let mut stack: Vec<&Expr> = vec![expr];
let mut symbols = Vec::new(); let mut lookups: Vec<ExpectLookup> = Vec::new();
while let Some(expr) = stack.pop() { while let Some(expr) = stack.pop() {
match expr { match expr {
@ -2636,11 +2643,23 @@ fn get_lookup_symbols(expr: &Expr) -> Vec<(Symbol, Variable)> {
symbol, symbol,
record_var: var, record_var: var,
.. ..
} } => {
| Expr::AbilityMember(symbol, _, var) => {
// Don't introduce duplicates, or make unused variables // Don't introduce duplicates, or make unused variables
if !symbols.iter().any(|(sym, _)| sym == symbol) { if !lookups.iter().any(|l| l.symbol == *symbol) {
symbols.push((*symbol, *var)); lookups.push(ExpectLookup {
symbol: *symbol,
var: *var,
ability_info: None,
});
}
}
Expr::AbilityMember(symbol, spec_id, var) => {
if !lookups.iter().any(|l| l.symbol == *symbol) {
lookups.push(ExpectLookup {
symbol: *symbol,
var: *var,
ability_info: *spec_id,
});
} }
} }
Expr::List { loc_elems, .. } => { Expr::List { loc_elems, .. } => {
@ -2737,7 +2756,7 @@ fn get_lookup_symbols(expr: &Expr) -> Vec<(Symbol, Variable)> {
} }
} }
symbols lookups
} }
/// Here we transform /// Here we transform
@ -2784,14 +2803,22 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
loop { loop {
match loc_expr.value { match loc_expr.value {
Expr::LetNonRec(boxed_def, remainder) => { Expr::LetNonRec(boxed_def, remainder) => {
lookups_in_cond.extend(boxed_def.pattern_vars.iter().map(|(a, b)| (*a, *b))); lookups_in_cond.extend(boxed_def.pattern_vars.iter().map(|(a, b)| ExpectLookup {
symbol: *a,
var: *b,
ability_info: None,
}));
stack.push(StoredDef::NonRecursive(loc_expr.region, boxed_def)); stack.push(StoredDef::NonRecursive(loc_expr.region, boxed_def));
loc_expr = *remainder; loc_expr = *remainder;
} }
Expr::LetRec(defs, remainder, mark) => { Expr::LetRec(defs, remainder, mark) => {
for def in &defs { for def in &defs {
lookups_in_cond.extend(def.pattern_vars.iter().map(|(a, b)| (*a, *b))); lookups_in_cond.extend(def.pattern_vars.iter().map(|(a, b)| ExpectLookup {
symbol: *a,
var: *b,
ability_info: None,
}));
} }
stack.push(StoredDef::Recursive(loc_expr.region, defs, mark)); stack.push(StoredDef::Recursive(loc_expr.region, defs, mark));
@ -2834,7 +2861,7 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
} }
struct ExpectCollector { struct ExpectCollector {
expects: VecMap<Region, Vec<(Symbol, Variable)>>, expects: VecMap<Region, Vec<ExpectLookup>>,
} }
impl crate::traverse::Visitor for ExpectCollector { impl crate::traverse::Visitor for ExpectCollector {

View file

@ -3,7 +3,7 @@ use crate::annotation::canonicalize_annotation;
use crate::def::{canonicalize_defs, Def}; use crate::def::{canonicalize_defs, Def};
use crate::effect_module::HostedGeneratedFunctions; use crate::effect_module::HostedGeneratedFunctions;
use crate::env::Env; use crate::env::Env;
use crate::expr::{ClosureData, Declarations, Expr, Output, PendingDerives}; use crate::expr::{ClosureData, Declarations, ExpectLookup, Expr, Output, PendingDerives};
use crate::pattern::{BindingsFromPattern, Pattern}; use crate::pattern::{BindingsFromPattern, Pattern};
use crate::scope::Scope; use crate::scope::Scope;
use bumpalo::Bump; use bumpalo::Bump;
@ -130,7 +130,7 @@ pub struct Module {
pub aliases: MutMap<Symbol, (bool, Alias)>, pub aliases: MutMap<Symbol, (bool, Alias)>,
pub rigid_variables: RigidVariables, pub rigid_variables: RigidVariables,
pub abilities_store: PendingAbilitiesStore, pub abilities_store: PendingAbilitiesStore,
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>, pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -152,7 +152,7 @@ pub struct ModuleOutput {
pub symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>, pub symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
pub pending_derives: PendingDerives, pub pending_derives: PendingDerives,
pub scope: Scope, pub scope: Scope,
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>, pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
} }
fn validate_generate_with<'a>( fn validate_generate_with<'a>(

View file

@ -13,8 +13,8 @@ use roc_can::expected::Expected::{self, *};
use roc_can::expected::PExpected; use roc_can::expected::PExpected;
use roc_can::expr::Expr::{self, *}; use roc_can::expr::Expr::{self, *};
use roc_can::expr::{ use roc_can::expr::{
AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef, Field, AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef,
FunctionDef, OpaqueWrapFunctionData, WhenBranch, ExpectLookup, Field, FunctionDef, OpaqueWrapFunctionData, WhenBranch,
}; };
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;
@ -519,7 +519,12 @@ pub fn constrain_expr(
let mut vars = Vec::with_capacity(lookups_in_cond.len()); let mut vars = Vec::with_capacity(lookups_in_cond.len());
for (symbol, var) in lookups_in_cond.iter() { for ExpectLookup {
symbol,
var,
ability_info: _,
} in lookups_in_cond.iter()
{
vars.push(*var); vars.push(*var);
all_constraints.push(constraints.lookup( all_constraints.push(constraints.lookup(
@ -566,7 +571,12 @@ pub fn constrain_expr(
let mut vars = Vec::with_capacity(lookups_in_cond.len()); let mut vars = Vec::with_capacity(lookups_in_cond.len());
for (symbol, var) in lookups_in_cond.iter() { for ExpectLookup {
symbol,
var,
ability_info: _,
} in lookups_in_cond.iter()
{
vars.push(*var); vars.push(*var);
all_constraints.push(constraints.lookup( all_constraints.push(constraints.lookup(

View file

@ -7,8 +7,8 @@ use parking_lot::Mutex;
use roc_builtins::roc::module_source; use roc_builtins::roc::module_source;
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl}; use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints}; use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
use roc_can::expr::Declarations;
use roc_can::expr::PendingDerives; use roc_can::expr::PendingDerives;
use roc_can::expr::{Declarations, ExpectLookup};
use roc_can::module::{ use roc_can::module::{
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module, canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
ResolvedImplementations, TypeState, ResolvedImplementations, TypeState,
@ -719,7 +719,7 @@ pub enum EntryPoint<'a> {
pub struct Expectations { pub struct Expectations {
pub subs: roc_types::subs::Subs, pub subs: roc_types::subs::Subs,
pub path: PathBuf, pub path: PathBuf,
pub expectations: VecMap<Region, Vec<(Symbol, Variable)>>, pub expectations: VecMap<Region, Vec<ExpectLookup>>,
pub ident_ids: IdentIds, pub ident_ids: IdentIds,
} }
@ -763,7 +763,7 @@ struct ParsedModule<'a> {
header_for: HeaderFor<'a>, header_for: HeaderFor<'a>,
} }
type LocExpects = VecMap<Region, Vec<(Symbol, Variable)>>; type LocExpects = VecMap<Region, Vec<ExpectLookup>>;
/// A message sent out _from_ a worker thread, /// A message sent out _from_ a worker thread,
/// representing a result of work done, or a request for further work /// representing a result of work done, or a request for further work

View file

@ -9,7 +9,7 @@ use bumpalo::collections::{CollectIn, Vec};
use bumpalo::Bump; use bumpalo::Bump;
use roc_builtins::bitcode::{FloatWidth, IntWidth}; use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_can::abilities::SpecializationId; use roc_can::abilities::SpecializationId;
use roc_can::expr::{AnnotatedMark, ClosureData, IntValue}; use roc_can::expr::{AnnotatedMark, ClosureData, ExpectLookup, IntValue};
use roc_can::module::ExposedByModule; use roc_can::module::ExposedByModule;
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap}; use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
use roc_collections::VecMap; use roc_collections::VecMap;
@ -6350,11 +6350,25 @@ pub fn from_can<'a>(
let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache); let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
let cond_symbol = env.unique_symbol(); let cond_symbol = env.unique_symbol();
let lookups = Vec::from_iter_in(lookups_in_cond.iter().map(|t| t.0), env.arena); let mut lookups = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
let mut layouts = Vec::with_capacity_in(lookups_in_cond.len(), env.arena); let mut layouts = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
for (_, var) in lookups_in_cond { for ExpectLookup {
symbol,
var,
ability_info,
} in lookups_in_cond
{
let symbol = match ability_info {
Some(specialization_id) => late_resolve_ability_specialization(
env,
symbol,
Some(specialization_id),
var,
),
None => symbol,
};
lookups.push(symbol);
let res_layout = layout_cache.from_var(env.arena, var, env.subs); let res_layout = layout_cache.from_var(env.arena, var, env.subs);
let layout = return_on_layout_error!(env, res_layout, "Expect"); let layout = return_on_layout_error!(env, res_layout, "Expect");
layouts.push(layout); layouts.push(layout);
@ -6389,11 +6403,25 @@ pub fn from_can<'a>(
let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache); let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
let cond_symbol = env.unique_symbol(); let cond_symbol = env.unique_symbol();
let lookups = Vec::from_iter_in(lookups_in_cond.iter().map(|t| t.0), env.arena); let mut lookups = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
let mut layouts = Vec::with_capacity_in(lookups_in_cond.len(), env.arena); let mut layouts = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
for (_, var) in lookups_in_cond { for ExpectLookup {
symbol,
var,
ability_info,
} in lookups_in_cond
{
let symbol = match ability_info {
Some(specialization_id) => late_resolve_ability_specialization(
env,
symbol,
Some(specialization_id),
var,
),
None => symbol,
};
lookups.push(symbol);
let res_layout = layout_cache.from_var(env.arena, var, env.subs); let res_layout = layout_cache.from_var(env.arena, var, env.subs);
let layout = return_on_layout_error!(env, res_layout, "Expect"); let layout = return_on_layout_error!(env, res_layout, "Expect");
layouts.push(layout); layouts.push(layout);

View file

@ -10,6 +10,7 @@ bumpalo = {version = "3.11.0", features = ["collections"]}
target-lexicon = "0.12.2" target-lexicon = "0.12.2"
roc_builtins = {path = "../compiler/builtins"} roc_builtins = {path = "../compiler/builtins"}
roc_can = {path = "../compiler/can"}
roc_collections = {path = "../compiler/collections"} roc_collections = {path = "../compiler/collections"}
roc_intern = {path = "../compiler/intern"} roc_intern = {path = "../compiler/intern"}
roc_load = {path = "../compiler/load"} roc_load = {path = "../compiler/load"}

View file

@ -4,6 +4,7 @@ use bumpalo::collections::Vec as BumpVec;
use bumpalo::Bump; use bumpalo::Bump;
use inkwell::context::Context; use inkwell::context::Context;
use roc_build::link::llvm_module_to_dylib; use roc_build::link::llvm_module_to_dylib;
use roc_can::expr::ExpectLookup;
use roc_collections::{MutSet, VecMap}; use roc_collections::{MutSet, VecMap};
use roc_gen_llvm::{ use roc_gen_llvm::{
llvm::{build::LlvmBackendMode, externs::add_default_roc_externs}, llvm::{build::LlvmBackendMode, externs::add_default_roc_externs},
@ -389,7 +390,16 @@ fn render_expect_failure<'a>(
}; };
let subs = arena.alloc(&mut data.subs); let subs = arena.alloc(&mut data.subs);
let (symbols, variables): (Vec<_>, Vec<_>) = current.iter().map(|(a, b)| (*a, *b)).unzip(); let (symbols, variables): (Vec<_>, Vec<_>) = current
.iter()
.map(
|ExpectLookup {
symbol,
var,
ability_info: _,
}| (*symbol, *var),
)
.unzip();
let (offset, expressions) = crate::get_values( let (offset, expressions) = crate::get_values(
target_info, target_info,