use super::*;
use crate::mapping::{ImplHeaderFailure, ImplToTrait};
#[derive(Debug, Clone)]
pub struct ForeignTrait<D: TypeData> {
pub identifier: D::Trait,
pub generics: Generics<D>,
methods: Vec<ForeignFunction<D>>,
}
impl<D: TypeData> ForeignTrait<D> {
pub fn new(identifier: D::Trait, generics: Generics<D>) -> Self {
if !generics.iter().all(|(_, constr)| constr.is_empty()) {
panic!(
"Constraining the type parameters of a trait declaration is currently unsupported"
);
}
Self::with_capacity(identifier, generics, 0)
}
pub fn with_capacity(identifier: D::Trait, generics: Generics<D>, cap: usize) -> Self {
ForeignTrait {
identifier,
generics,
methods: Vec::with_capacity(cap),
}
}
pub fn push_method(&mut self, method: ForeignFunction<D>) {
self.methods.push(method);
}
pub fn instantiate(&self, tenv: &mut TEnv<D>) -> InstantiatedTrait<D> {
let mut mapping = self.generics.to_mapping(tenv);
let rid = tenv.spawn_with_cons(vec![Constraint {
trid: self.identifier.clone(),
params: mapping.to_types(D::Meta::default()), }]);
mapping.assign_self(rid);
InstantiatedTrait {
trid: self.identifier.clone(),
mapping,
methods: &self.methods,
}
}
}
#[derive(Debug, Clone)]
pub struct InstantiatedTrait<'a, D: TypeData> {
pub trid: D::Trait,
mapping: Mapping<D>,
pub methods: &'a Vec<ForeignFunction<D>>,
}
impl<'a, D: TypeData> InstantiatedTrait<'a, D> {
pub fn set_self(&self, t: Type<D>, tenv: &mut TEnv<D>) {
let rid = self.mapping.resolve_self().unwrap();
tenv.assign(rid, t);
}
pub fn set_self_check_constraint(
&self,
tenv: &mut TEnv<D>,
traits: &TraitIndex<D>,
t: Type<D>,
) -> Result<(), check::Error<D>> {
let rid = self.mapping.resolve_self().unwrap();
TypeContext::new(tenv, traits, ErrorHandler::Expensive).check_constraints_then_assign(
rid,
&[],
t,
)
}
pub fn method(&self, mid: usize, tenv: &mut TEnv<D>) -> Function<D> {
let mut mapping = self.mapping.clone();
let f = &self.methods[mid];
f.generics.append_to_mapping(tenv, &mut mapping);
let ptypes = mapping.apply_types(&f.function.ptypes);
let returns = mapping.apply_type(&f.function.returns);
Function::new(ptypes, returns)
}
pub fn generate_method_annotation(&self, mid: usize, tenv: &TEnv<D>) -> ForeignFunction<D> {
let mut tenv = tenv.clone();
let instantiated = self.method(mid, &mut tenv);
instantiated.to_foreign(&tenv, Generics::new())
}
pub fn mapping_mut(&mut self) -> &mut Mapping<D> {
&mut self.mapping
}
pub fn verify_method_annotation(
&self,
mid: usize,
method: ForeignFunction<D>,
tenv: &TEnv<D>,
) -> (ForeignFunction<D>, Vec<ImplHeaderFailure<D>>) {
assert!(self.mapping.resolve_self().is_some());
let expected = &self.methods[mid];
let mut converter = ImplToTrait::new(method.generics, &self.mapping, tenv);
let ptypes = converter.types(method.function.ptypes, &expected.function.ptypes);
let returns = converter.type_(method.function.returns, &expected.function.returns);
let (generics, errors) = converter.finish();
(
ForeignFunction {
generics,
function: Function { ptypes, returns },
},
errors,
)
}
}