charon_lib/transform/
skip_trait_refs_when_known.rsuse crate::{register_error, transform::TransformCtx, ullbc_ast::*};
use super::ctx::UllbcPass;
fn transform_call(ctx: &mut TransformCtx, span: Span, call: &mut Call) {
let FnOperand::Regular(fn_ptr) = &mut call.func else {
return;
};
let FunIdOrTraitMethodRef::Trait(trait_ref, name, _) = &fn_ptr.func else {
return;
};
let TraitRefKind::TraitImpl(impl_id, impl_generics) = &trait_ref.kind else {
return;
};
let Some(trait_impl) = &ctx.translated.trait_impls.get(*impl_id) else {
return;
};
let Some((_, bound_fn)) = trait_impl
.required_methods
.iter()
.chain(trait_impl.provided_methods.iter())
.find(|(n, _)| n == name)
else {
return;
};
let method_generics = &fn_ptr.generics;
if !method_generics.matches(&bound_fn.params) {
register_error!(
ctx,
span,
"Mismatched method generics:\nparams: {:?}\nsupplied: {:?}",
bound_fn.params,
method_generics
);
}
let fn_ref: Binder<Binder<FunDeclRef>> = Binder::new(
BinderKind::Other,
trait_impl.generics.clone(),
bound_fn.clone(),
);
let fn_ref = fn_ref.apply(impl_generics).apply(method_generics);
fn_ptr.generics = fn_ref.generics;
fn_ptr.func = FunIdOrTraitMethodRef::Fun(FunId::Regular(fn_ref.id));
}
pub struct Transform;
impl UllbcPass for Transform {
fn transform_body(&self, ctx: &mut TransformCtx, b: &mut ExprBody) {
for block in b.body.iter_mut() {
for st in block.statements.iter_mut() {
if let RawStatement::Call(call) = &mut st.content {
transform_call(ctx, st.span, call)
};
}
}
}
}