mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Correct imports of Encode and abilities across modules
This commit is contained in:
parent
47c9959786
commit
312cdd0b70
15 changed files with 375 additions and 214 deletions
|
@ -11,6 +11,7 @@ pub fn module_source(module_id: ModuleId) -> &'static str {
|
||||||
ModuleId::SET => SET,
|
ModuleId::SET => SET,
|
||||||
ModuleId::BOX => BOX,
|
ModuleId::BOX => BOX,
|
||||||
ModuleId::BOOL => BOOL,
|
ModuleId::BOOL => BOOL,
|
||||||
|
ModuleId::ENCODE => ENCODE,
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"ModuleId {:?} is not part of the standard library",
|
"ModuleId {:?} is not part of the standard library",
|
||||||
module_id
|
module_id
|
||||||
|
@ -26,3 +27,4 @@ const DICT: &str = include_str!("../roc/Dict.roc");
|
||||||
const SET: &str = include_str!("../roc/Set.roc");
|
const SET: &str = include_str!("../roc/Set.roc");
|
||||||
const BOX: &str = include_str!("../roc/Box.roc");
|
const BOX: &str = include_str!("../roc/Box.roc");
|
||||||
const BOOL: &str = include_str!("../roc/Bool.roc");
|
const BOOL: &str = include_str!("../roc/Bool.roc");
|
||||||
|
const ENCODE: &str = include_str!("../roc/Encode.roc");
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::{all::MutMap, VecSet};
|
||||||
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
use roc_types::{subs::Variable, types::Type};
|
use roc_types::{subs::Variable, types::Type};
|
||||||
|
@ -12,16 +13,37 @@ pub struct MemberVariables {
|
||||||
pub flex_vars: Vec<Variable>,
|
pub flex_vars: Vec<Variable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum MemberTypeInfo {
|
||||||
|
/// The member and its signature is defined locally, in the module the store is created for.
|
||||||
|
/// We need to instantiate and introduce this during solving.
|
||||||
|
Local {
|
||||||
|
signature_var: Variable,
|
||||||
|
signature: Type,
|
||||||
|
variables: MemberVariables,
|
||||||
|
},
|
||||||
|
/// The member was defined in another module, so we'll import its variable when it's time to
|
||||||
|
/// solve. At that point we'll resolve `var` here.
|
||||||
|
Imported { signature_var: Option<Variable> },
|
||||||
|
}
|
||||||
|
|
||||||
/// Stores information about an ability member definition, including the parent ability, the
|
/// Stores information about an ability member definition, including the parent ability, the
|
||||||
/// defining type, and what type variables need to be instantiated with instances of the ability.
|
/// defining type, and what type variables need to be instantiated with instances of the ability.
|
||||||
// TODO: SoA and put me in an arena
|
// TODO: SoA and put me in an arena
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AbilityMemberData {
|
pub struct AbilityMemberData {
|
||||||
pub parent_ability: Symbol,
|
pub parent_ability: Symbol,
|
||||||
pub signature_var: Variable,
|
|
||||||
pub signature: Type,
|
|
||||||
pub variables: MemberVariables,
|
|
||||||
pub region: Region,
|
pub region: Region,
|
||||||
|
pub typ: MemberTypeInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbilityMemberData {
|
||||||
|
pub fn signature_var(&self) -> Option<Variable> {
|
||||||
|
match self.typ {
|
||||||
|
MemberTypeInfo::Local { signature_var, .. } => Some(signature_var),
|
||||||
|
MemberTypeInfo::Imported { signature_var } => signature_var,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A particular specialization of an ability member.
|
/// A particular specialization of an ability member.
|
||||||
|
@ -77,24 +99,16 @@ pub struct AbilitiesStore {
|
||||||
|
|
||||||
impl AbilitiesStore {
|
impl AbilitiesStore {
|
||||||
/// Records the definition of an ability, including its members.
|
/// Records the definition of an ability, including its members.
|
||||||
pub fn register_ability(
|
pub fn register_ability<I>(&mut self, ability: Symbol, members: I)
|
||||||
&mut self,
|
where
|
||||||
ability: Symbol,
|
I: IntoIterator<Item = (Symbol, AbilityMemberData)>,
|
||||||
members: Vec<(Symbol, Region, Variable, Type, MemberVariables)>,
|
I::IntoIter: ExactSizeIterator,
|
||||||
) {
|
{
|
||||||
|
let members = members.into_iter();
|
||||||
let mut members_vec = Vec::with_capacity(members.len());
|
let mut members_vec = Vec::with_capacity(members.len());
|
||||||
for (member, region, signature_var, signature, variables) in members.into_iter() {
|
for (member, member_data) in members {
|
||||||
members_vec.push(member);
|
members_vec.push(member);
|
||||||
let old_member = self.ability_members.insert(
|
let old_member = self.ability_members.insert(member, member_data);
|
||||||
member,
|
|
||||||
AbilityMemberData {
|
|
||||||
parent_ability: ability,
|
|
||||||
signature_var,
|
|
||||||
signature,
|
|
||||||
region,
|
|
||||||
variables,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
debug_assert!(old_member.is_none(), "Replacing existing member definition");
|
debug_assert!(old_member.is_none(), "Replacing existing member definition");
|
||||||
}
|
}
|
||||||
let old_ability = self.members_of_ability.insert(ability, members_vec);
|
let old_ability = self.members_of_ability.insert(ability, members_vec);
|
||||||
|
@ -184,8 +198,6 @@ impl AbilitiesStore {
|
||||||
self.declared_specializations.get(&(member, typ)).copied()
|
self.declared_specializations.get(&(member, typ)).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns pairs of (type, ability member) specifying that "ability member" has a
|
|
||||||
/// specialization with type "type".
|
|
||||||
pub fn members_of_ability(&self, ability: Symbol) -> Option<&[Symbol]> {
|
pub fn members_of_ability(&self, ability: Symbol) -> Option<&[Symbol]> {
|
||||||
self.members_of_ability.get(&ability).map(|v| v.as_ref())
|
self.members_of_ability.get(&ability).map(|v| v.as_ref())
|
||||||
}
|
}
|
||||||
|
@ -222,4 +234,119 @@ impl AbilitiesStore {
|
||||||
pub fn get_resolved(&self, id: SpecializationId) -> Option<Symbol> {
|
pub fn get_resolved(&self, id: SpecializationId) -> Option<Symbol> {
|
||||||
self.resolved_specializations.get(&id).copied()
|
self.resolved_specializations.get(&id).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a store from [`self`] that closes over the abilities/members given by the
|
||||||
|
/// imported `symbols`, and their specializations (if any).
|
||||||
|
pub fn closure_from_imported(&self, symbols: &VecSet<Symbol>) -> Self {
|
||||||
|
let Self {
|
||||||
|
members_of_ability,
|
||||||
|
ability_members,
|
||||||
|
declared_specializations,
|
||||||
|
|
||||||
|
// Covered by `declared_specializations`
|
||||||
|
specialization_to_root: _,
|
||||||
|
|
||||||
|
// Taking closure for a new module, so specialization IDs can be fresh
|
||||||
|
next_specialization_id: _,
|
||||||
|
resolved_specializations: _,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
let mut new = Self::default();
|
||||||
|
|
||||||
|
// 1. Figure out the abilities we need to introduce.
|
||||||
|
let mut abilities_to_introduce = VecSet::with_capacity(2);
|
||||||
|
symbols.iter().for_each(|symbol| {
|
||||||
|
if let Some(member_data) = ability_members.get(symbol) {
|
||||||
|
// If the symbol is member of an ability, we need to capture the entire ability.
|
||||||
|
abilities_to_introduce.insert(member_data.parent_ability);
|
||||||
|
}
|
||||||
|
if members_of_ability.contains_key(symbol) {
|
||||||
|
abilities_to_introduce.insert(*symbol);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Add each ability, and any specializations of its members we know about.
|
||||||
|
for ability in abilities_to_introduce.into_iter() {
|
||||||
|
let members = members_of_ability.get(&ability).unwrap();
|
||||||
|
let mut imported_member_data = Vec::with_capacity(members.len());
|
||||||
|
for member in members {
|
||||||
|
let mut member_data = ability_members.get(member).unwrap().clone();
|
||||||
|
// All external members need to be marked as imported. We'll figure out their real
|
||||||
|
// type variables when it comes time to solve the module we're currently importing
|
||||||
|
// into.
|
||||||
|
member_data.typ = MemberTypeInfo::Imported {
|
||||||
|
signature_var: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
imported_member_data.push((*member, member_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
new.register_ability(ability, imported_member_data);
|
||||||
|
|
||||||
|
// Add any specializations of the ability's members we know about.
|
||||||
|
declared_specializations
|
||||||
|
.iter()
|
||||||
|
.filter(|((member, _), _)| members.contains(member))
|
||||||
|
.for_each(|(&(member, typ), &specialization)| {
|
||||||
|
new.register_specializing_symbol(specialization.symbol, member);
|
||||||
|
new.register_specialization_for_type(member, typ, specialization);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
new
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn union(&mut self, other: Self) {
|
||||||
|
let Self {
|
||||||
|
members_of_ability: other_members_of_ability,
|
||||||
|
ability_members: mut other_ability_members,
|
||||||
|
specialization_to_root,
|
||||||
|
declared_specializations,
|
||||||
|
next_specialization_id,
|
||||||
|
resolved_specializations,
|
||||||
|
} = other;
|
||||||
|
|
||||||
|
for (ability, members) in other_members_of_ability.into_iter() {
|
||||||
|
if let Some(my_members) = self.members_of_ability(ability) {
|
||||||
|
debug_assert!(
|
||||||
|
my_members == members,
|
||||||
|
"Two abilities have different definitions, definitely a bug"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let member_data = members
|
||||||
|
.into_iter()
|
||||||
|
.map(|member| (member, other_ability_members.remove(&member).unwrap()));
|
||||||
|
self.register_ability(ability, member_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (specialization, member) in specialization_to_root.into_iter() {
|
||||||
|
let old_root = self.specialization_to_root.insert(specialization, member);
|
||||||
|
debug_assert!(old_root.is_none() || old_root.unwrap() == member);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((member, typ), specialization) in declared_specializations.into_iter() {
|
||||||
|
let old_specialization = self
|
||||||
|
.declared_specializations
|
||||||
|
.insert((member, typ), specialization);
|
||||||
|
debug_assert!(
|
||||||
|
old_specialization.is_none() || old_specialization.unwrap() == specialization
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(next_specialization_id == 0);
|
||||||
|
debug_assert!(self.next_specialization_id == 0);
|
||||||
|
debug_assert!(resolved_specializations.is_empty());
|
||||||
|
debug_assert!(self.resolved_specializations.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolved_imported_member_var(&mut self, member: Symbol, var: Variable) {
|
||||||
|
let member_data = self.ability_members.get_mut(&member).unwrap();
|
||||||
|
match &mut member_data.typ {
|
||||||
|
MemberTypeInfo::Imported { signature_var } => {
|
||||||
|
let old = signature_var.replace(var);
|
||||||
|
debug_assert!(old.is_none(), "Replacing existing variable!");
|
||||||
|
}
|
||||||
|
_ => internal_error!("{:?} is not imported!", member),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::abilities::AbilityMemberData;
|
||||||
|
use crate::abilities::MemberTypeInfo;
|
||||||
use crate::abilities::MemberVariables;
|
use crate::abilities::MemberVariables;
|
||||||
use crate::annotation::canonicalize_annotation;
|
use crate::annotation::canonicalize_annotation;
|
||||||
use crate::annotation::find_type_def_symbols;
|
use crate::annotation::find_type_def_symbols;
|
||||||
|
@ -646,10 +648,15 @@ fn resolve_abilities<'a>(
|
||||||
|
|
||||||
can_members.push((
|
can_members.push((
|
||||||
member_sym,
|
member_sym,
|
||||||
name_region,
|
AbilityMemberData {
|
||||||
var_store.fresh(),
|
parent_ability: loc_ability_name.value,
|
||||||
member_annot.typ,
|
region: name_region,
|
||||||
|
typ: MemberTypeInfo::Local {
|
||||||
variables,
|
variables,
|
||||||
|
signature: member_annot.typ,
|
||||||
|
signature_var: var_store.fresh(),
|
||||||
|
},
|
||||||
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,13 +166,14 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
exposed_ident_ids: IdentIds,
|
exposed_ident_ids: IdentIds,
|
||||||
dep_idents: &'a IdentIdsByModule,
|
dep_idents: &'a IdentIdsByModule,
|
||||||
aliases: MutMap<Symbol, Alias>,
|
aliases: MutMap<Symbol, Alias>,
|
||||||
|
imported_abilities_state: AbilitiesStore,
|
||||||
exposed_imports: MutMap<Ident, (Symbol, Region)>,
|
exposed_imports: MutMap<Ident, (Symbol, Region)>,
|
||||||
exposed_symbols: &VecSet<Symbol>,
|
exposed_symbols: &VecSet<Symbol>,
|
||||||
symbols_from_requires: &[(Loc<Symbol>, Loc<TypeAnnotation<'a>>)],
|
symbols_from_requires: &[(Loc<Symbol>, Loc<TypeAnnotation<'a>>)],
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
) -> ModuleOutput {
|
) -> ModuleOutput {
|
||||||
let mut can_exposed_imports = MutMap::default();
|
let mut can_exposed_imports = MutMap::default();
|
||||||
let mut scope = Scope::new(home, exposed_ident_ids);
|
let mut scope = Scope::new(home, exposed_ident_ids, imported_abilities_state);
|
||||||
let mut env = Env::new(home, dep_idents, module_ids);
|
let mut env = Env::new(home, dep_idents, module_ids);
|
||||||
let num_deps = dep_idents.len();
|
let num_deps = dep_idents.len();
|
||||||
|
|
||||||
|
|
|
@ -191,15 +191,20 @@ pub fn canonicalize_def_header_pattern<'a>(
|
||||||
Identifier(name) => {
|
Identifier(name) => {
|
||||||
match scope.introduce_or_shadow_ability_member((*name).into(), region) {
|
match scope.introduce_or_shadow_ability_member((*name).into(), region) {
|
||||||
Ok((symbol, shadowing_ability_member)) => {
|
Ok((symbol, shadowing_ability_member)) => {
|
||||||
output.references.insert_bound(symbol);
|
|
||||||
let can_pattern = match shadowing_ability_member {
|
let can_pattern = match shadowing_ability_member {
|
||||||
// A fresh identifier.
|
// A fresh identifier.
|
||||||
None => Pattern::Identifier(symbol),
|
None => {
|
||||||
|
output.references.insert_bound(symbol);
|
||||||
|
Pattern::Identifier(symbol)
|
||||||
|
}
|
||||||
// Likely a specialization of an ability.
|
// Likely a specialization of an ability.
|
||||||
Some(ability_member_name) => Pattern::AbilityMemberSpecialization {
|
Some(ability_member_name) => {
|
||||||
|
output.references.insert_value_lookup(ability_member_name);
|
||||||
|
Pattern::AbilityMemberSpecialization {
|
||||||
ident: symbol,
|
ident: symbol,
|
||||||
specializes: ability_member_name,
|
specializes: ability_member_name,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Loc::at(region, can_pattern)
|
Loc::at(region, can_pattern)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,11 @@ pub struct Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
pub fn new(home: ModuleId, initial_ident_ids: IdentIds) -> Scope {
|
pub fn new(
|
||||||
|
home: ModuleId,
|
||||||
|
initial_ident_ids: IdentIds,
|
||||||
|
starting_abilities_store: AbilitiesStore,
|
||||||
|
) -> Scope {
|
||||||
let imports = Symbol::default_in_scope()
|
let imports = Symbol::default_in_scope()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(a, (b, c))| (a, b, c))
|
.map(|(a, (b, c))| (a, b, c))
|
||||||
|
@ -43,8 +47,7 @@ impl Scope {
|
||||||
exposed_ident_count: initial_ident_ids.len(),
|
exposed_ident_count: initial_ident_ids.len(),
|
||||||
locals: ScopedIdentIds::from_ident_ids(home, initial_ident_ids),
|
locals: ScopedIdentIds::from_ident_ids(home, initial_ident_ids),
|
||||||
aliases: VecMap::default(),
|
aliases: VecMap::default(),
|
||||||
// TODO(abilities): default abilities in scope
|
abilities_store: starting_abilities_store,
|
||||||
abilities_store: AbilitiesStore::default(),
|
|
||||||
imports,
|
imports,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -564,7 +567,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn scope_contains_introduced() {
|
fn scope_contains_introduced() {
|
||||||
let _register_module_debug_names = ModuleIds::default();
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
let mut scope = Scope::new(
|
||||||
|
ModuleId::ATTR,
|
||||||
|
IdentIds::default(),
|
||||||
|
AbilitiesStore::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let region = Region::zero();
|
let region = Region::zero();
|
||||||
let ident = Ident::from("mezolit");
|
let ident = Ident::from("mezolit");
|
||||||
|
@ -579,7 +586,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn second_introduce_shadows() {
|
fn second_introduce_shadows() {
|
||||||
let _register_module_debug_names = ModuleIds::default();
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
let mut scope = Scope::new(
|
||||||
|
ModuleId::ATTR,
|
||||||
|
IdentIds::default(),
|
||||||
|
AbilitiesStore::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let region1 = Region::from_pos(Position { offset: 10 });
|
let region1 = Region::from_pos(Position { offset: 10 });
|
||||||
let region2 = Region::from_pos(Position { offset: 20 });
|
let region2 = Region::from_pos(Position { offset: 20 });
|
||||||
|
@ -604,7 +615,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn inner_scope_does_not_influence_outer() {
|
fn inner_scope_does_not_influence_outer() {
|
||||||
let _register_module_debug_names = ModuleIds::default();
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
let mut scope = Scope::new(
|
||||||
|
ModuleId::ATTR,
|
||||||
|
IdentIds::default(),
|
||||||
|
AbilitiesStore::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let region = Region::zero();
|
let region = Region::zero();
|
||||||
let ident = Ident::from("uránia");
|
let ident = Ident::from("uránia");
|
||||||
|
@ -621,7 +636,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn default_idents_in_scope() {
|
fn default_idents_in_scope() {
|
||||||
let _register_module_debug_names = ModuleIds::default();
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
let scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
let scope = Scope::new(
|
||||||
|
ModuleId::ATTR,
|
||||||
|
IdentIds::default(),
|
||||||
|
AbilitiesStore::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let idents: Vec<_> = scope.idents_in_scope().collect();
|
let idents: Vec<_> = scope.idents_in_scope().collect();
|
||||||
|
|
||||||
|
@ -644,7 +663,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn idents_with_inner_scope() {
|
fn idents_with_inner_scope() {
|
||||||
let _register_module_debug_names = ModuleIds::default();
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
let mut scope = Scope::new(
|
||||||
|
ModuleId::ATTR,
|
||||||
|
IdentIds::default(),
|
||||||
|
AbilitiesStore::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let idents: Vec<_> = scope.idents_in_scope().collect();
|
let idents: Vec<_> = scope.idents_in_scope().collect();
|
||||||
|
|
||||||
|
@ -711,7 +734,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn import_is_in_scope() {
|
fn import_is_in_scope() {
|
||||||
let _register_module_debug_names = ModuleIds::default();
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
let mut scope = Scope::new(
|
||||||
|
ModuleId::ATTR,
|
||||||
|
IdentIds::default(),
|
||||||
|
AbilitiesStore::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let ident = Ident::from("product");
|
let ident = Ident::from("product");
|
||||||
let symbol = Symbol::LIST_PRODUCT;
|
let symbol = Symbol::LIST_PRODUCT;
|
||||||
|
@ -729,7 +756,11 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn shadow_of_import() {
|
fn shadow_of_import() {
|
||||||
let _register_module_debug_names = ModuleIds::default();
|
let _register_module_debug_names = ModuleIds::default();
|
||||||
let mut scope = Scope::new(ModuleId::ATTR, IdentIds::default());
|
let mut scope = Scope::new(
|
||||||
|
ModuleId::ATTR,
|
||||||
|
IdentIds::default(),
|
||||||
|
AbilitiesStore::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let ident = Ident::from("product");
|
let ident = Ident::from("product");
|
||||||
let symbol = Symbol::LIST_PRODUCT;
|
let symbol = Symbol::LIST_PRODUCT;
|
||||||
|
|
|
@ -55,7 +55,7 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
|
||||||
// rules multiple times unnecessarily.
|
// rules multiple times unnecessarily.
|
||||||
let loc_expr = operator::desugar_expr(arena, &loc_expr);
|
let loc_expr = operator::desugar_expr(arena, &loc_expr);
|
||||||
|
|
||||||
let mut scope = Scope::new(home, IdentIds::default());
|
let mut scope = Scope::new(home, IdentIds::default(), Default::default());
|
||||||
scope.add_alias(
|
scope.add_alias(
|
||||||
Symbol::NUM_INT,
|
Symbol::NUM_INT,
|
||||||
Region::zero(),
|
Region::zero(),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::expr::{constrain_def_make_constraint, constrain_def_pattern, Env};
|
use crate::expr::{constrain_def_make_constraint, constrain_def_pattern, Env};
|
||||||
use roc_builtins::std::StdLib;
|
use roc_builtins::std::StdLib;
|
||||||
use roc_can::abilities::AbilitiesStore;
|
use roc_can::abilities::{AbilitiesStore, MemberTypeInfo};
|
||||||
use roc_can::constraint::{Constraint, Constraints};
|
use roc_can::constraint::{Constraint, Constraints};
|
||||||
use roc_can::def::Declaration;
|
use roc_can::def::Declaration;
|
||||||
use roc_can::expected::Expected;
|
use roc_can::expected::Expected;
|
||||||
|
@ -176,6 +176,12 @@ pub fn frontload_ability_constraints(
|
||||||
mut constraint: Constraint,
|
mut constraint: Constraint,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
for (member_name, member_data) in abilities_store.root_ability_members().iter() {
|
for (member_name, member_data) in abilities_store.root_ability_members().iter() {
|
||||||
|
if let MemberTypeInfo::Local {
|
||||||
|
signature_var,
|
||||||
|
variables: vars,
|
||||||
|
signature,
|
||||||
|
} = &member_data.typ
|
||||||
|
{
|
||||||
let rigids = Default::default();
|
let rigids = Default::default();
|
||||||
let mut env = Env {
|
let mut env = Env {
|
||||||
home,
|
home,
|
||||||
|
@ -217,6 +223,7 @@ pub fn frontload_ability_constraints(
|
||||||
def_pattern_state,
|
def_pattern_state,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
constraint
|
constraint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ const MODULES: &[(ModuleId, &str)] = &[
|
||||||
(ModuleId::DICT, "Dict.roc"),
|
(ModuleId::DICT, "Dict.roc"),
|
||||||
(ModuleId::SET, "Set.roc"),
|
(ModuleId::SET, "Set.roc"),
|
||||||
(ModuleId::BOX, "Box.roc"),
|
(ModuleId::BOX, "Box.roc"),
|
||||||
|
(ModuleId::ENCODE, "Encode.roc"),
|
||||||
];
|
];
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -127,6 +127,7 @@ struct ModuleCache<'a> {
|
||||||
headers: MutMap<ModuleId, ModuleHeader<'a>>,
|
headers: MutMap<ModuleId, ModuleHeader<'a>>,
|
||||||
parsed: MutMap<ModuleId, ParsedModule<'a>>,
|
parsed: MutMap<ModuleId, ParsedModule<'a>>,
|
||||||
aliases: MutMap<ModuleId, MutMap<Symbol, (bool, Alias)>>,
|
aliases: MutMap<ModuleId, MutMap<Symbol, (bool, Alias)>>,
|
||||||
|
abilities: MutMap<ModuleId, AbilitiesStore>,
|
||||||
constrained: MutMap<ModuleId, ConstrainedModule>,
|
constrained: MutMap<ModuleId, ConstrainedModule>,
|
||||||
typechecked: MutMap<ModuleId, TypeCheckedModule<'a>>,
|
typechecked: MutMap<ModuleId, TypeCheckedModule<'a>>,
|
||||||
found_specializations: MutMap<ModuleId, FoundSpecializationsModule<'a>>,
|
found_specializations: MutMap<ModuleId, FoundSpecializationsModule<'a>>,
|
||||||
|
@ -146,51 +147,33 @@ impl Default for ModuleCache<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut module_names = MutMap::default();
|
let mut module_names = MutMap::default();
|
||||||
|
|
||||||
|
macro_rules! insert_builtins {
|
||||||
|
($($name:ident,)*) => {$(
|
||||||
module_names.insert(
|
module_names.insert(
|
||||||
ModuleId::RESULT,
|
ModuleId::$name,
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::RESULT)),
|
PQModuleName::Unqualified(ModuleName::from(ModuleName::$name)),
|
||||||
);
|
);
|
||||||
|
)*}
|
||||||
|
}
|
||||||
|
|
||||||
module_names.insert(
|
insert_builtins! {
|
||||||
ModuleId::LIST,
|
RESULT,
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::LIST)),
|
LIST,
|
||||||
);
|
STR,
|
||||||
|
DICT,
|
||||||
module_names.insert(
|
SET,
|
||||||
ModuleId::STR,
|
BOOL,
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::STR)),
|
NUM,
|
||||||
);
|
BOX,
|
||||||
|
ENCODE,
|
||||||
module_names.insert(
|
}
|
||||||
ModuleId::DICT,
|
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::DICT)),
|
|
||||||
);
|
|
||||||
|
|
||||||
module_names.insert(
|
|
||||||
ModuleId::SET,
|
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::SET)),
|
|
||||||
);
|
|
||||||
|
|
||||||
module_names.insert(
|
|
||||||
ModuleId::BOOL,
|
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::BOOL)),
|
|
||||||
);
|
|
||||||
|
|
||||||
module_names.insert(
|
|
||||||
ModuleId::NUM,
|
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::NUM)),
|
|
||||||
);
|
|
||||||
|
|
||||||
module_names.insert(
|
|
||||||
ModuleId::BOX,
|
|
||||||
PQModuleName::Unqualified(ModuleName::from(ModuleName::BOX)),
|
|
||||||
);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
module_names,
|
module_names,
|
||||||
headers: Default::default(),
|
headers: Default::default(),
|
||||||
parsed: Default::default(),
|
parsed: Default::default(),
|
||||||
aliases: Default::default(),
|
aliases: Default::default(),
|
||||||
|
abilities: Default::default(),
|
||||||
constrained: Default::default(),
|
constrained: Default::default(),
|
||||||
typechecked: Default::default(),
|
typechecked: Default::default(),
|
||||||
found_specializations: Default::default(),
|
found_specializations: Default::default(),
|
||||||
|
@ -305,10 +288,12 @@ fn start_phase<'a>(
|
||||||
|
|
||||||
let exposed_symbols = state
|
let exposed_symbols = state
|
||||||
.exposed_symbols_by_module
|
.exposed_symbols_by_module
|
||||||
.remove(&module_id)
|
.get(&module_id)
|
||||||
.expect("Could not find listener ID in exposed_symbols_by_module");
|
.expect("Could not find listener ID in exposed_symbols_by_module")
|
||||||
|
.clone();
|
||||||
|
|
||||||
let mut aliases = MutMap::default();
|
let mut aliases = MutMap::default();
|
||||||
|
let mut abilities_store = AbilitiesStore::default();
|
||||||
|
|
||||||
for imported in parsed.imported_modules.keys() {
|
for imported in parsed.imported_modules.keys() {
|
||||||
match state.module_cache.aliases.get(imported) {
|
match state.module_cache.aliases.get(imported) {
|
||||||
|
@ -327,6 +312,27 @@ fn start_phase<'a>(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match state.module_cache.abilities.get(imported) {
|
||||||
|
None => unreachable!(
|
||||||
|
r"imported module {:?} did not register its abilities, so {:?} cannot use them",
|
||||||
|
imported, parsed.module_id,
|
||||||
|
),
|
||||||
|
Some(import_store) => {
|
||||||
|
let exposed_symbols = state
|
||||||
|
.exposed_symbols_by_module
|
||||||
|
.get(imported)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
internal_error!(
|
||||||
|
"Could not find exposed symbols of imported {:?}",
|
||||||
|
imported
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
abilities_store
|
||||||
|
.union(import_store.closure_from_imported(exposed_symbols));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let skip_constraint_gen = {
|
let skip_constraint_gen = {
|
||||||
|
@ -341,6 +347,7 @@ fn start_phase<'a>(
|
||||||
exposed_symbols,
|
exposed_symbols,
|
||||||
module_ids,
|
module_ids,
|
||||||
aliases,
|
aliases,
|
||||||
|
abilities_store,
|
||||||
skip_constraint_gen,
|
skip_constraint_gen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -866,6 +873,7 @@ enum BuildTask<'a> {
|
||||||
dep_idents: IdentIdsByModule,
|
dep_idents: IdentIdsByModule,
|
||||||
exposed_symbols: VecSet<Symbol>,
|
exposed_symbols: VecSet<Symbol>,
|
||||||
aliases: MutMap<Symbol, Alias>,
|
aliases: MutMap<Symbol, Alias>,
|
||||||
|
abilities_store: AbilitiesStore,
|
||||||
skip_constraint_gen: bool,
|
skip_constraint_gen: bool,
|
||||||
},
|
},
|
||||||
Solve {
|
Solve {
|
||||||
|
@ -2028,6 +2036,11 @@ fn update<'a>(
|
||||||
.aliases
|
.aliases
|
||||||
.insert(module_id, constrained_module.module.aliases.clone());
|
.insert(module_id, constrained_module.module.aliases.clone());
|
||||||
|
|
||||||
|
state
|
||||||
|
.module_cache
|
||||||
|
.abilities
|
||||||
|
.insert(module_id, constrained_module.module.abilities_store.clone());
|
||||||
|
|
||||||
state
|
state
|
||||||
.module_cache
|
.module_cache
|
||||||
.constrained
|
.constrained
|
||||||
|
@ -2644,90 +2657,36 @@ fn load_module<'a>(
|
||||||
|
|
||||||
module_timing.read_roc_file = Default::default();
|
module_timing.read_roc_file = Default::default();
|
||||||
module_timing.parse_header = parse_header_duration;
|
module_timing.parse_header = parse_header_duration;
|
||||||
|
|
||||||
|
macro_rules! load_builtins {
|
||||||
|
($($name:literal, $module_id:path)*) => {
|
||||||
match module_name.as_inner().as_str() {
|
match module_name.as_inner().as_str() {
|
||||||
"Result" => {
|
$(
|
||||||
|
$name => {
|
||||||
return Ok(load_builtin_module(
|
return Ok(load_builtin_module(
|
||||||
arena,
|
arena,
|
||||||
module_ids,
|
module_ids,
|
||||||
ident_ids_by_module,
|
ident_ids_by_module,
|
||||||
module_timing,
|
module_timing,
|
||||||
ModuleId::RESULT,
|
$module_id,
|
||||||
"Result.roc",
|
concat!($name, ".roc")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
"List" => {
|
)*
|
||||||
return Ok(load_builtin_module(
|
_ => { /* fall through */ }
|
||||||
arena,
|
}}
|
||||||
module_ids,
|
|
||||||
ident_ids_by_module,
|
|
||||||
module_timing,
|
|
||||||
ModuleId::LIST,
|
|
||||||
"List.roc",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"Str" => {
|
|
||||||
return Ok(load_builtin_module(
|
|
||||||
arena,
|
|
||||||
module_ids,
|
|
||||||
ident_ids_by_module,
|
|
||||||
module_timing,
|
|
||||||
ModuleId::STR,
|
|
||||||
"Str.roc",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"Dict" => {
|
|
||||||
return Ok(load_builtin_module(
|
|
||||||
arena,
|
|
||||||
module_ids,
|
|
||||||
ident_ids_by_module,
|
|
||||||
module_timing,
|
|
||||||
ModuleId::DICT,
|
|
||||||
"Dict.roc",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"Set" => {
|
|
||||||
return Ok(load_builtin_module(
|
|
||||||
arena,
|
|
||||||
module_ids,
|
|
||||||
ident_ids_by_module,
|
|
||||||
module_timing,
|
|
||||||
ModuleId::SET,
|
|
||||||
"Set.roc",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"Num" => {
|
|
||||||
return Ok(load_builtin_module(
|
|
||||||
arena,
|
|
||||||
module_ids,
|
|
||||||
ident_ids_by_module,
|
|
||||||
module_timing,
|
|
||||||
ModuleId::NUM,
|
|
||||||
"Num.roc",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"Bool" => {
|
|
||||||
return Ok(load_builtin_module(
|
|
||||||
arena,
|
|
||||||
module_ids,
|
|
||||||
ident_ids_by_module,
|
|
||||||
module_timing,
|
|
||||||
ModuleId::BOOL,
|
|
||||||
"Bool.roc",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"Box" => {
|
|
||||||
return Ok(load_builtin_module(
|
|
||||||
arena,
|
|
||||||
module_ids,
|
|
||||||
ident_ids_by_module,
|
|
||||||
module_timing,
|
|
||||||
ModuleId::BOX,
|
|
||||||
"Box.roc",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// fall through
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_builtins! {
|
||||||
|
"Result", ModuleId::RESULT
|
||||||
|
"List", ModuleId::LIST
|
||||||
|
"Str", ModuleId::STR
|
||||||
|
"Dict", ModuleId::DICT
|
||||||
|
"Set", ModuleId::SET
|
||||||
|
"Num", ModuleId::NUM
|
||||||
|
"Bool", ModuleId::BOOL
|
||||||
|
"Box", ModuleId::BOX
|
||||||
|
"Encode", ModuleId::ENCODE
|
||||||
}
|
}
|
||||||
|
|
||||||
let (filename, opt_shorthand) = module_name_to_path(src_dir, module_name, arc_shorthands);
|
let (filename, opt_shorthand) = module_name_to_path(src_dir, module_name, arc_shorthands);
|
||||||
|
@ -3569,6 +3528,7 @@ impl<'a> BuildTask<'a> {
|
||||||
|
|
||||||
fn add_imports(
|
fn add_imports(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
|
abilities_store: &mut AbilitiesStore,
|
||||||
mut exposed_for_module: ExposedForModule,
|
mut exposed_for_module: ExposedForModule,
|
||||||
def_types: &mut Vec<(Symbol, Loc<roc_types::types::Type>)>,
|
def_types: &mut Vec<(Symbol, Loc<roc_types::types::Type>)>,
|
||||||
rigid_vars: &mut Vec<Variable>,
|
rigid_vars: &mut Vec<Variable>,
|
||||||
|
@ -3610,6 +3570,10 @@ fn add_imports(
|
||||||
rigid_vars.extend(copied_import.flex_able);
|
rigid_vars.extend(copied_import.flex_able);
|
||||||
|
|
||||||
import_variables.extend(copied_import.registered);
|
import_variables.extend(copied_import.registered);
|
||||||
|
|
||||||
|
if abilities_store.is_ability_member_name(symbol) {
|
||||||
|
abilities_store.resolved_imported_member_var(symbol, copied_import.variable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
internal_error!("Imported module {:?} is not available", module_id)
|
internal_error!("Imported module {:?} is not available", module_id)
|
||||||
|
@ -3638,7 +3602,7 @@ fn run_solve_solve(
|
||||||
exposed_symbols,
|
exposed_symbols,
|
||||||
aliases,
|
aliases,
|
||||||
rigid_variables,
|
rigid_variables,
|
||||||
abilities_store,
|
mut abilities_store,
|
||||||
..
|
..
|
||||||
} = module;
|
} = module;
|
||||||
|
|
||||||
|
@ -3649,6 +3613,7 @@ fn run_solve_solve(
|
||||||
|
|
||||||
let import_variables = add_imports(
|
let import_variables = add_imports(
|
||||||
&mut subs,
|
&mut subs,
|
||||||
|
&mut abilities_store,
|
||||||
exposed_for_module,
|
exposed_for_module,
|
||||||
&mut def_types,
|
&mut def_types,
|
||||||
&mut rigid_vars,
|
&mut rigid_vars,
|
||||||
|
@ -3835,6 +3800,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
dep_idents: IdentIdsByModule,
|
dep_idents: IdentIdsByModule,
|
||||||
exposed_symbols: VecSet<Symbol>,
|
exposed_symbols: VecSet<Symbol>,
|
||||||
aliases: MutMap<Symbol, Alias>,
|
aliases: MutMap<Symbol, Alias>,
|
||||||
|
imported_abilities_state: AbilitiesStore,
|
||||||
parsed: ParsedModule<'a>,
|
parsed: ParsedModule<'a>,
|
||||||
skip_constraint_gen: bool,
|
skip_constraint_gen: bool,
|
||||||
) -> CanAndCon {
|
) -> CanAndCon {
|
||||||
|
@ -3866,6 +3832,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
exposed_ident_ids,
|
exposed_ident_ids,
|
||||||
&dep_idents,
|
&dep_idents,
|
||||||
aliases,
|
aliases,
|
||||||
|
imported_abilities_state,
|
||||||
exposed_imports,
|
exposed_imports,
|
||||||
&exposed_symbols,
|
&exposed_symbols,
|
||||||
&symbols_from_requires,
|
&symbols_from_requires,
|
||||||
|
@ -3944,7 +3911,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
Vacant(vacant) => {
|
Vacant(vacant) => {
|
||||||
if !name.is_builtin() {
|
if !name.is_builtin() || name.module_id() == ModuleId::ENCODE {
|
||||||
vacant.insert((false, alias));
|
vacant.insert((false, alias));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4438,6 +4405,7 @@ fn run_task<'a>(
|
||||||
dep_idents,
|
dep_idents,
|
||||||
exposed_symbols,
|
exposed_symbols,
|
||||||
aliases,
|
aliases,
|
||||||
|
abilities_store,
|
||||||
skip_constraint_gen,
|
skip_constraint_gen,
|
||||||
} => {
|
} => {
|
||||||
let can_and_con = canonicalize_and_constrain(
|
let can_and_con = canonicalize_and_constrain(
|
||||||
|
@ -4446,6 +4414,7 @@ fn run_task<'a>(
|
||||||
dep_idents,
|
dep_idents,
|
||||||
exposed_symbols,
|
exposed_symbols,
|
||||||
aliases,
|
aliases,
|
||||||
|
abilities_store,
|
||||||
parsed,
|
parsed,
|
||||||
skip_constraint_gen,
|
skip_constraint_gen,
|
||||||
);
|
);
|
||||||
|
|
|
@ -89,6 +89,7 @@ impl ModuleName {
|
||||||
pub const SET: &'static str = "Set";
|
pub const SET: &'static str = "Set";
|
||||||
pub const RESULT: &'static str = "Result";
|
pub const RESULT: &'static str = "Result";
|
||||||
pub const BOX: &'static str = "Box";
|
pub const BOX: &'static str = "Box";
|
||||||
|
pub const ENCODE: &'static str = "Encode";
|
||||||
|
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
self.0.as_str()
|
self.0.as_str()
|
||||||
|
|
|
@ -1309,8 +1309,10 @@ define_builtins! {
|
||||||
0 BOX_BOX_TYPE: "Box" imported // the Box.Box opaque type
|
0 BOX_BOX_TYPE: "Box" imported // the Box.Box opaque type
|
||||||
1 BOX_BOX_FUNCTION: "box" // Box.box
|
1 BOX_BOX_FUNCTION: "box" // Box.box
|
||||||
2 BOX_UNBOX: "unbox"
|
2 BOX_UNBOX: "unbox"
|
||||||
|
}
|
||||||
|
9 ENCODE: "Encode" => {
|
||||||
|
0 ENCODE_ENCODE: "Encode"
|
||||||
}
|
}
|
||||||
|
|
||||||
num_modules: 9 // Keep this count up to date by hand! (TODO: see the mut_map! macro for how we could determine this count correctly in the macro)
|
num_modules: 10 // Keep this count up to date by hand! (TODO: see the mut_map! macro for how we could determine this count correctly in the macro)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use roc_can::abilities::AbilitiesStore;
|
use roc_can::abilities::AbilitiesStore;
|
||||||
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::subs::Subs;
|
use roc_types::subs::Subs;
|
||||||
|
@ -20,7 +21,7 @@ pub enum AbilityImplError {
|
||||||
BadPattern(Region, PatternCategory, Variable),
|
BadPattern(Region, PatternCategory, Variable),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Debug)]
|
||||||
pub struct DeferredMustImplementAbility(Vec<(MustImplementConstraints, AbilityImplError)>);
|
pub struct DeferredMustImplementAbility(Vec<(MustImplementConstraints, AbilityImplError)>);
|
||||||
|
|
||||||
impl DeferredMustImplementAbility {
|
impl DeferredMustImplementAbility {
|
||||||
|
@ -201,9 +202,14 @@ pub fn resolve_ability_specialization(
|
||||||
.expect("Not an ability member symbol");
|
.expect("Not an ability member symbol");
|
||||||
|
|
||||||
let snapshot = subs.snapshot();
|
let snapshot = subs.snapshot();
|
||||||
instantiate_rigids(subs, member_def.signature_var);
|
|
||||||
let (_, must_implement_ability) =
|
let signature_var = member_def
|
||||||
unify(subs, specialization_var, member_def.signature_var, Mode::EQ).expect_success(
|
.signature_var()
|
||||||
|
.unwrap_or_else(|| internal_error!("Signature var not resolved for {:?}", ability_member));
|
||||||
|
|
||||||
|
instantiate_rigids(subs, signature_var);
|
||||||
|
let (_, must_implement_ability) = unify(subs, specialization_var, signature_var, Mode::EQ)
|
||||||
|
.expect_success(
|
||||||
"If resolving a specialization, the specialization must be known to typecheck.",
|
"If resolving a specialization, the specialization must be known to typecheck.",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -314,7 +314,7 @@ impl Aliases {
|
||||||
|
|
||||||
let (typ, delayed_variables, &mut kind) =
|
let (typ, delayed_variables, &mut kind) =
|
||||||
match self.aliases.iter_mut().find(|(s, _, _, _)| *s == symbol) {
|
match self.aliases.iter_mut().find(|(s, _, _, _)| *s == symbol) {
|
||||||
None => return Err(()),
|
None => panic!("{:?}", &self.aliases),
|
||||||
Some((_, typ, delayed_variables, kind)) => (typ, delayed_variables, kind),
|
Some((_, typ, delayed_variables, kind)) => (typ, delayed_variables, kind),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1495,7 +1495,9 @@ fn check_ability_specialization(
|
||||||
// inferred type for the specialization actually aligns with the expected
|
// inferred type for the specialization actually aligns with the expected
|
||||||
// implementation.
|
// implementation.
|
||||||
if let Some((root_symbol, root_data)) = abilities_store.root_name_and_def(symbol) {
|
if let Some((root_symbol, root_data)) = abilities_store.root_name_and_def(symbol) {
|
||||||
let root_signature_var = root_data.signature_var;
|
let root_signature_var = root_data
|
||||||
|
.signature_var()
|
||||||
|
.unwrap_or_else(|| internal_error!("Signature var not resolved for {:?}", root_symbol));
|
||||||
|
|
||||||
// Check if they unify - if they don't, then the claimed specialization isn't really one,
|
// Check if they unify - if they don't, then the claimed specialization isn't really one,
|
||||||
// and that's a type error!
|
// and that's a type error!
|
||||||
|
|
|
@ -149,7 +149,7 @@ pub fn can_expr_with<'a>(
|
||||||
// rules multiple times unnecessarily.
|
// rules multiple times unnecessarily.
|
||||||
let loc_expr = operator::desugar_expr(arena, &loc_expr);
|
let loc_expr = operator::desugar_expr(arena, &loc_expr);
|
||||||
|
|
||||||
let mut scope = Scope::new(home, IdentIds::default());
|
let mut scope = Scope::new(home, IdentIds::default(), Default::default());
|
||||||
|
|
||||||
// to skip loading other modules, we populate the scope with the builtin aliases
|
// to skip loading other modules, we populate the scope with the builtin aliases
|
||||||
// that makes the reporting tests much faster
|
// that makes the reporting tests much faster
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue