Skip to content

Commit

Permalink
Shove more into a common env
Browse files Browse the repository at this point in the history
  • Loading branch information
ayazhafiz committed Jun 22, 2023
1 parent b5ea2c2 commit ad20a2e
Show file tree
Hide file tree
Showing 10 changed files with 566 additions and 624 deletions.
20 changes: 20 additions & 0 deletions crates/compiler/can/src/constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ pub type PExpectedTypeIndex = Index<PExpected<TypeOrVar>>;
pub type TypeOrVar = EitherIndex<TypeTag, Variable>;

impl Constraints {
pub fn empty() -> Self {
Self {
constraints: Default::default(),
type_slices: Default::default(),
variables: Default::default(),
loc_symbols: Default::default(),
let_constraints: Default::default(),
categories: Default::default(),
pattern_categories: Default::default(),
expectations: Default::default(),
pattern_expectations: Default::default(),
includes_tags: Default::default(),
strings: Default::default(),
sketched_rows: Default::default(),
eq: Default::default(),
pattern_eq: Default::default(),
cycles: Default::default(),
}
}

pub fn new() -> Self {
let constraints = Vec::new();
let type_slices = Vec::with_capacity(16);
Expand Down
40 changes: 29 additions & 11 deletions crates/compiler/late_solve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ use std::sync::{Arc, RwLock};

use bumpalo::Bump;
use roc_can::abilities::AbilitiesStore;
use roc_can::constraint::Constraints;
use roc_can::module::ExposedByModule;
use roc_collections::MutMap;
use roc_derive::SharedDerivedModule;
use roc_error_macros::internal_error;
use roc_module::symbol::ModuleId;
use roc_module::symbol::Symbol;
use roc_solve::ability::AbilityResolver;
use roc_solve::specialize::{compact_lambda_sets_of_vars, DerivedEnv, Phase};
use roc_solve::specialize::{compact_lambda_sets_of_vars, Phase};
use roc_solve::Pools;
use roc_solve::{DerivedEnv, Env};
use roc_types::subs::{get_member_lambda_sets_at_region, Content, FlatType, LambdaSet};
use roc_types::subs::{ExposedTypesStorageSubs, Subs, Variable};
use roc_types::types::Polarity;
use roc_unify::unify::MetaCollector;
use roc_unify::unify::{Env, Mode, Unified};
use roc_unify::unify::{Env as UEnv, Mode, Unified};

pub use roc_solve::ability::{ResolveError, Resolved};
pub use roc_types::subs::instantiate_rigids;
Expand Down Expand Up @@ -340,6 +342,19 @@ impl MetaCollector for ChangedVariableCollector {
}
}

std::thread_local! {
static SCRATCHPAD_FOR_OCCURS: std::cell::RefCell<Option<Constraints>> = std::cell::RefCell::new(Some(Constraints::empty()));
}

fn with_empty_solve_constraints<T>(f: impl FnOnce(&Constraints) -> T) -> T {
SCRATCHPAD_FOR_OCCURS.with(|cell| {
let constr = cell.take().unwrap();
let result = f(&constr);
cell.replace(Some(constr));
result
})
}

/// Unifies two variables and performs lambda set compaction.
/// Ranks and other ability demands are disregarded.
#[allow(clippy::too_many_arguments)]
Expand All @@ -359,7 +374,7 @@ pub fn unify(
"derived module can only unify its subs in its own context!"
);
let unified = roc_unify::unify::unify_with_collector::<ChangedVariableCollector>(
&mut Env::new(subs),
&mut UEnv::new(subs),
left,
right,
Mode::EQ,
Expand All @@ -381,14 +396,17 @@ pub fn unify(
exposed_types: exposed_by_module,
};

let must_implement_constraints = compact_lambda_sets_of_vars(
subs,
&derived_env,
arena,
&mut pools,
lambda_sets_to_specialize,
&late_phase,
);
let must_implement_constraints = with_empty_solve_constraints(|c| {
let mut env = Env {
constraints: c,
subs,
derived_env: &derived_env,
arena,
pools: &mut pools,
};

compact_lambda_sets_of_vars(&mut env, lambda_sets_to_specialize, &late_phase)
});
// At this point we can't do anything with must-implement constraints, since we're no
// longer solving. We must assume that they were totally caught during solving.
// After we land https://github.com/roc-lang/roc/issues/3207 this concern should totally
Expand Down
16 changes: 8 additions & 8 deletions crates/compiler/solve/src/ability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ use roc_types::subs::{
TupleElems, Variable,
};
use roc_types::types::{AliasKind, Category, MemberImpl, PatternCategory, Polarity, Types};
use roc_unify::unify::{Env, MustImplementConstraints};
use roc_unify::unify::{Env as UEnv, MustImplementConstraints};
use roc_unify::unify::{MustImplementAbility, Obligated};

use crate::{aliases::Aliases, pools::Pools, to_var::type_to_var};
use crate::env::Env;
use crate::{aliases::Aliases, to_var::type_to_var};

#[derive(Debug, Clone)]
pub enum AbilityImplError {
Expand Down Expand Up @@ -55,7 +56,7 @@ pub struct PendingDerivesTable(

impl PendingDerivesTable {
pub fn new(
subs: &mut Subs,
env: &mut Env,
types: &mut Types,
aliases: &mut Aliases,
pending_derives: PendingDerives,
Expand All @@ -80,17 +81,16 @@ impl PendingDerivesTable {
// Neither rank nor pools should matter here.
let typ = types.from_old_type(&typ);
let opaque_var = type_to_var(
subs,
env,
Rank::toplevel(),
problems,
abilities_store,
obligation_cache,
&mut Pools::default(),
types,
aliases,
typ,
);
let real_var = match subs.get_content_without_compacting(opaque_var) {
let real_var = match env.subs.get_content_without_compacting(opaque_var) {
Content::Alias(_, _, real_var, AliasKind::Opaque) => real_var,
_ => internal_error!("Non-opaque in derives table"),
};
Expand Down Expand Up @@ -1283,7 +1283,7 @@ impl DerivableVisitor for DeriveEq {

// Of the floating-point types,
// only Dec implements Eq.
let mut env = Env::new(subs);
let mut env = UEnv::new(subs);
let unified = unify(
&mut env,
content_var,
Expand Down Expand Up @@ -1418,7 +1418,7 @@ pub fn resolve_ability_specialization<R: AbilityResolver>(

instantiate_rigids(subs, signature_var);
let (_vars, must_implement_ability, _lambda_sets_to_specialize, _meta) = unify(
&mut Env::new(subs),
&mut UEnv::new(subs),
specialization_var,
signature_var,
Mode::EQ,
Expand Down
64 changes: 25 additions & 39 deletions crates/compiler/solve/src/aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ use roc_types::{
types::{Alias, AliasKind, OptAbleVar, Type, TypeTag, Types},
};

use crate::ability::ObligationCache;
use crate::pools::Pools;
use crate::solve::register;
use crate::to_var::type_to_var_help;
use crate::{ability::ObligationCache, env::Env};

#[derive(Debug, Clone, Copy)]
struct DelayedAliasVariables {
Expand Down Expand Up @@ -123,9 +121,8 @@ impl Aliases {
}

fn instantiate_result_result(
subs: &mut Subs,
env: &mut Env,
rank: Rank,
pools: &mut Pools,
alias_variables: AliasVariables,
) -> Variable {
let tag_names_slice = Subs::RESULT_TAG_NAMES;
Expand All @@ -134,68 +131,65 @@ impl Aliases {
let ok_slice = SubsSlice::new(alias_variables.variables_start, 1);

let variable_slices =
SubsSlice::extend_new(&mut subs.variable_slices, [err_slice, ok_slice]);
SubsSlice::extend_new(&mut env.subs.variable_slices, [err_slice, ok_slice]);

let union_tags = UnionTags::from_slices(tag_names_slice, variable_slices);
let ext_var = TagExt::Any(Variable::EMPTY_TAG_UNION);
let flat_type = FlatType::TagUnion(union_tags, ext_var);
let content = Content::Structure(flat_type);

register(subs, rank, pools, content)
env.register(rank, content)
}

/// Build an alias of the form `Num range := range`
fn build_num_opaque(
subs: &mut Subs,
env: &mut Env,
rank: Rank,
pools: &mut Pools,
symbol: Symbol,
range_var: Variable,
) -> Variable {
let content = Content::Alias(
symbol,
AliasVariables::insert_into_subs(subs, [range_var], [], []),
AliasVariables::insert_into_subs(env.subs, [range_var], [], []),
range_var,
AliasKind::Opaque,
);

register(subs, rank, pools, content)
env.register(rank, content)
}

fn instantiate_builtin_aliases_real_var(
&mut self,
subs: &mut Subs,
env: &mut Env,
rank: Rank,
pools: &mut Pools,
symbol: Symbol,
alias_variables: AliasVariables,
) -> Option<(Variable, AliasKind)> {
match symbol {
Symbol::RESULT_RESULT => {
let var = Self::instantiate_result_result(subs, rank, pools, alias_variables);
let var = Self::instantiate_result_result(env, rank, alias_variables);

Some((var, AliasKind::Structural))
}
Symbol::NUM_NUM | Symbol::NUM_INTEGER | Symbol::NUM_FLOATINGPOINT => {
// Num range := range | Integer range := range | FloatingPoint range := range
let range_var = subs.variables[alias_variables.variables_start as usize];
let range_var = env.subs.variables[alias_variables.variables_start as usize];
Some((range_var, AliasKind::Opaque))
}
Symbol::NUM_INT => {
// Int range : Num (Integer range)
//
// build `Integer range := range`
let integer_content_var = Self::build_num_opaque(
subs,
env,
rank,
pools,
Symbol::NUM_INTEGER,
subs.variables[alias_variables.variables_start as usize],
env.subs.variables[alias_variables.variables_start as usize],
);

// build `Num (Integer range) := Integer range`
let num_content_var =
Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, integer_content_var);
Self::build_num_opaque(env, rank, Symbol::NUM_NUM, integer_content_var);

Some((num_content_var, AliasKind::Structural))
}
Expand All @@ -204,16 +198,15 @@ impl Aliases {
//
// build `FloatingPoint range := range`
let fpoint_content_var = Self::build_num_opaque(
subs,
env,
rank,
pools,
Symbol::NUM_FLOATINGPOINT,
subs.variables[alias_variables.variables_start as usize],
env.subs.variables[alias_variables.variables_start as usize],
);

// build `Num (FloatingPoint range) := FloatingPoint range`
let num_content_var =
Self::build_num_opaque(subs, rank, pools, Symbol::NUM_NUM, fpoint_content_var);
Self::build_num_opaque(env, rank, Symbol::NUM_NUM, fpoint_content_var);

Some((num_content_var, AliasKind::Structural))
}
Expand All @@ -235,9 +228,8 @@ impl Aliases {

pub fn instantiate_real_var(
&mut self,
subs: &mut Subs,
env: &mut Env,
rank: Rank,
pools: &mut Pools,
problems: &mut Vec<TypeError>,
abilities_store: &AbilitiesStore,
obligation_cache: &mut ObligationCache,
Expand All @@ -247,14 +239,9 @@ impl Aliases {
alias_variables: AliasVariables,
) -> (Variable, AliasKind) {
// hardcoded instantiations for builtin aliases
if let Some((var, kind)) = Self::instantiate_builtin_aliases_real_var(
self,
subs,
rank,
pools,
symbol,
alias_variables,
) {
if let Some((var, kind)) =
self.instantiate_builtin_aliases_real_var(env, rank, symbol, alias_variables)
{
return (var, kind);
}

Expand All @@ -271,7 +258,7 @@ impl Aliases {
let mut substitutions: MutMap<_, _> = Default::default();

let old_type_variables = delayed_variables.type_variables(&mut self.variables);
let new_type_variables = &subs.variables[alias_variables.type_variables().indices()];
let new_type_variables = &env.subs.variables[alias_variables.type_variables().indices()];

for (old, new) in old_type_variables.iter_mut().zip(new_type_variables) {
// if constraint gen duplicated a type these variables could be the same
Expand All @@ -289,13 +276,13 @@ impl Aliases {
.iter_mut()
{
debug_assert!(opt_abilities.is_none());
let new_var = subs.fresh_unnamed_flex_var();
let new_var = env.subs.fresh_unnamed_flex_var();
substitutions.insert(*rec_var, new_var);
}

let old_lambda_set_variables = delayed_variables.lambda_set_variables(&mut self.variables);
let new_lambda_set_variables =
&subs.variables[alias_variables.lambda_set_variables().indices()];
&env.subs.variables[alias_variables.lambda_set_variables().indices()];

for (old, new) in old_lambda_set_variables
.iter_mut()
Expand All @@ -310,7 +297,7 @@ impl Aliases {
let old_infer_ext_vars =
delayed_variables.infer_ext_in_output_variables(&mut self.variables);
let new_infer_ext_vars =
&subs.variables[alias_variables.infer_ext_in_output_variables().indices()];
&env.subs.variables[alias_variables.infer_ext_in_output_variables().indices()];

for (old, new) in old_infer_ext_vars.iter_mut().zip(new_infer_ext_vars) {
debug_assert!(old.opt_abilities.is_none());
Expand All @@ -326,9 +313,8 @@ impl Aliases {
};

let alias_variable = type_to_var_help(
subs,
env,
rank,
pools,
problems,
abilities_store,
obligation_cache,
Expand Down
Loading

0 comments on commit ad20a2e

Please sign in to comment.