Skip to content

Commit

Permalink
frontend: Add specialize_type_for_call method
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Jan 31, 2025
1 parent 2f301db commit 0516ca5
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 18 deletions.
5 changes: 3 additions & 2 deletions dora-frontend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ pub use parsety::{ParsedTraitType, ParsedType, ParsedTypeAst};
pub use path::{parse_path, PathKind};
pub use program_emitter::emit_program;
pub use specialize::{
replace_type, specialize_for_element, specialize_trait_type, specialize_ty_for_generic,
specialize_ty_for_trait_object, specialize_type, specialize_type_array,
replace_type, specialize_for_element, specialize_trait_type, specialize_ty_for_call,
specialize_ty_for_generic, specialize_ty_for_trait_object, specialize_type,
specialize_type_array, CallSpecializationData,
};

pub(crate) mod access;
Expand Down
2 changes: 1 addition & 1 deletion dora-frontend/src/parsety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ fn expand_st(
let impl_alias_id = impl_.trait_alias_map().get(&id).cloned();
if let Some(impl_alias_id) = impl_alias_id {
let impl_alias = sa.alias(impl_alias_id);
impl_alias.ty()
expand_st(sa, element, impl_alias.ty(), replace_self)
} else {
SourceType::Error
}
Expand Down
95 changes: 95 additions & 0 deletions dora-frontend/src/specialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,101 @@ fn replace_sta(
SourceTypeArray::with(new_array)
}

pub struct CallSpecializationData {
pub object_ty: SourceType,
pub type_params: SourceTypeArray,
}

pub fn specialize_ty_for_call(
sa: &Sema,
ty: SourceType,
call_data: &CallSpecializationData,
) -> SourceType {
match ty {
SourceType::Class(cls_id, cls_type_params) => SourceType::Class(
cls_id,
specialize_ty_for_call_array(sa, cls_type_params, call_data),
),

SourceType::TraitObject(trait_id, trait_type_params, bindings) => SourceType::TraitObject(
trait_id,
specialize_ty_for_call_array(sa, trait_type_params, call_data),
specialize_ty_for_call_array(sa, bindings, call_data),
),

SourceType::Struct(struct_id, struct_type_params) => SourceType::Struct(
struct_id,
specialize_ty_for_call_array(sa, struct_type_params, call_data),
),

SourceType::Enum(enum_id, enum_type_params) => SourceType::Enum(
enum_id,
specialize_ty_for_call_array(sa, enum_type_params, call_data),
),

SourceType::Alias(alias_id, alias_type_params) => SourceType::Alias(
alias_id,
specialize_ty_for_call_array(sa, alias_type_params, call_data),
),

SourceType::Assoc(alias_id, alias_type_params) => {
let alias = sa.alias(alias_id);
assert!(alias_type_params.is_empty());

match &call_data.object_ty {
SourceType::TraitObject(_trait_id, _type_params, assoc_types) => {
assoc_types[alias.idx_in_trait()].clone()
}

// Associated types should only be used in traits.
_ => unreachable!(),
}
}

SourceType::GenericAssoc { assoc_id, .. } => {
let _assoc = sa.alias(assoc_id);
unimplemented!()
}

SourceType::Lambda(params, return_type) => SourceType::Lambda(
specialize_ty_for_call_array(sa, params, call_data),
Box::new(specialize_ty_for_call(sa, *return_type, call_data)),
),

SourceType::Tuple(subtypes) => {
SourceType::Tuple(specialize_ty_for_call_array(sa, subtypes, call_data))
}

SourceType::TypeParam(id) => call_data.type_params[id.index()].clone(),

SourceType::Unit
| SourceType::UInt8
| SourceType::Bool
| SourceType::Char
| SourceType::Int32
| SourceType::Int64
| SourceType::Float32
| SourceType::Float64
| SourceType::Error => ty,

SourceType::This | SourceType::Any | SourceType::Ptr => {
unreachable!()
}
}
}

fn specialize_ty_for_call_array(
sa: &Sema,
array: SourceTypeArray,
call_data: &CallSpecializationData,
) -> SourceTypeArray {
let new_array = array
.iter()
.map(|ty| specialize_ty_for_call(sa, ty, call_data))
.collect::<Vec<_>>();
SourceTypeArray::with(new_array)
}

pub fn specialize_ty_for_trait_object(
sa: &Sema,
ty: SourceType,
Expand Down
25 changes: 10 additions & 15 deletions dora-frontend/src/typeck/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ use crate::typeck::{
check_args_compatible, check_args_compatible_fct, check_expr, find_method_call_candidates,
read_path_expr, CallArguments, TypeCheck,
};
use crate::typeparamck;
use crate::{
empty_sta, specialize_ty_for_generic, specialize_ty_for_trait_object, specialize_type,
ty::error as ty_error, ErrorMessage, SourceType, SourceTypeArray, TraitType,
empty_sta, specialize_ty_for_generic, specialize_type, ty::error as ty_error,
CallSpecializationData, ErrorMessage, SourceType, SourceTypeArray, TraitType,
};
use crate::{specialize_ty_for_call, typeparamck};

pub(super) fn check_expr_call(
ck: &mut TypeCheck,
Expand Down Expand Up @@ -426,18 +426,13 @@ fn check_expr_call_method(
e.span,
) {
check_args_compatible_fct(ck, fct, arguments, &full_type_params, None);
match &object_type {
SourceType::TraitObject(trait_id, type_params, assoc_types) => {
specialize_ty_for_trait_object(
ck.sa,
fct.return_type(),
*trait_id,
&type_params,
&assoc_types,
)
}
_ => specialize_type(ck.sa, fct.return_type(), &full_type_params),
}

let call_data = CallSpecializationData {
object_ty: candidate.object_type.clone(),
type_params: full_type_params.clone(),
};

specialize_ty_for_call(ck.sa, fct.return_type(), &call_data)
} else {
ty_error()
};
Expand Down

0 comments on commit 0516ca5

Please sign in to comment.