Skip to content

Commit 35ce0a2

Browse files
committed
Added error message for attempting to require implementation parameters on main function, as well as cleaned up some implementation parameter code
1 parent 11f06ec commit 35ce0a2

File tree

10 files changed

+112
-69
lines changed

10 files changed

+112
-69
lines changed

Diff for: src/asg/func.rs

-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::{asg::*, name::ResolvedName, source_files::Source, tag::Tag};
2-
use indexmap::IndexMap;
32
use std::{collections::HashSet, fmt::Display};
43

54
#[derive(Clone, Debug)]
@@ -47,11 +46,6 @@ impl<'a> CurrentConstraints {
4746
}
4847
}
4948

50-
#[derive(Clone, Debug)]
51-
pub struct ImplParams {
52-
pub params: IndexMap<String, GenericTraitRef>,
53-
}
54-
5549
#[derive(Clone, Debug)]
5650
pub struct Func {
5751
pub name: ResolvedName,

Diff for: src/asg/impl_params.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use super::GenericTraitRef;
2+
use crate::index_map_ext::IndexMapExt;
3+
use indexmap::IndexMap;
4+
5+
#[derive(Clone, Debug)]
6+
pub struct ImplParams {
7+
params: IndexMap<String, GenericTraitRef>,
8+
}
9+
10+
impl ImplParams {
11+
pub fn new(params: IndexMap<String, GenericTraitRef>) -> Self {
12+
Self { params }
13+
}
14+
pub fn iter(&self) -> impl Iterator<Item = (&String, &GenericTraitRef)> {
15+
self.params.iter()
16+
}
17+
18+
pub fn get(&self, key: &str) -> Option<&GenericTraitRef> {
19+
self.params.get(key)
20+
}
21+
22+
pub fn has_items(&self) -> bool {
23+
self.params.has_items()
24+
}
25+
}

Diff for: src/asg/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod generic_trait_ref;
88
mod global;
99
mod helper_expr;
1010
mod human_name;
11+
mod impl_params;
1112
mod implementation;
1213
mod overload;
1314
mod stmt;
@@ -29,6 +30,7 @@ pub use generic_trait_ref::*;
2930
pub use global::*;
3031
pub use helper_expr::*;
3132
pub use human_name::*;
33+
pub use impl_params::*;
3234
pub use implementation::*;
3335
pub use overload::*;
3436
use slotmap::{new_key_type, SlotMap};

Diff for: src/index_map_ext.rs

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ pub trait IndexMapExt<K: Equivalent<K> + Hash + Eq, V> {
1212
fn get_or_insert_with(&mut self, key: K, make_val: impl Fn() -> V) -> &mut V;
1313

1414
fn insert_or_panic(&mut self, key: K, value: V);
15+
16+
fn has_items(&self) -> bool;
1517
}
1618

1719
impl<K: Equivalent<K> + Hash + Eq, V> IndexMapExt<K, V> for IndexMap<K, V> {
@@ -38,4 +40,8 @@ impl<K: Equivalent<K> + Hash + Eq, V> IndexMapExt<K, V> for IndexMap<K, V> {
3840
fn insert_or_panic(&mut self, key: K, value: V) {
3941
assert!(self.insert(key, value).is_none());
4042
}
43+
44+
fn has_items(&self) -> bool {
45+
!self.is_empty()
46+
}
4147
}

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub fn infer_callee_missing_impl_args(
1313
catalog: &mut PolyCatalog,
1414
source: Source,
1515
) -> Result<(), ResolveError> {
16-
for (expected_name, expected_trait) in function.impl_params.params.iter() {
16+
for (expected_name, expected_trait) in function.impl_params.iter() {
1717
if used_names.contains(expected_name) {
1818
continue;
1919
}
@@ -27,7 +27,6 @@ pub fn infer_callee_missing_impl_args(
2727

2828
let from_env = caller
2929
.impl_params
30-
.params
3130
.iter()
3231
.filter_map(|(param_name, param_trait)| {
3332
if catalog

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

+2-3
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn resolve_polymorph_impl_arg(
9999
.get(current_func_ref)
100100
.expect("referenced function to exist");
101101

102-
let Some(arg_concrete_trait) = caller.impl_params.params.get(polymorph) else {
102+
let Some(arg_concrete_trait) = caller.impl_params.get(polymorph) else {
103103
return Err(ResolveError::other(
104104
format!("Undefined implementation polymorph '${}'", polymorph),
105105
impl_arg_source,
@@ -135,7 +135,6 @@ fn try_register_specified_impl(
135135
None => Sourced::new(
136136
callee_func
137137
.impl_params
138-
.params
139138
.iter()
140139
.filter(|(param_name, param)| {
141140
param.trait_ref == arg_concrete_trait.trait_ref
@@ -157,7 +156,7 @@ fn try_register_specified_impl(
157156
}
158157
.clone();
159158

160-
let Some(param_generic_trait) = impl_params.params.get(target_param.inner().as_str()) else {
159+
let Some(param_generic_trait) = impl_params.get(target_param.inner().as_str()) else {
161160
return Err(ResolveError::other(
162161
format!(
163162
"No implementation parameter named '${}' exists on callee",

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ pub fn resolve_static_member_call_polymorph(
239239
.get(func_ref)
240240
.expect("referenced function to exist");
241241

242-
let Some(generic_trait_ref) = func.impl_params.params.get(polymorph) else {
242+
let Some(generic_trait_ref) = func.impl_params.get(polymorph) else {
243243
return Err(ResolveError::other(
244244
format!("Undeclared implementation '${}'", polymorph),
245245
*source,

Diff for: src/resolve/func_head.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ pub fn create_func_head<'a>(
104104

105105
let impl_params = create_func_impl_params(&type_ctx, head)?;
106106

107+
let is_main = options.coerce_main_signature && head.name == "main";
108+
109+
if is_main && impl_params.has_items() {
110+
return Err(ResolveError::other(
111+
"Main function cannot have implementation parameters",
112+
head.source,
113+
));
114+
}
115+
107116
Ok(asg.funcs.insert(asg::Func {
108117
name,
109118
params,
@@ -113,9 +122,7 @@ pub fn create_func_head<'a>(
113122
vars: VariableStorage::new(),
114123
source: head.source,
115124
abide_abi: head.abide_abi,
116-
tag: head.tag.or_else(|| {
117-
(options.coerce_main_signature && head.name == "main").then_some(Tag::Main)
118-
}),
125+
tag: head.tag.or_else(|| is_main.then_some(Tag::Main)),
119126
is_generic,
120127
constraints: CurrentConstraints::new(constraints),
121128
impl_params,
@@ -178,5 +185,5 @@ pub fn create_func_impl_params(
178185
}
179186
}
180187

181-
Ok(ImplParams { params })
188+
Ok(ImplParams::new(params))
182189
}

Diff for: src/resolve/impl_head/for_alls.rs

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use crate::{resolve::error::ResolveError, source_files::Source};
2+
use std::collections::{HashMap, HashSet};
3+
4+
#[derive(Debug, Default)]
5+
pub struct ForAlls {
6+
substitution_polys: HashSet<String>,
7+
trait_to_impl: HashMap<String, String>,
8+
impl_to_trait: HashMap<String, String>,
9+
}
10+
11+
impl ForAlls {
12+
pub fn new(substitution_polys: HashSet<String>) -> Self {
13+
Self {
14+
substitution_polys,
15+
trait_to_impl: Default::default(),
16+
impl_to_trait: Default::default(),
17+
}
18+
}
19+
20+
pub fn insert(
21+
&mut self,
22+
in_trait: String,
23+
in_impl: String,
24+
source: Source,
25+
) -> Result<(), ResolveError> {
26+
if self.substitution_polys.contains(&in_impl) {
27+
return Err(ResolveError::other("Inconsistent mapping", source));
28+
}
29+
30+
if let Some(expected) = self.trait_to_impl.get(&in_trait) {
31+
if *expected != in_impl {
32+
return Err(ResolveError::other("Inconsistent mapping", source));
33+
}
34+
}
35+
36+
if let Some(expected) = self.impl_to_trait.get(&in_impl) {
37+
if *expected != in_trait {
38+
return Err(ResolveError::other("Inconsistent mapping", source));
39+
}
40+
}
41+
42+
if self.trait_to_impl.contains_key(&in_trait) && self.impl_to_trait.contains_key(&in_impl) {
43+
// Already exists, and is correct
44+
return Ok(());
45+
}
46+
47+
if !self
48+
.trait_to_impl
49+
.insert(in_trait.clone(), in_impl.clone())
50+
.is_none()
51+
|| !self.impl_to_trait.insert(in_impl, in_trait).is_none()
52+
{
53+
return Err(ResolveError::other("Inconsistent mapping", source));
54+
}
55+
56+
Ok(())
57+
}
58+
}

Diff for: src/resolve/impl_head.rs renamed to src/resolve/impl_head/mod.rs

+6-53
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod for_alls;
12
use super::{
23
collect_constraints::collect_constraints_into, ctx::ResolveCtx, error::ResolveError,
34
func_head::create_func_head, job::FuncJob,
@@ -8,11 +9,11 @@ use crate::{
89
cli::BuildOptions,
910
name::{Name, ResolvedName},
1011
resolve::{error::ResolveErrorKind, type_ctx::ResolveTypeCtx},
11-
source_files::Source,
1212
workspace::fs::FsNodeId,
1313
};
14+
use for_alls::ForAlls;
1415
use indexmap::IndexMap;
15-
use std::collections::{HashMap, HashSet};
16+
use std::collections::HashMap;
1617

1718
pub fn create_impl_heads(
1819
ctx: &mut ResolveCtx,
@@ -83,74 +84,26 @@ pub fn create_impl_heads(
8384
Ok(())
8485
}
8586

86-
#[derive(Debug, Default)]
87-
struct ForAlls {
88-
substitution_polys: HashSet<String>,
89-
trait_to_impl: HashMap<String, String>,
90-
impl_to_trait: HashMap<String, String>,
91-
}
92-
93-
impl ForAlls {
94-
pub fn insert(
95-
&mut self,
96-
in_trait: String,
97-
in_impl: String,
98-
source: Source,
99-
) -> Result<(), ResolveError> {
100-
if self.substitution_polys.contains(&in_impl) {
101-
return Err(ResolveError::other("Inconsistent mapping", source));
102-
}
103-
104-
if let Some(expected) = self.trait_to_impl.get(&in_trait) {
105-
if *expected != in_impl {
106-
return Err(ResolveError::other("Inconsistent mapping", source));
107-
}
108-
}
109-
110-
if let Some(expected) = self.impl_to_trait.get(&in_impl) {
111-
if *expected != in_trait {
112-
return Err(ResolveError::other("Inconsistent mapping", source));
113-
}
114-
}
115-
116-
if self.trait_to_impl.contains_key(&in_trait) && self.impl_to_trait.contains_key(&in_impl) {
117-
// Already exists, and is correct
118-
return Ok(());
119-
}
120-
121-
if !self
122-
.trait_to_impl
123-
.insert(in_trait.clone(), in_impl.clone())
124-
.is_none()
125-
|| !self.impl_to_trait.insert(in_impl, in_trait).is_none()
126-
{
127-
return Err(ResolveError::other("Inconsistent mapping", source));
128-
}
129-
130-
Ok(())
131-
}
132-
}
133-
13487
fn ensure_satisfies_trait_func(
13588
ctx: &ResolveCtx,
13689
asg: &Asg,
13790
expected: HashMap<&str, &Type>,
13891
trait_func: &TraitFunc,
13992
impl_func: &Func,
14093
) -> Result<(), ResolveError> {
141-
if !impl_func.impl_params.params.is_empty() {
94+
if impl_func.impl_params.has_items() {
14295
return Err(ResolveError::other(
14396
"Implementation parameter is not allowed by trait definition",
14497
impl_func.source,
14598
));
14699
}
147100

148-
let mut for_alls = ForAlls::default();
149101
let mut mappings = HashMap::new();
150102
for sub in expected.values() {
151103
collect_constraints_into(&mut mappings, sub);
152104
}
153-
for_alls.substitution_polys = mappings.into_keys().collect();
105+
106+
let mut for_alls = ForAlls::new(mappings.into_keys().collect());
154107

155108
if trait_func.params.is_cstyle_vararg != impl_func.params.is_cstyle_vararg {
156109
return Err(ResolveError::other(

0 commit comments

Comments
 (0)