Internal error when late compaction fails

This commit is contained in:
Ayaz Hafiz 2022-06-08 11:40:58 -04:00
parent f4fc9cbe04
commit 266f56d25b
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 37 additions and 6 deletions

View file

@ -3,7 +3,7 @@
use bumpalo::Bump; use bumpalo::Bump;
use roc_can::abilities::AbilitiesStore; use roc_can::abilities::AbilitiesStore;
use roc_solve::solve::{compact_lambda_sets_of_vars, Pools}; use roc_solve::solve::{compact_lambda_sets_of_vars, Phase, Pools};
use roc_types::subs::{Subs, Variable}; use roc_types::subs::{Subs, Variable};
use roc_unify::unify::{unify as unify_unify, Mode, Unified}; use roc_unify::unify::{unify as unify_unify, Mode, Unified};
@ -33,6 +33,7 @@ pub fn unify(
&mut pools, &mut pools,
abilities_store, abilities_store,
lambda_sets_to_specialize, lambda_sets_to_specialize,
Phase::Late,
); );
// Pools are only used to keep track of variable ranks for generalization purposes. // Pools are only used to keep track of variable ranks for generalization purposes.
// Since we break generalization during monomorphization, `pools` is irrelevant // Since we break generalization during monomorphization, `pools` is irrelevant

View file

@ -81,6 +81,18 @@ use roc_unify::unify::{unify, Mode, Obligated, Unified::*};
// Ranks are used to limit the number of type variables considered for generalization. Only those inside // Ranks are used to limit the number of type variables considered for generalization. Only those inside
// of the let (so those used in inferring the type of `\x -> x`) are considered. // of the let (so those used in inferring the type of `\x -> x`) are considered.
/// What phase in the compiler is reaching out to solve types.
/// This is important to distinguish subtle differences in the behavior of the solving algorithm.
#[derive(Clone, Copy)]
pub enum Phase {
/// The regular type-solving phase.
/// Here we can assume that some information is still unknown, and react to that.
Solve,
/// Calls into solve during later phases of compilation, namely monomorphization.
/// Here we expect all information is known.
Late,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum TypeError { pub enum TypeError {
BadExpr(Region, Category, ErrorType, Expected<ErrorType>), BadExpr(Region, Category, ErrorType, Expected<ErrorType>),
@ -563,6 +575,7 @@ fn run_in_place(
&mut pools, &mut pools,
abilities_store, abilities_store,
deferred_uls_to_resolve, deferred_uls_to_resolve,
Phase::Solve,
); );
state.env state.env
@ -1771,6 +1784,7 @@ pub fn compact_lambda_sets_of_vars(
pools: &mut Pools, pools: &mut Pools,
abilities_store: &AbilitiesStore, abilities_store: &AbilitiesStore,
uls_of_var: UlsOfVar, uls_of_var: UlsOfVar,
phase: Phase,
) { ) {
let mut seen = VecSet::default(); let mut seen = VecSet::default();
for (_, lambda_sets) in uls_of_var.drain() { for (_, lambda_sets) in uls_of_var.drain() {
@ -1780,7 +1794,7 @@ pub fn compact_lambda_sets_of_vars(
continue; continue;
} }
compact_lambda_set(subs, arena, pools, abilities_store, root_lset); compact_lambda_set(subs, arena, pools, abilities_store, root_lset, phase);
seen.insert(root_lset); seen.insert(root_lset);
} }
} }
@ -1792,6 +1806,7 @@ fn compact_lambda_set(
pools: &mut Pools, pools: &mut Pools,
abilities_store: &AbilitiesStore, abilities_store: &AbilitiesStore,
this_lambda_set: Variable, this_lambda_set: Variable,
phase: Phase,
) { ) {
let LambdaSet { let LambdaSet {
solved, solved,
@ -1842,12 +1857,20 @@ fn compact_lambda_set(
} }
}; };
let specialized_lambda_set = match abilities_store.get_specialization(member, *opaque) { let opt_specialization = abilities_store.get_specialization(member, *opaque);
None => { let specialized_lambda_set = match (phase, opt_specialization) {
(Phase::Solve, None) => {
// doesn't specialize, we'll have reported an error for this // doesn't specialize, we'll have reported an error for this
continue; continue;
} }
Some(specialization) => *specialization (Phase::Late, None) => {
internal_error!(
"expected to know a specialization for {:?}#{:?}, but it wasn't found",
opaque,
member
);
}
(_, Some(specialization)) => *specialization
.specialization_lambda_sets .specialization_lambda_sets
.get(&region) .get(&region)
.expect("lambda set region not resolved"), .expect("lambda set region not resolved"),
@ -1855,7 +1878,14 @@ fn compact_lambda_set(
// Ensure the specialization lambda set is already compacted. // Ensure the specialization lambda set is already compacted.
if subs.get_root_key(specialized_lambda_set) != subs.get_root_key(this_lambda_set) { if subs.get_root_key(specialized_lambda_set) != subs.get_root_key(this_lambda_set) {
compact_lambda_set(subs, arena, pools, abilities_store, specialized_lambda_set); compact_lambda_set(
subs,
arena,
pools,
abilities_store,
specialized_lambda_set,
phase,
);
} }
// Ensure the specialization lambda set we'll unify with is not a generalized one, but one // Ensure the specialization lambda set we'll unify with is not a generalized one, but one