Skip to content

Commit 32c9141

Browse files
committed
Added support for specifying generics at call sites, and fixed a few trait implementation inference bugs
1 parent af9ddf6 commit 32c9141

File tree

18 files changed

+177
-63
lines changed

18 files changed

+177
-63
lines changed

Diff for: src/asg/func.rs

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ impl<'a> CurrentConstraints {
4949
#[derive(Clone, Debug)]
5050
pub struct Func {
5151
pub name: ResolvedName,
52+
pub named_type_args: Vec<String>,
5253
pub params: Params,
5354
pub return_type: Type,
5455
pub stmts: Vec<Stmt>,

Diff for: src/asg/impl_params.rs

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ impl ImplParams {
1919
self.params.get(key)
2020
}
2121

22+
pub fn is_empty(&self) -> bool {
23+
self.params.is_empty()
24+
}
25+
2226
pub fn has_items(&self) -> bool {
2327
self.params.has_items()
2428
}

Diff for: src/ast/func/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub struct Func {
1313
#[derive(Clone, Debug)]
1414
pub struct FuncHead {
1515
pub name: String,
16+
pub named_type_params: Vec<String>,
1617
pub givens: Vec<Given>,
1718
pub params: Params,
1819
pub return_type: Type,
@@ -31,5 +32,7 @@ impl FuncHead {
3132
.required
3233
.iter()
3334
.any(|param| param.ast_type.contains_polymorph().is_some())
35+
|| !self.named_type_params.is_empty()
36+
|| !self.givens.is_empty()
3437
}
3538
}

Diff for: src/c/translation/function.rs

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pub fn declare_function(
7373

7474
let head = FuncHead {
7575
name,
76+
named_type_params: vec![],
7677
givens: vec![],
7778
params: parameters,
7879
return_type,

Diff for: src/interpreter_env/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ fn thin_void_func(name: impl Into<String>, syscall_kind: InterpreterSyscallKind)
2323

2424
let head = FuncHead {
2525
name: name.into(),
26+
named_type_params: vec![],
2627
givens: vec![],
2728
params: Params::default(),
2829
return_type: void.clone(),
@@ -59,6 +60,7 @@ fn thin_cstring_func(
5960

6061
let head = FuncHead {
6162
name: name.into(),
63+
named_type_params: vec![],
6264
givens: vec![],
6365
params: Params::normal([Param::new(param_name.clone(), ptr_char.clone())]),
6466
return_type: void.clone(),
@@ -104,6 +106,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
104106
file.funcs.push(Func {
105107
head: FuncHead {
106108
name: "<interpreter entry point>".into(),
109+
named_type_params: vec![],
107110
givens: vec![],
108111
params: Params::default(),
109112
return_type: void.clone(),
@@ -215,6 +218,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
215218
file.funcs.push(Func {
216219
head: FuncHead {
217220
name: "project".into(),
221+
named_type_params: vec![],
218222
givens: vec![],
219223
params: Params::normal([
220224
Param::new("name".into(), ptr_char.clone()),
@@ -258,6 +262,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
258262
file.funcs.push(Func {
259263
head: FuncHead {
260264
name: "use".into(),
265+
named_type_params: vec![],
261266
givens: vec![],
262267
params: Params::normal([
263268
Param::new("as_namespace".into(), ptr_char.clone()),
@@ -301,6 +306,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
301306
file.funcs.push(Func {
302307
head: FuncHead {
303308
name: "import".into(),
309+
named_type_params: vec![],
304310
givens: vec![],
305311
params: Params::normal([Param::new("namespace".into(), ptr_char.clone())]),
306312
return_type: TypeKind::Named(Name::plain("Dependency"), vec![]).at(source),

Diff for: src/lower/mod.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,26 @@ use function::{lower_func_body, lower_func_head};
1919
use global::lower_global;
2020
use structure::lower_struct;
2121

22-
pub fn lower<'a>(options: &BuildOptions, rast: &Asg) -> Result<ir::Module, LowerError> {
22+
pub fn lower<'a>(options: &BuildOptions, asg: &Asg) -> Result<ir::Module, LowerError> {
2323
let mut ir_module = ir::Module::new(options.target.clone());
2424

25-
for (struct_ref, structure) in rast.structs.iter() {
26-
lower_struct(&mut ir_module, struct_ref, structure, rast)?;
25+
for (struct_ref, structure) in asg.structs.iter() {
26+
lower_struct(&mut ir_module, struct_ref, structure, asg)?;
2727
}
2828

29-
for (global_ref, global) in rast.globals.iter() {
30-
lower_global(&mut ir_module, global_ref, global, rast)?;
29+
for (global_ref, global) in asg.globals.iter() {
30+
lower_global(&mut ir_module, global_ref, global, asg)?;
3131
}
3232

33-
for (func_ref, function) in rast.funcs.iter() {
33+
for (func_ref, function) in asg.funcs.iter() {
3434
if function.is_generic {
3535
continue;
3636
}
3737

3838
ir_module
3939
.funcs
4040
.translate(func_ref, PolyRecipe::default(), || {
41-
lower_func_head(&ir_module, func_ref, &PolyRecipe::default(), rast)
41+
lower_func_head(&ir_module, func_ref, &PolyRecipe::default(), asg)
4242
})?;
4343
}
4444

@@ -47,7 +47,7 @@ pub fn lower<'a>(options: &BuildOptions, rast: &Asg) -> Result<ir::Module, Lower
4747
for (func_ref, poly_recipe, ir_func_ref) in ir_module.funcs.monomorphized() {
4848
bodies.push((
4949
*ir_func_ref,
50-
lower_func_body(&ir_module, *func_ref, &poly_recipe, rast)?,
50+
lower_func_body(&ir_module, *func_ref, &poly_recipe, asg)?,
5151
));
5252
}
5353

Diff for: src/parser/parse_func.rs

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88
inflow::Inflow,
99
token::{Token, TokenKind},
1010
};
11+
use itertools::Itertools;
1112

1213
impl<'a, I: Inflow<Token>> Parser<'a, I> {
1314
pub fn parse_func(&mut self, annotations: Vec<Annotation>) -> Result<Func, ParseError> {
@@ -49,6 +50,9 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
4950
let name = self.parse_identifier(Some("after 'func' keyword"))?;
5051
self.ignore_newlines();
5152

53+
let named_type_params = self.parse_type_params()?.into_keys().collect_vec();
54+
self.ignore_newlines();
55+
5256
let params = self
5357
.input
5458
.peek_is(TokenKind::OpenParen)
@@ -72,6 +76,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
7276
Ok(Func {
7377
head: FuncHead {
7478
name,
79+
named_type_params,
7580
givens,
7681
params,
7782
return_type,

Diff for: src/pragma_section/parse.rs

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ impl PragmaSection {
103103
ast_file.funcs.push(Func {
104104
head: FuncHead {
105105
name: "main".into(),
106+
named_type_params: vec![],
106107
givens: vec![],
107108
params: Params::default(),
108109
return_type: TypeKind::Void.at(source),

Diff for: src/resolve/expr/call/infer_impl.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::{
22
asg,
3-
resolve::{error::ResolveError, expr::ResolveExprCtx, PolyCatalog, PolyValue},
3+
resolve::{
4+
error::ResolveError, expr::ResolveExprCtx, PolyCatalog, PolyRecipeResolver, PolyValue,
5+
},
46
source_files::Source,
57
};
68
use itertools::Itertools;
@@ -29,24 +31,23 @@ pub fn infer_callee_missing_impl_args(
2931
.impl_params
3032
.iter()
3133
.filter_map(|(param_name, param_trait)| {
32-
if catalog
33-
.extend_if_match_all_types(ctx, &expected_trait.args, &param_trait.args)
34-
.is_err()
35-
{
36-
return None;
37-
}
34+
let matched = catalog
35+
.try_match_all_types(ctx, &expected_trait.args, &param_trait.args)
36+
.ok()?;
3837

39-
catalog
40-
.resolver()
38+
PolyRecipeResolver::new_disjoint(&matched.partial, &catalog.resolver())
4139
.resolve_trait(expected_trait)
4240
.ok()
4341
.and_then(|expected_trait| {
44-
(param_trait.trait_ref == expected_trait.trait_ref).then_some(param_name)
42+
(param_trait.trait_ref == expected_trait.trait_ref)
43+
.then_some((param_name, matched))
4544
})
4645
});
4746

4847
match from_env.exactly_one() {
49-
Ok(param_name) => {
48+
Ok((param_name, matched)) => {
49+
catalog.polymorphs.extend(matched.partial);
50+
5051
if catalog
5152
.polymorphs
5253
.insert(expected_name.into(), PolyValue::PolyImpl(param_name.into()))

Diff for: src/resolve/expr/call/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
resolve::{
1010
conform::{conform_expr, to_default::conform_expr_to_default, ConformMode, Perform},
1111
error::{ResolveError, ResolveErrorKind},
12-
Initialized, PolyCatalog,
12+
resolve_type_args_to_poly_args, Initialized, PolyCatalog,
1313
},
1414
source_files::Source,
1515
};
@@ -35,14 +35,16 @@ pub fn resolve_call_expr(
3535
)?);
3636
}
3737

38+
let generics = resolve_type_args_to_poly_args(ctx, &call.generics)?;
39+
3840
let args = match cast(ctx, call, args, source)? {
3941
Ok(cast) => return Ok(cast),
4042
Err(args) => args,
4143
};
4244

4345
let callee = ctx
4446
.func_haystack
45-
.find(ctx, &call.name, call.generics.as_slice(), &args[..], source)
47+
.find(ctx, &call.name, &generics, &args[..], source)
4648
.map_err(|reason| {
4749
ResolveErrorKind::FailedToFindFunction {
4850
signature: format!(

Diff for: src/resolve/expr/mod.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,17 @@ use ordered_float::NotNan;
5151
use static_member::{resolve_static_member_call, resolve_static_member_value};
5252
use std::collections::HashMap;
5353

54-
pub struct ResolveExprCtx<'a, 'b> {
55-
pub asg: &'b mut Asg<'a>,
56-
pub func_haystack: &'b FuncHaystack,
54+
pub struct ResolveExprCtx<'ast, 'root_ctx> {
55+
pub asg: &'root_ctx mut Asg<'ast>,
56+
pub func_haystack: &'root_ctx FuncHaystack,
5757
pub variable_haystack: VariableHaystack,
5858
pub func_ref: Option<asg::FuncRef>,
59-
pub settings: &'b Settings,
60-
pub public_funcs: &'b HashMap<FsNodeId, HashMap<String, Vec<asg::FuncRef>>>,
61-
pub types_in_modules: &'b HashMap<FsNodeId, HashMap<String, asg::TypeDecl>>,
62-
pub globals_in_modules: &'b HashMap<FsNodeId, HashMap<String, asg::GlobalVarDecl>>,
63-
pub helper_exprs_in_modules: &'b HashMap<FsNodeId, HashMap<String, asg::HelperExprDecl>>,
64-
pub impls_in_modules: &'b HashMap<FsNodeId, HashMap<String, asg::ImplRef>>,
59+
pub settings: &'root_ctx Settings,
60+
pub public_funcs: &'root_ctx HashMap<FsNodeId, HashMap<String, Vec<asg::FuncRef>>>,
61+
pub types_in_modules: &'root_ctx HashMap<FsNodeId, HashMap<String, asg::TypeDecl>>,
62+
pub globals_in_modules: &'root_ctx HashMap<FsNodeId, HashMap<String, asg::GlobalVarDecl>>,
63+
pub helper_exprs_in_modules: &'root_ctx HashMap<FsNodeId, HashMap<String, asg::HelperExprDecl>>,
64+
pub impls_in_modules: &'root_ctx HashMap<FsNodeId, HashMap<String, asg::ImplRef>>,
6565
pub module_fs_node_id: FsNodeId,
6666
pub physical_fs_node_id: FsNodeId,
6767
pub current_constraints: CurrentConstraints,

Diff for: src/resolve/expr/static_member.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
expr::PreferredType,
1212
func_haystack::{FindFunctionError, FuncHaystack},
1313
initialized::Initialized,
14-
PolyCatalog, PolyRecipe,
14+
resolve_type_args_to_poly_args, PolyCatalog, PolyRecipe,
1515
},
1616
source_files::Source,
1717
};
@@ -171,6 +171,9 @@ pub fn resolve_static_member_call_named(
171171
*call_source,
172172
));
173173
};
174+
175+
let generics = resolve_type_args_to_poly_args(ctx, &static_member_call.call.generics)?;
176+
174177
let imp = ctx
175178
.asg
176179
.impls
@@ -186,7 +189,7 @@ pub fn resolve_static_member_call_named(
186189
FuncHaystack::fits(
187190
ctx,
188191
func_ref,
189-
static_member_call.call.generics.as_slice(),
192+
&generics,
190193
&args,
191194
Some(catalog.clone()),
192195
*call_source,

Diff for: src/resolve/func_haystack.rs

+23-9
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ use super::{
88
};
99
use crate::{
1010
asg::{self, Callee, TypeKind, TypedExpr},
11-
ast::TypeArg,
1211
name::{Name, ResolvedName},
13-
resolve::conform::Perform,
12+
resolve::{conform::Perform, PolyValue},
1413
source_files::Source,
1514
workspace::fs::FsNodeId,
1615
};
@@ -43,7 +42,7 @@ impl FuncHaystack {
4342
&self,
4443
ctx: &ResolveExprCtx,
4544
name: &Name,
46-
generics: &[TypeArg],
45+
generics: &[PolyValue],
4746
arguments: &[TypedExpr],
4847
source: Source,
4948
) -> Result<Callee, FindFunctionError> {
@@ -97,7 +96,7 @@ impl FuncHaystack {
9796
pub fn fits(
9897
ctx: &ResolveExprCtx,
9998
func_ref: asg::FuncRef,
100-
generics: &[TypeArg],
99+
generics: &[PolyValue],
101100
args: &[TypedExpr],
102101
existing_catalog: Option<PolyCatalog>,
103102
source: Source,
@@ -107,8 +106,23 @@ impl FuncHaystack {
107106

108107
let mut catalog = existing_catalog.unwrap_or_default();
109108

110-
if generics.len() != 0 {
111-
todo!("FuncHaystack::fits does not support specified generics yet");
109+
if generics.len() > function.named_type_args.len() {
110+
return None;
111+
}
112+
113+
for (name, poly_value) in function
114+
.named_type_args
115+
.iter()
116+
.take(generics.len())
117+
.zip(generics.iter())
118+
{
119+
if catalog
120+
.polymorphs
121+
.insert(name.clone(), poly_value.clone())
122+
.is_some()
123+
{
124+
return None;
125+
}
112126
}
113127

114128
if !params.is_cstyle_vararg && args.len() != params.required.len() {
@@ -174,7 +188,7 @@ impl FuncHaystack {
174188
&self,
175189
ctx: &ResolveExprCtx,
176190
resolved_name: &ResolvedName,
177-
generics: &[TypeArg],
191+
generics: &[PolyValue],
178192
arguments: &[TypedExpr],
179193
source: Source,
180194
) -> Option<Result<Callee, FindFunctionError>> {
@@ -198,7 +212,7 @@ impl FuncHaystack {
198212
&self,
199213
ctx: &ResolveExprCtx,
200214
name: &Name,
201-
generics: &[TypeArg],
215+
generics: &[PolyValue],
202216
arguments: &[TypedExpr],
203217
source: Source,
204218
) -> Option<Result<Callee, FindFunctionError>> {
@@ -235,7 +249,7 @@ impl FuncHaystack {
235249
&self,
236250
ctx: &ResolveExprCtx,
237251
name: &Name,
238-
generics: &[TypeArg],
252+
generics: &[PolyValue],
239253
arguments: &[TypedExpr],
240254
source: Source,
241255
) -> Option<Result<Callee, FindFunctionError>> {

Diff for: src/resolve/func_head.rs

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ pub fn create_func_head<'a>(
115115

116116
Ok(asg.funcs.insert(asg::Func {
117117
name,
118+
named_type_args: head.named_type_params.clone(),
118119
params,
119120
return_type,
120121
stmts: vec![],

0 commit comments

Comments
 (0)