mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-01 10:52:18 +00:00
Detect ability specializations that overload different opaque types
This commit is contained in:
parent
51bce825fb
commit
10db3f8574
5 changed files with 70 additions and 2 deletions
|
@ -279,6 +279,13 @@ impl<Phase: ResolvePhase> IAbilitiesStore<Phase> {
|
|||
id
|
||||
}
|
||||
|
||||
/// Finds the implementation key for a symbol specializing the ability member, if it specializes any.
|
||||
/// For example, suppose `hashId : Id -> U64` specializes `hash : a -> U64 | a has Hash`.
|
||||
/// Calling this with `hashId` would retrieve (hash, hashId).
|
||||
pub fn impl_key(&self, specializing_symbol: Symbol) -> Option<&ImplKey> {
|
||||
self.specialization_to_root.get(&specializing_symbol)
|
||||
}
|
||||
|
||||
/// 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>) -> PendingAbilitiesStore {
|
||||
|
@ -373,7 +380,7 @@ impl IAbilitiesStore<Resolved> {
|
|||
&self,
|
||||
specializing_symbol: Symbol,
|
||||
) -> Option<(ImplKey, &AbilityMemberData<Resolved>)> {
|
||||
let impl_key = self.specialization_to_root.get(&specializing_symbol)?;
|
||||
let impl_key = self.impl_key(specializing_symbol)?;
|
||||
debug_assert!(self.ability_members.contains_key(&impl_key.ability_member));
|
||||
let root_data = self
|
||||
.ability_members
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::abilities::AbilityMemberData;
|
||||
use crate::abilities::ImplKey;
|
||||
use crate::abilities::MemberVariables;
|
||||
use crate::abilities::PendingMemberType;
|
||||
use crate::annotation::canonicalize_annotation;
|
||||
|
@ -671,8 +672,30 @@ fn canonicalize_opaque<'a>(
|
|||
Err(()) => continue,
|
||||
};
|
||||
|
||||
let member_impl = MemberImpl::Impl(impl_symbol);
|
||||
// Did the user claim this implementation for a specialization of a different
|
||||
// type? e.g.
|
||||
//
|
||||
// A has [Hash {hash: myHash}]
|
||||
// B has [Hash {hash: myHash}]
|
||||
//
|
||||
// If so, that's an error and we drop the impl for this opaque type.
|
||||
let member_impl = match scope.abilities_store.impl_key(impl_symbol) {
|
||||
Some(ImplKey {
|
||||
opaque,
|
||||
ability_member,
|
||||
}) => {
|
||||
env.problem(Problem::OverloadedSpecialization {
|
||||
overload: loc_impl.region,
|
||||
original_opaque: *opaque,
|
||||
ability_member: *ability_member,
|
||||
});
|
||||
MemberImpl::Error
|
||||
}
|
||||
None => MemberImpl::Impl(impl_symbol),
|
||||
};
|
||||
|
||||
// Did the user already claim an implementation for the ability member for this
|
||||
// type previously? (e.g. Hash {hash: hash1, hash: hash2})
|
||||
let opt_old_impl_symbol =
|
||||
impl_map.insert(member, Loc::at(loc_impl.region, member_impl));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue