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

View file

@ -230,14 +230,14 @@ pub enum Expr {
Expect {
loc_condition: 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
ExpectFx {
loc_condition: 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
@ -247,6 +247,13 @@ pub enum Expr {
RuntimeError(RuntimeError),
}
#[derive(Clone, Copy, Debug)]
pub struct ExpectLookup {
pub symbol: Symbol,
pub var: Variable,
pub ability_info: Option<SpecializationId>,
}
impl Expr {
pub fn category(&self) -> Category {
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 {
expects: VecMap::default(),
};
@ -2625,9 +2632,9 @@ pub struct DestructureDef {
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 symbols = Vec::new();
let mut lookups: Vec<ExpectLookup> = Vec::new();
while let Some(expr) = stack.pop() {
match expr {
@ -2636,11 +2643,23 @@ fn get_lookup_symbols(expr: &Expr) -> Vec<(Symbol, Variable)> {
symbol,
record_var: var,
..
}
| Expr::AbilityMember(symbol, _, var) => {
} => {
// Don't introduce duplicates, or make unused variables
if !symbols.iter().any(|(sym, _)| sym == symbol) {
symbols.push((*symbol, *var));
if !lookups.iter().any(|l| l.symbol == *symbol) {
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, .. } => {
@ -2737,7 +2756,7 @@ fn get_lookup_symbols(expr: &Expr) -> Vec<(Symbol, Variable)> {
}
}
symbols
lookups
}
/// Here we transform
@ -2784,14 +2803,22 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
loop {
match loc_expr.value {
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));
loc_expr = *remainder;
}
Expr::LetRec(defs, remainder, mark) => {
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));
@ -2834,7 +2861,7 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
}
struct ExpectCollector {
expects: VecMap<Region, Vec<(Symbol, Variable)>>,
expects: VecMap<Region, Vec<ExpectLookup>>,
}
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::effect_module::HostedGeneratedFunctions;
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::scope::Scope;
use bumpalo::Bump;
@ -130,7 +130,7 @@ pub struct Module {
pub aliases: MutMap<Symbol, (bool, Alias)>,
pub rigid_variables: RigidVariables,
pub abilities_store: PendingAbilitiesStore,
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>,
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
}
#[derive(Debug, Default)]
@ -152,7 +152,7 @@ pub struct ModuleOutput {
pub symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
pub pending_derives: PendingDerives,
pub scope: Scope,
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>,
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
}
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::expr::Expr::{self, *};
use roc_can::expr::{
AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef, Field,
FunctionDef, OpaqueWrapFunctionData, WhenBranch,
AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef,
ExpectLookup, Field, FunctionDef, OpaqueWrapFunctionData, WhenBranch,
};
use roc_can::pattern::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());
for (symbol, var) in lookups_in_cond.iter() {
for ExpectLookup {
symbol,
var,
ability_info: _,
} in lookups_in_cond.iter()
{
vars.push(*var);
all_constraints.push(constraints.lookup(
@ -566,7 +571,12 @@ pub fn constrain_expr(
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);
all_constraints.push(constraints.lookup(

View file

@ -7,8 +7,8 @@ use parking_lot::Mutex;
use roc_builtins::roc::module_source;
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
use roc_can::expr::Declarations;
use roc_can::expr::PendingDerives;
use roc_can::expr::{Declarations, ExpectLookup};
use roc_can::module::{
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
ResolvedImplementations, TypeState,
@ -719,7 +719,7 @@ pub enum EntryPoint<'a> {
pub struct Expectations {
pub subs: roc_types::subs::Subs,
pub path: PathBuf,
pub expectations: VecMap<Region, Vec<(Symbol, Variable)>>,
pub expectations: VecMap<Region, Vec<ExpectLookup>>,
pub ident_ids: IdentIds,
}
@ -763,7 +763,7 @@ struct ParsedModule<'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,
/// 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 roc_builtins::bitcode::{FloatWidth, IntWidth};
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_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
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 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);
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 layout = return_on_layout_error!(env, res_layout, "Expect");
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 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);
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 layout = return_on_layout_error!(env, res_layout, "Expect");
layouts.push(layout);