Skip to content

Commit

Permalink
frontend: Allow extra specialization in argument type check
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Feb 5, 2025
1 parent f21bda1 commit 6287f54
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 19 deletions.
41 changes: 36 additions & 5 deletions dora-frontend/src/specialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ pub fn specialize_ty_for_call(

if type_param_ty.is_type_param() {
SourceType::GenericAssoc {
tp_id,
tp_id: type_param_ty.type_param_id().expect("missing"),
trait_ty,
assoc_id,
}
Expand Down Expand Up @@ -527,10 +527,41 @@ pub fn specialize_for_element(
| SourceType::Float64
| SourceType::Error => ty,

SourceType::Any
| SourceType::Ptr
| SourceType::Assoc(..)
| SourceType::GenericAssoc { .. } => unreachable!(),
SourceType::GenericAssoc {
tp_id,
trait_ty,
assoc_id,
} => {
let assoc = sa.alias(assoc_id);
assert!(assoc.parent.is_trait());
let type_param_ty = type_params_for_element[tp_id.index()].clone();

if type_param_ty.is_type_param() {
SourceType::GenericAssoc {
tp_id: type_param_ty.type_param_id().expect("missing"),
trait_ty,
assoc_id,
}
} else if let Some(impl_match) = find_impl(
sa,
element,
type_param_ty,
element.type_param_definition(),
trait_ty,
) {
let impl_ = sa.impl_(impl_match.id);
let ty = impl_
.trait_alias_map()
.get(&assoc_id)
.map(|a| sa.alias(*a).ty())
.unwrap_or(SourceType::Error);
specialize_for_element(sa, ty, element, type_params_for_element)
} else {
unimplemented!()
}
}

SourceType::Any | SourceType::Ptr | SourceType::Assoc(..) => unreachable!(),
}
}

Expand Down
12 changes: 8 additions & 4 deletions dora-frontend/src/typeck/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ fn check_expr_call_generic_static_method(
arguments,
&trait_ty.type_params,
Some(tp.clone()),
|ty| ty,
);

let call_type = CallType::GenericStaticMethod(
Expand Down Expand Up @@ -202,7 +203,7 @@ fn check_expr_call_expr(

let method = ck.sa.fct(method_id);

check_args_compatible_fct(ck, method, arguments, &impl_match.bindings, None);
check_args_compatible_fct(ck, method, arguments, &impl_match.bindings, None, |ty| ty);

let return_type = specialize_type(ck.sa, method.return_type(), &impl_match.bindings);
ck.analysis.set_ty(e.id, return_type.clone());
Expand Down Expand Up @@ -243,6 +244,7 @@ fn check_expr_call_expr_lambda(
&arguments,
&type_params,
None,
|ty| ty,
);

let call_type = CallType::Lambda(params, return_type.clone());
Expand Down Expand Up @@ -278,7 +280,7 @@ fn check_expr_call_fct(
ck.file_id,
e.span,
) {
check_args_compatible_fct(ck, fct, arguments, &type_params, None);
check_args_compatible_fct(ck, fct, arguments, &type_params, None, |ty| ty);
specialize_type(ck.sa, fct.return_type(), &type_params)
} else {
ty_error()
Expand Down Expand Up @@ -340,7 +342,7 @@ fn check_expr_call_static_method(
ck.file_id,
e.span,
) {
check_args_compatible_fct(ck, fct, arguments, &full_type_params, None);
check_args_compatible_fct(ck, fct, arguments, &full_type_params, None, |ty| ty);
specialize_type(ck.sa, fct.return_type(), &full_type_params)
} else {
ty_error()
Expand Down Expand Up @@ -425,7 +427,7 @@ fn check_expr_call_method(
ck.file_id,
e.span,
) {
check_args_compatible_fct(ck, fct, arguments, &full_type_params, None);
check_args_compatible_fct(ck, fct, arguments, &full_type_params, None, |ty| ty);

let call_data = CallSpecializationData {
object_ty: candidate.object_type.clone(),
Expand Down Expand Up @@ -877,6 +879,7 @@ fn check_expr_call_self(
arguments,
&trait_type_params,
Some(SourceType::This),
|ty| ty,
);

return_type
Expand Down Expand Up @@ -967,6 +970,7 @@ fn check_expr_call_generic_type_param(
arguments,
&trait_type_params,
Some(object_type.clone()),
|ty| specialize_ty_for_generic(ck.sa, ty, id, trait_method.trait_id()),
);

return_type
Expand Down
24 changes: 19 additions & 5 deletions dora-frontend/src/typeck/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,31 +419,38 @@ pub(super) fn add_local(
}
}

pub(super) fn check_args_compatible_fct(
pub(super) fn check_args_compatible_fct<S>(
ck: &TypeCheck,
callee: &FctDefinition,
args: CallArguments,
type_params: &SourceTypeArray,
self_ty: Option<SourceType>,
) {
extra_specialization: S,
) where
S: FnMut(SourceType) -> SourceType,
{
check_args_compatible(
ck,
callee.params.regular_params(),
callee.params.variadic_param(),
&args,
type_params,
self_ty,
extra_specialization,
);
}

pub(super) fn check_args_compatible(
pub(super) fn check_args_compatible<S>(
ck: &TypeCheck,
regular_params: &[Param],
variadic_param: Option<&Param>,
args: &CallArguments,
type_params: &SourceTypeArray,
self_ty: Option<SourceType>,
) {
mut extra_specialization: S,
) where
S: FnMut(SourceType) -> SourceType,
{
for arg in &args.arguments {
if let Some(ref name) = arg.name {
ck.sa
Expand All @@ -458,6 +465,7 @@ pub(super) fn check_args_compatible(
Some(&type_params),
self_ty.clone(),
);
let param_ty = extra_specialization(param_ty);
let arg_ty = ck.analysis.ty(arg.id);

if !arg_allows(ck.sa, param_ty.clone(), arg_ty.clone(), self_ty.clone())
Expand Down Expand Up @@ -522,6 +530,10 @@ pub(super) fn arg_allows(
arg: SourceType,
self_ty: Option<SourceType>,
) -> bool {
if arg.is_error() {
return true;
}

match def {
SourceType::Error => true,
SourceType::Any => unreachable!(),
Expand Down Expand Up @@ -607,7 +619,9 @@ pub(super) fn arg_allows(
arg_allows(sa, alias.ty(), arg, self_ty.clone())
}

SourceType::Assoc(..) | SourceType::GenericAssoc { .. } => unimplemented!(),
SourceType::GenericAssoc { .. } => def == arg,

SourceType::Assoc(..) => unimplemented!(),
}
}

Expand Down
1 change: 0 additions & 1 deletion dora-sema-fuzzer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ fn check_program(program: String) {
program_file: Some(FileContent::Content(program)),
packages: Vec::new(),
boots: false,
new_default_impl: true,
};

let mut sa = Sema::new(sem_args);
Expand Down
10 changes: 6 additions & 4 deletions tests/trait/trait-default-wip.dora
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Map[I: MyIterator, R] {
fct: (I::Item): R,
}

impl[I: MyIterator] MyIterator for Map[I, R] {
impl[I: MyIterator, R] MyIterator for Map[I, R] {
type Item = R;

fn next(): Option[R] {
Expand Down Expand Up @@ -81,9 +81,11 @@ fn main() {
assert(Range(2).count() == 2);
assert(Range(7).count() == 7);

let r = Range(2).enumerate();
let r = Range(2).enumerate().map[Int](|x: (Int, Int)|: (Int, Int) {
(x.0, x.1 * 2)
});

assert(Some[(Int, Int)]((0, 2)) == r.next());
assert(Some[(Int, Int)]((1, 1)) == r.next());
assert(Some[(Int, Int)]((0, 4)) == r.next());
assert(Some[(Int, Int)]((1, 2)) == r.next());
assert(r.next().isNone());
}

0 comments on commit 6287f54

Please sign in to comment.