Skip to content

Commit 5a902fe

Browse files
committed
Started working on support for polymorphic type aliases
1 parent 4e717f8 commit 5a902fe

File tree

15 files changed

+157
-60
lines changed

15 files changed

+157
-60
lines changed

Diff for: src/asg/datatype/kind/mod.rs

+38-10
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub enum TypeKind {
3939
FuncPtr(FuncPtr),
4040
Enum(HumanName, EnumRef),
4141
Structure(HumanName, StructRef, Vec<Type>),
42-
TypeAlias(HumanName, TypeAliasRef),
42+
TypeAlias(HumanName, TypeAliasRef, Vec<Type>),
4343
Polymorph(String, Vec<Constraint>),
4444
Trait(HumanName, TraitRef, Vec<Type>),
4545
}
@@ -68,10 +68,11 @@ impl TypeKind {
6868
TypeKind::FixedArray(fixed_array) => fixed_array.inner.kind.contains_polymorph(),
6969
TypeKind::FuncPtr(_) => todo!(),
7070
TypeKind::Enum(_, _) => false,
71-
TypeKind::Structure(_, _, parameters) | TypeKind::Trait(_, _, parameters) => parameters
71+
TypeKind::Structure(_, _, parameters)
72+
| TypeKind::Trait(_, _, parameters)
73+
| TypeKind::TypeAlias(_, _, parameters) => parameters
7274
.iter()
7375
.any(|parameter| parameter.kind.contains_polymorph()),
74-
TypeKind::TypeAlias(_, _) => false,
7576
TypeKind::Polymorph(_, _) => true,
7677
}
7778
}
@@ -88,7 +89,7 @@ impl TypeKind {
8889
TypeKind::CInteger(integer, sign) => {
8990
sign.or_else(|| target.map(|target| target.default_c_integer_sign(*integer)))
9091
}
91-
TypeKind::TypeAlias(_, _type_ref) => todo!(),
92+
TypeKind::TypeAlias(_, _, _) => panic!("sign of type alias"),
9293
TypeKind::Unresolved => panic!(),
9394
TypeKind::AnonymousEnum(enumeration) => enumeration.backing_type.kind.sign(target),
9495
TypeKind::Floating(_)
@@ -113,6 +114,9 @@ impl TypeKind {
113114
asg.structs.get(*struct_ref).unwrap().params.len()
114115
}
115116
TypeKind::Trait(_, trait_ref, _) => asg.traits.get(*trait_ref).unwrap().params.len(),
117+
TypeKind::TypeAlias(_, type_alias_ref, _) => {
118+
asg.type_aliases.get(*type_alias_ref).unwrap().params.len()
119+
}
116120
_ => 0,
117121
}
118122
}
@@ -140,12 +144,11 @@ impl TypeKind {
140144
func.return_type.kind.for_each_polymorph(f);
141145
}
142146
TypeKind::Enum(_, _) => (),
143-
TypeKind::Structure(_, _, params) => {
147+
TypeKind::Structure(_, _, params) | TypeKind::TypeAlias(_, _, params) => {
144148
for param in params.iter() {
145149
param.kind.for_each_polymorph(f);
146150
}
147151
}
148-
TypeKind::TypeAlias(_, _) => (),
149152
TypeKind::Polymorph(name, _) => f(name),
150153
TypeKind::Trait(_, _, params) => {
151154
for param in params.iter() {
@@ -232,7 +235,29 @@ impl TypeKind {
232235
mapped,
233236
)))
234237
}
235-
TypeKind::TypeAlias(_, _) => Ok(Cow::Borrowed(self)),
238+
TypeKind::TypeAlias(human_name, type_alias_ref, type_args) => {
239+
if type_args.is_empty() {
240+
return Ok(Cow::Borrowed(self));
241+
}
242+
243+
let mut mapped = vec![];
244+
245+
for (i, type_arg) in type_args.iter().enumerate() {
246+
let TypeParam::Type(inner) = mapper(TypeParam::Type(Cow::Borrowed(type_arg)))
247+
.map_err(TypeParamError::MappingError)?
248+
else {
249+
return Err(TypeParamError::ExpectedType { index: i });
250+
};
251+
252+
mapped.push(inner.into_owned());
253+
}
254+
255+
Ok(Cow::Owned(Self::TypeAlias(
256+
human_name.clone(),
257+
*type_alias_ref,
258+
mapped,
259+
)))
260+
}
236261
TypeKind::Polymorph(_, _) => Ok(Cow::Borrowed(self)),
237262
TypeKind::Trait(human_name, trait_ref, type_args) => {
238263
if type_args.is_empty() {
@@ -279,7 +304,10 @@ impl Display for TypeKind {
279304
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
280305
match self {
281306
TypeKind::Unresolved => panic!("cannot display unresolved type"),
282-
TypeKind::TypeAlias(name, _) => write!(f, "{}", name)?,
307+
TypeKind::TypeAlias(name, _, type_args) => {
308+
write!(f, "{}", name)?;
309+
write_parameters(f, type_args)?;
310+
}
283311
TypeKind::Boolean => write!(f, "bool")?,
284312
TypeKind::Integer(bits, sign) => {
285313
f.write_str(match (bits, sign) {
@@ -315,9 +343,9 @@ impl Display for TypeKind {
315343
}
316344
TypeKind::Void => f.write_str("void")?,
317345
TypeKind::Never => f.write_str("never")?,
318-
TypeKind::Structure(name, _, parameters) => {
346+
TypeKind::Structure(name, _, type_args) => {
319347
write!(f, "{}", name)?;
320-
write_parameters(f, parameters)?;
348+
write_parameters(f, type_args)?;
321349
}
322350
TypeKind::AnonymousStruct() => f.write_str("anonymous-struct")?,
323351
TypeKind::AnonymousUnion() => f.write_str("anonymous-union")?,

Diff for: src/asg/datatype/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,11 @@ impl Type {
5252
func.return_type.strip_constraints();
5353
}
5454
TypeKind::Enum(_, _) => (),
55-
TypeKind::Structure(_, _, parameters) => {
56-
for parameter in parameters {
55+
TypeKind::Structure(_, _, params) | TypeKind::TypeAlias(_, _, params) => {
56+
for parameter in params {
5757
parameter.strip_constraints();
5858
}
5959
}
60-
TypeKind::TypeAlias(_, _) => (),
6160
TypeKind::Polymorph(_, constraints) => {
6261
constraints.drain(..);
6362
}

Diff for: src/asg/mod.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod overload;
1414
mod stmt;
1515
mod structure;
1616
mod trait_constraint;
17+
mod type_alias;
1718
mod type_decl;
1819
mod variable_storage;
1920

@@ -38,6 +39,7 @@ use std::collections::{HashMap, HashSet};
3839
pub use stmt::*;
3940
pub use structure::*;
4041
pub use trait_constraint::*;
42+
pub use type_alias::TypeAlias;
4143
pub use type_decl::*;
4244
pub use variable_storage::*;
4345

@@ -59,7 +61,7 @@ pub struct Asg<'a> {
5961
pub structs: SlotMap<StructRef, Struct>,
6062
pub globals: SlotMap<GlobalVarRef, GlobalVar>,
6163
pub enums: SlotMap<EnumRef, Enum>,
62-
pub type_aliases: SlotMap<TypeAliasRef, Type>,
64+
pub type_aliases: SlotMap<TypeAliasRef, TypeAlias>,
6365
pub traits: SlotMap<TraitRef, Trait>,
6466
pub impls: SlotMap<ImplRef, Impl>,
6567
pub workspace: &'a AstWorkspace<'a>,
@@ -87,12 +89,17 @@ impl<'a> Asg<'a> {
8789
let mut running = whole_type;
8890
let mut depth = 0;
8991

90-
while let TypeKind::TypeAlias(_, type_alias_ref) = running.kind {
91-
running = self
92+
while let TypeKind::TypeAlias(_, type_alias_ref, type_args) = &running.kind {
93+
let alias = self
9294
.type_aliases
93-
.get(type_alias_ref)
95+
.get(*type_alias_ref)
9496
.expect("valid type alias ref");
9597

98+
if !type_args.is_empty() || !alias.params.is_empty() {
99+
todo!("unalias type alias with type args");
100+
}
101+
102+
running = &alias.becomes;
96103
depth += 1;
97104

98105
if depth > Self::MAX_UNALIAS_DEPTH {
@@ -108,12 +115,18 @@ impl<'a> Asg<'a> {
108115
let mut running = whole_type;
109116
let mut depth = 0;
110117

111-
while let TypeKind::TypeAlias(human_name, type_alias_ref) = &running.kind {
112-
running = self
118+
while let TypeKind::TypeAlias(human_name, type_alias_ref, type_args) = &running.kind {
119+
let alias = self
113120
.type_aliases
114121
.get(*type_alias_ref)
115122
.expect("valid type alias ref");
116123

124+
if !type_args.is_empty() || !alias.params.is_empty() {
125+
todo!("unalias type alias with type args");
126+
}
127+
128+
running = &alias.becomes;
129+
117130
if !seen.insert(type_alias_ref) {
118131
return UnaliasError::SelfReferentialTypeAlias(human_name.0.clone());
119132
}

Diff for: src/asg/type_alias.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use super::{HumanName, Type};
2+
use crate::source_files::Source;
3+
use indexmap::IndexSet;
4+
5+
#[derive(Clone, Debug)]
6+
pub struct TypeAlias {
7+
pub human_name: HumanName,
8+
pub source: Source,
9+
pub params: IndexSet<String>,
10+
pub becomes: Type,
11+
}

Diff for: src/ast/type_alias.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use super::{Privacy, Type};
22
use crate::source_files::Source;
3+
use indexmap::IndexSet;
34

45
#[derive(Clone, Debug)]
56
pub struct TypeAlias {
67
pub name: String,
8+
pub params: IndexSet<String>,
79
pub value: Type,
810
pub source: Source,
911
pub privacy: Privacy,

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

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::{
1111
c::parser::{CTypedef, DeclarationSpecifiers, Declarator, ParseError},
1212
diagnostics::Diagnostics,
1313
};
14+
use indexmap::IndexSet;
1415
use std::collections::HashMap;
1516

1617
pub fn declare_named_declaration(
@@ -33,6 +34,7 @@ pub fn declare_named_declaration(
3334
if is_typedef {
3435
ast_file.type_aliases.push(ast::TypeAlias {
3536
name: name.clone(),
37+
params: IndexSet::new(),
3638
value: ast_type.clone(),
3739
source: declarator.source,
3840
privacy: Privacy::Public,

Diff for: src/lower/datatype.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,21 @@ pub fn lower_type(
122122
asg,
123123
)
124124
}
125-
asg::TypeKind::TypeAlias(_, type_alias_ref) => {
126-
let ty = asg
125+
asg::TypeKind::TypeAlias(_, type_alias_ref, type_args) => {
126+
if !type_args.is_empty() {
127+
todo!("lower_type for type alias with type args");
128+
}
129+
130+
let type_alias = asg
127131
.type_aliases
128132
.get(*type_alias_ref)
129133
.expect("referenced type alias to exist");
130134

131-
lower_type(ir_module, &ConcreteType(Cow::Borrowed(ty)), asg)
135+
lower_type(
136+
ir_module,
137+
&ConcreteType(Cow::Borrowed(&type_alias.becomes)),
138+
asg,
139+
)
132140
}
133141
}
134142
}

Diff for: src/parser/parse_type_alias.rs

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
1818
let name = self.parse_identifier(Some("for alias name after 'typealias' keyword"))?;
1919
self.ignore_newlines();
2020

21+
let params = self.parse_type_params()?.into_keys().collect();
22+
2123
for annotation in annotations {
2224
match annotation.kind {
2325
AnnotationKind::Public => privacy = Privacy::Public,
@@ -31,6 +33,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
3133

3234
Ok(TypeAlias {
3335
name,
36+
params,
3437
value: becomes_type,
3538
source,
3639
privacy,

Diff for: src/resolve/collect_constraints.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,11 @@ pub fn collect_constraints_into(map: &mut HashMap<String, HashSet<Constraint>>,
3333
asg::TypeKind::FixedArray(fixed_array) => collect_constraints_into(map, &fixed_array.inner),
3434
asg::TypeKind::FuncPtr(_) => todo!(),
3535
asg::TypeKind::Enum(_, _) => (),
36-
asg::TypeKind::Structure(_, _, parameters) => {
37-
for parameter in parameters {
36+
asg::TypeKind::Structure(_, _, params) | asg::TypeKind::TypeAlias(_, _, params) => {
37+
for parameter in params {
3838
collect_constraints_into(map, parameter);
3939
}
4040
}
41-
asg::TypeKind::TypeAlias(_, _) => (),
4241
asg::TypeKind::Polymorph(name, constraints) => {
4342
let set = map.entry(name.to_string()).or_default();
4443
for constraint in constraints {

Diff for: src/resolve/error.rs

-4
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ pub enum ResolveErrorKind {
225225
name: String,
226226
},
227227
CannotCreateOutOfRangeFloat,
228-
TypeAliasesCannotContainPolymorphs,
229228
FailedToConformArgumentToDefaultValue,
230229
Other {
231230
message: String,
@@ -565,9 +564,6 @@ impl Display for ResolveErrorKind {
565564
ResolveErrorKind::CannotCreateOutOfRangeFloat => {
566565
write!(f, "Cannot create out-of-range floating-point number")?;
567566
}
568-
ResolveErrorKind::TypeAliasesCannotContainPolymorphs => {
569-
write!(f, "Type aliases cannot contain polymorphs")?;
570-
}
571567
ResolveErrorKind::FailedToConformArgumentToDefaultValue => {
572568
write!(f, "Failed to conform argument to default value")?;
573569
}

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

+12-6
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,19 @@ fn matches(
268268
}
269269
_ => Err(mismatch(ty_in_impl.source)),
270270
},
271-
asg::TypeKind::TypeAlias(_, trait_alias_ref) => match &ty_in_impl.kind {
272-
asg::TypeKind::TypeAlias(_, impl_alias_ref) => {
273-
if trait_alias_ref == impl_alias_ref {
274-
Ok(())
275-
} else {
276-
Err(mismatch(ty_in_impl.source))
271+
asg::TypeKind::TypeAlias(_, trait_type_alias_ref, trait_args) => match &ty_in_impl.kind {
272+
asg::TypeKind::TypeAlias(_, impl_type_alias_ref, impl_args) => {
273+
if trait_type_alias_ref != impl_type_alias_ref
274+
|| trait_args.len() != impl_args.len()
275+
{
276+
return Err(mismatch(ty_in_impl.source));
277+
}
278+
279+
for (trait_arg, impl_arg) in trait_args.iter().zip(impl_args.iter()) {
280+
matches(ctx, asg, expected, for_alls, trait_arg, impl_arg)?;
277281
}
282+
283+
Ok(())
278284
}
279285
_ => Err(mismatch(ty_in_impl.source)),
280286
},

0 commit comments

Comments
 (0)