mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Validate derives clauses after solving
This commit is contained in:
parent
4cf87510c8
commit
a4c122d5db
11 changed files with 440 additions and 113 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue