Validate derives clauses after solving

This commit is contained in:
Ayaz Hafiz 2022-05-20 15:53:47 -04:00
parent 4cf87510c8
commit a4c122d5db
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
11 changed files with 440 additions and 113 deletions

View file

@ -1,12 +1,13 @@
use crate::ability::{
resolve_ability_specialization, type_implementing_specialization, AbilityImplError,
DeferredMustImplementAbility, Resolved, Unfulfilled,
DeferredObligations, DeriveKey, PendingDerivesTable, Resolved, Unfulfilled,
};
use bumpalo::Bump;
use roc_can::abilities::{AbilitiesStore, MemberSpecialization};
use roc_can::constraint::Constraint::{self, *};
use roc_can::constraint::{Constraints, Cycle, LetConstraint, OpportunisticResolve};
use roc_can::expected::{Expected, PExpected};
use roc_can::expr::PendingDerives;
use roc_collections::all::MutMap;
use roc_debug_flags::dbg_do;
#[cfg(debug_assertions)]
@ -418,7 +419,7 @@ impl Env {
const DEFAULT_POOLS: usize = 8;
#[derive(Clone, Debug)]
struct Pools(Vec<Vec<Variable>>);
pub(crate) struct Pools(Vec<Vec<Variable>>);
impl Default for Pools {
fn default() -> Self {
@ -481,6 +482,7 @@ pub fn run(
mut subs: Subs,
aliases: &mut Aliases,
constraint: &Constraint,
pending_derives: PendingDerives,
abilities_store: &mut AbilitiesStore,
) -> (Solved<Subs>, Env) {
let env = run_in_place(
@ -489,6 +491,7 @@ pub fn run(
&mut subs,
aliases,
constraint,
pending_derives,
abilities_store,
);
@ -502,6 +505,7 @@ fn run_in_place(
subs: &mut Subs,
aliases: &mut Aliases,
constraint: &Constraint,
pending_derives: PendingDerives,
abilities_store: &mut AbilitiesStore,
) -> Env {
let mut pools = Pools::default();
@ -513,7 +517,8 @@ fn run_in_place(
let rank = Rank::toplevel();
let arena = Bump::new();
let mut deferred_must_implement_abilities = DeferredMustImplementAbility::default();
let pending_derives = PendingDerivesTable::new(subs, aliases, pending_derives);
let mut deferred_obligations = DeferredObligations::new(pending_derives);
let state = solve(
&arena,
@ -526,12 +531,14 @@ fn run_in_place(
subs,
constraint,
abilities_store,
&mut deferred_must_implement_abilities,
&mut deferred_obligations,
);
// Now that the module has been solved, we can run through and check all
// types claimed to implement abilities.
problems.extend(deferred_must_implement_abilities.check_all(subs, abilities_store));
// types claimed to implement abilities. This will also tell us what derives
// are legal, which we need to register.
let (obligation_problems, _derived) = deferred_obligations.check_all(subs, abilities_store);
problems.extend(obligation_problems);
state.env
}
@ -584,7 +591,7 @@ fn solve(
subs: &mut Subs,
constraint: &Constraint,
abilities_store: &mut AbilitiesStore,
deferred_must_implement_abilities: &mut DeferredMustImplementAbility,
deferred_obligations: &mut DeferredObligations,
) -> State {
let initial = Work::Constraint {
env: &Env::default(),
@ -644,7 +651,7 @@ fn solve(
rank,
abilities_store,
problems,
deferred_must_implement_abilities,
deferred_obligations,
*symbol,
*loc_var,
);
@ -749,7 +756,7 @@ fn solve(
rank,
abilities_store,
problems,
deferred_must_implement_abilities,
deferred_obligations,
*symbol,
*loc_var,
);
@ -804,7 +811,7 @@ fn solve(
} => {
introduce(subs, rank, pools, &vars);
if !must_implement_ability.is_empty() {
deferred_must_implement_abilities.add(
deferred_obligations.add(
must_implement_ability,
AbilityImplError::BadExpr(*region, category.clone(), actual),
);
@ -911,7 +918,7 @@ fn solve(
} => {
introduce(subs, rank, pools, &vars);
if !must_implement_ability.is_empty() {
deferred_must_implement_abilities.add(
deferred_obligations.add(
must_implement_ability,
AbilityImplError::BadExpr(
*region,
@ -988,7 +995,7 @@ fn solve(
} => {
introduce(subs, rank, pools, &vars);
if !must_implement_ability.is_empty() {
deferred_must_implement_abilities.add(
deferred_obligations.add(
must_implement_ability,
AbilityImplError::BadPattern(*region, category.clone(), actual),
);
@ -1150,7 +1157,7 @@ fn solve(
} => {
introduce(subs, rank, pools, &vars);
if !must_implement_ability.is_empty() {
deferred_must_implement_abilities.add(
deferred_obligations.add(
must_implement_ability,
AbilityImplError::BadPattern(
*region,
@ -1479,7 +1486,7 @@ fn check_ability_specialization(
rank: Rank,
abilities_store: &mut AbilitiesStore,
problems: &mut Vec<TypeError>,
deferred_must_implement_abilities: &mut DeferredMustImplementAbility,
deferred_obligations: &mut DeferredObligations,
symbol: Symbol,
symbol_loc_var: Loc<Variable>,
) {
@ -1531,8 +1538,13 @@ fn check_ability_specialization(
// Make sure we check that the opaque has specialized all members of the
// ability, after we finish solving the module.
deferred_must_implement_abilities
deferred_obligations
.add(must_implement_ability, AbilityImplError::IncompleteAbility);
// This specialization dominates any derives that might be present.
deferred_obligations.dominate(DeriveKey {
opaque,
ability: parent_ability,
});
}
Some(Obligated::Adhoc(var)) => {
// This is a specialization of a structural type - never allowed.
@ -1701,7 +1713,7 @@ fn either_type_index_to_var(
}
}
fn type_to_var(
pub(crate) fn type_to_var(
subs: &mut Subs,
rank: Rank,
pools: &mut Pools,