diff --git a/ast/src/lexer.rs b/ast/src/lexer.rs index 59c720f86..dc84820e0 100644 --- a/ast/src/lexer.rs +++ b/ast/src/lexer.rs @@ -163,6 +163,7 @@ pub enum TokenKind { Trait, True, Try, + Type, Uni, UnsignedShr, UnsignedShrAssign, @@ -272,6 +273,7 @@ impl TokenKind { TokenKind::Extern => "the 'extern' keyword", TokenKind::Inline => "the 'inline' keyword", TokenKind::Copy => "the 'copy' keyword", + TokenKind::Type => "the 'type' keyword", } } } @@ -341,6 +343,7 @@ impl Token { | TokenKind::Extern | TokenKind::Inline | TokenKind::Copy + | TokenKind::Type ) } @@ -989,6 +992,7 @@ impl Lexer { "case" => TokenKind::Case, "enum" => TokenKind::Enum, "copy" => TokenKind::Copy, + "type" => TokenKind::Type, _ => TokenKind::Identifier, }, 5 => match value.as_str() { @@ -1359,6 +1363,7 @@ mod tests { assert!(tok(TokenKind::Nil, "", 1..=1, 1..=1).is_keyword()); assert!(tok(TokenKind::Inline, "", 1..=1, 1..=1).is_keyword()); assert!(tok(TokenKind::Copy, "", 1..=1, 1..=1).is_keyword()); + assert!(tok(TokenKind::Type, "", 1..=1, 1..=1).is_keyword()); } #[test] @@ -1987,6 +1992,7 @@ mod tests { assert_token!("case", Case, "case", 1..=1, 1..=4); assert_token!("enum", Enum, "enum", 1..=1, 1..=4); assert_token!("copy", Copy, "copy", 1..=1, 1..=4); + assert_token!("type", Type, "type", 1..=1, 1..=4); assert_token!("class", Class, "class", 1..=1, 1..=5); assert_token!("async", Async, "async", 1..=1, 1..=5); diff --git a/ast/src/nodes.rs b/ast/src/nodes.rs index 2fa422a59..949ef1722 100644 --- a/ast/src/nodes.rs +++ b/ast/src/nodes.rs @@ -450,45 +450,45 @@ impl Node for DefineField { } #[derive(Debug, PartialEq, Eq)] -pub enum ClassExpression { +pub enum TypeExpression { DefineMethod(Box), DefineField(Box), DefineConstructor(Box), Comment(Box), } -impl Node for ClassExpression { +impl Node for TypeExpression { fn location(&self) -> &Location { match self { - ClassExpression::DefineMethod(n) => &n.location, - ClassExpression::DefineField(n) => &n.location, - ClassExpression::DefineConstructor(n) => &n.location, - ClassExpression::Comment(n) => &n.location, + TypeExpression::DefineMethod(n) => &n.location, + TypeExpression::DefineField(n) => &n.location, + TypeExpression::DefineConstructor(n) => &n.location, + TypeExpression::Comment(n) => &n.location, } } } #[derive(Debug, PartialEq, Eq)] -pub struct ClassExpressions { - pub values: Vec, +pub struct TypeExpressions { + pub values: Vec, pub location: Location, } -impl Node for ClassExpressions { +impl Node for TypeExpressions { fn location(&self) -> &Location { &self.location } } #[derive(Debug, PartialEq, Eq)] -pub enum ClassSemantics { +pub enum TypeSemantics { Default, Inline, Copy, } #[derive(Debug, PartialEq, Eq)] -pub enum ClassKind { +pub enum TypeKind { Async, Builtin, Enum, @@ -497,17 +497,17 @@ pub enum ClassKind { } #[derive(Debug, PartialEq, Eq)] -pub struct DefineClass { - pub semantics: ClassSemantics, +pub struct DefineType { + pub semantics: TypeSemantics, pub public: bool, - pub kind: ClassKind, + pub kind: TypeKind, pub name: Constant, pub type_parameters: Option, - pub body: ClassExpressions, + pub body: TypeExpressions, pub location: Location, } -impl Node for DefineClass { +impl Node for DefineType { fn location(&self) -> &Location { &self.location } @@ -574,9 +574,9 @@ impl Node for DefineTrait { pub enum TopLevelExpression { DefineConstant(Box), DefineMethod(Box), - DefineClass(Box), + DefineType(Box), DefineTrait(Box), - ReopenClass(Box), + ReopenType(Box), ImplementTrait(Box), Import(Box), ExternImport(Box), @@ -588,9 +588,9 @@ impl Node for TopLevelExpression { match self { TopLevelExpression::DefineConstant(ref n) => n.location(), TopLevelExpression::DefineMethod(ref n) => n.location(), - TopLevelExpression::DefineClass(ref n) => n.location(), + TopLevelExpression::DefineType(ref n) => n.location(), TopLevelExpression::DefineTrait(ref n) => n.location(), - TopLevelExpression::ReopenClass(ref n) => n.location(), + TopLevelExpression::ReopenType(ref n) => n.location(), TopLevelExpression::ImplementTrait(ref n) => n.location(), TopLevelExpression::Import(ref n) => n.location(), TopLevelExpression::ExternImport(ref n) => n.location(), @@ -627,14 +627,14 @@ impl Node for ImplementationExpressions { } #[derive(Debug, PartialEq, Eq)] -pub struct ReopenClass { - pub class_name: Constant, +pub struct ReopenType { + pub type_name: Constant, pub body: ImplementationExpressions, pub location: Location, pub bounds: Option, } -impl Node for ReopenClass { +impl Node for ReopenType { fn location(&self) -> &Location { &self.location } @@ -698,7 +698,7 @@ impl Node for TypeBounds { #[derive(Debug, PartialEq, Eq)] pub struct ImplementTrait { pub trait_name: TypeName, - pub class_name: Constant, + pub type_name: Constant, pub body: ImplementationExpressions, pub location: Location, pub bounds: Option, @@ -1474,7 +1474,7 @@ pub struct FieldPattern { } #[derive(Debug, PartialEq, Eq)] -pub struct ClassPattern { +pub struct TypePattern { pub values: Vec, pub location: Location, } @@ -1495,7 +1495,7 @@ pub struct StringPattern { pub enum Pattern { Constant(Box), Constructor(Box), - Class(Box), + Type(Box), Int(Box), True(Box), False(Box), @@ -1511,7 +1511,7 @@ impl Pattern { match self { Pattern::Constant(ref n) => &n.location, Pattern::Constructor(ref n) => &n.location, - Pattern::Class(ref n) => &n.location, + Pattern::Type(ref n) => &n.location, Pattern::Int(ref n) => n.location(), Pattern::True(ref n) => n.location(), Pattern::False(ref n) => n.location(), diff --git a/ast/src/parser.rs b/ast/src/parser.rs index fcb80b1b3..8e8be36a7 100644 --- a/ast/src/parser.rs +++ b/ast/src/parser.rs @@ -100,7 +100,7 @@ impl Parser { ) -> Result { let expr = match start.kind { TokenKind::Import => self.import(start)?, - TokenKind::Class => self.define_class(start)?, + TokenKind::Class | TokenKind::Type => self.define_type(start)?, TokenKind::Implement => self.implementation(start)?, TokenKind::Trait => self.define_trait(start)?, TokenKind::Fn => self.define_module_method(start)?, @@ -1022,7 +1022,7 @@ impl Parser { } } - fn define_class( + fn define_type( &mut self, start: Token, ) -> Result { @@ -1030,50 +1030,50 @@ impl Parser { let semantics = match self.peek().kind { TokenKind::Inline => { self.next(); - ClassSemantics::Inline + TypeSemantics::Inline } TokenKind::Copy => { self.next(); - ClassSemantics::Copy + TypeSemantics::Copy } - _ => ClassSemantics::Default, + _ => TypeSemantics::Default, }; let kind = match self.peek().kind { TokenKind::Async => { self.next(); - ClassKind::Async + TypeKind::Async } TokenKind::Enum => { self.next(); - ClassKind::Enum + TypeKind::Enum } TokenKind::Builtin => { self.next(); - ClassKind::Builtin + TypeKind::Builtin } TokenKind::Extern => { self.next(); - ClassKind::Extern + TypeKind::Extern } - _ => ClassKind::Regular, + _ => TypeKind::Regular, }; let name = Constant::from(self.expect(TokenKind::Constant)?); - let type_parameters = if let ClassKind::Extern = kind { + let type_parameters = if let TypeKind::Extern = kind { None } else { self.optional_type_parameter_definitions()? }; - let body = if let ClassKind::Extern = kind { - self.extern_class_expressions()? + let body = if let TypeKind::Extern = kind { + self.extern_type_expressions()? } else { - self.class_expressions()? + self.type_expressions()? }; let location = Location::start_end(&start.location, &body.location); - Ok(TopLevelExpression::DefineClass(Box::new(DefineClass { + Ok(TopLevelExpression::DefineType(Box::new(DefineType { public, semantics, kind, @@ -1108,7 +1108,7 @@ impl Parser { Ok(DefineConstructor { name, members, location }) } - fn class_expressions(&mut self) -> Result { + fn type_expressions(&mut self) -> Result { let start = self.expect(TokenKind::CurlyOpen)?; let mut values = Vec::new(); @@ -1119,16 +1119,16 @@ impl Parser { let location = Location::start_end(&start.location, &token.location); - return Ok(ClassExpressions { values, location }); + return Ok(TypeExpressions { values, location }); } - values.push(self.class_expression(token)?); + values.push(self.type_expression(token)?); } } - fn extern_class_expressions( + fn extern_type_expressions( &mut self, - ) -> Result { + ) -> Result { let start = self.expect(TokenKind::CurlyOpen)?; let mut values = Vec::new(); @@ -1139,15 +1139,15 @@ impl Parser { let location = Location::start_end(&start.location, &token.location); - return Ok(ClassExpressions { values, location }); + return Ok(TypeExpressions { values, location }); } let node = match token.kind { - TokenKind::Let => ClassExpression::DefineField(Box::new( + TokenKind::Let => TypeExpression::DefineField(Box::new( self.define_field(token)?, )), TokenKind::Comment => { - ClassExpression::Comment(self.comment(token)) + TypeExpression::Comment(self.comment(token)) } _ => { error!( @@ -1161,21 +1161,21 @@ impl Parser { } } - fn class_expression( + fn type_expression( &mut self, start: Token, - ) -> Result { + ) -> Result { let expr = match start.kind { - TokenKind::Let => ClassExpression::DefineField(Box::new( - self.define_field(start)?, - )), - TokenKind::Fn => ClassExpression::DefineMethod(Box::new( + TokenKind::Let => { + TypeExpression::DefineField(Box::new(self.define_field(start)?)) + } + TokenKind::Fn => TypeExpression::DefineMethod(Box::new( self.define_method(start)?, )), - TokenKind::Case => ClassExpression::DefineConstructor(Box::new( + TokenKind::Case => TypeExpression::DefineConstructor(Box::new( self.define_constructor(start)?, )), - TokenKind::Comment => ClassExpression::Comment(self.comment(start)), + TokenKind::Comment => TypeExpression::Comment(self.comment(start)), _ => { error!( start.location, @@ -1217,7 +1217,7 @@ impl Parser { { self.implement_trait(start, token) } else { - self.reopen_class(start, token) + self.reopen_type(start, token) } } @@ -1230,14 +1230,14 @@ impl Parser { self.expect(TokenKind::For)?; - let class_name = Constant::from(self.expect(TokenKind::Constant)?); + let type_name = Constant::from(self.expect(TokenKind::Constant)?); let bounds = self.optional_type_bounds()?; let body = self.trait_implementation_expressions()?; let location = Location::start_end(&start.location, body.location()); Ok(TopLevelExpression::ImplementTrait(Box::new(ImplementTrait { trait_name, - class_name, + type_name, body, location, bounds, @@ -1324,26 +1324,26 @@ impl Parser { Ok(Requirements { values, location }) } - fn reopen_class( + fn reopen_type( &mut self, start: Token, - class_token: Token, + type_token: Token, ) -> Result { - let class_name = Constant::from(class_token); + let type_name = Constant::from(type_token); let bounds = self.optional_type_bounds()?; - let body = self.reopen_class_expressions()?; + let body = self.reopen_type_expressions()?; let end_loc = location!(bounds).unwrap_or_else(|| body.location()); let location = Location::start_end(&start.location, end_loc); - Ok(TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name, + Ok(TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name, body, location, bounds, }))) } - fn reopen_class_expressions( + fn reopen_type_expressions( &mut self, ) -> Result { let start = self.expect(TokenKind::CurlyOpen)?; @@ -2756,7 +2756,7 @@ impl Parser { Pattern::Tuple(Box::new(TuplePattern { values, location })) } TokenKind::CurlyOpen => { - Pattern::Class(Box::new(self.class_pattern(token)?)) + Pattern::Type(Box::new(self.type_pattern(token)?)) } _ => { error!( @@ -2819,10 +2819,10 @@ impl Parser { ); } - fn class_pattern( + fn type_pattern( &mut self, start: Token, - ) -> Result { + ) -> Result { let mut values = Vec::new(); while self.peek().kind != TokenKind::CurlyClose { @@ -2846,7 +2846,7 @@ impl Parser { let close = self.expect(TokenKind::CurlyClose)?; let location = Location::start_end(&start.location, &close.location); - Ok(ClassPattern { values, location }) + Ok(TypePattern { values, location }) } fn optional_match_guard( @@ -4612,133 +4612,133 @@ mod tests { } #[test] - fn test_empty_class() { + fn test_empty_type() { assert_eq!( - top(parse("class A {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(9, 10) + location: cols(8, 9) }, - location: cols(1, 10) + location: cols(1, 9) })) ); assert_eq!( - top(parse("class pub A {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type pub A {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: true, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(11, 11) + location: cols(10, 10) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(13, 14) + location: cols(12, 13) }, - location: cols(1, 14) + location: cols(1, 13) })) ); } #[test] - fn test_extern_class() { + fn test_extern_type() { assert_eq!( - top(parse("class extern A {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type extern A {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(14, 14) + location: cols(13, 13) }, - kind: ClassKind::Extern, + kind: TypeKind::Extern, type_parameters: None, - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(16, 17) + location: cols(15, 16) }, - location: cols(1, 17) + location: cols(1, 16) })) ); } #[test] - fn test_copy_class() { + fn test_copy_type() { assert_eq!( - top(parse("class copy A {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type copy A {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Copy, + semantics: TypeSemantics::Copy, name: Constant { source: None, name: "A".to_string(), - location: cols(12, 12) + location: cols(11, 11) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(14, 15) + location: cols(13, 14) }, - location: cols(1, 15) + location: cols(1, 14) })) ); } #[test] - fn test_async_class() { + fn test_async_type() { assert_eq!( - top(parse("class async A {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type async A {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(13, 13) + location: cols(12, 12) }, - kind: ClassKind::Async, + kind: TypeKind::Async, type_parameters: None, - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(15, 16) + location: cols(14, 15) }, - location: cols(1, 16) + location: cols(1, 15) })) ); } #[test] - fn test_class_with_async_method() { + fn test_type_with_async_method() { assert_eq!( - top(parse("class A { fn async foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn async foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: false, public: false, @@ -4746,38 +4746,38 @@ mod tests { kind: MethodKind::Async, name: Identifier { name: "foo".to_string(), - location: cols(20, 22) + location: cols(19, 21) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(24, 25) + location: cols(23, 24) }), - location: cols(11, 25) + location: cols(10, 24) } ))], - location: cols(9, 27) + location: cols(8, 26) }, - location: cols(1, 27) + location: cols(1, 26) })) ); assert_eq!( - top(parse("class A { fn async mut foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn async mut foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: false, public: false, @@ -4785,142 +4785,142 @@ mod tests { kind: MethodKind::AsyncMutable, name: Identifier { name: "foo".to_string(), - location: cols(24, 26) + location: cols(23, 25) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(28, 29) + location: cols(27, 28) }), - location: cols(11, 29) + location: cols(10, 28) } ))], - location: cols(9, 31) + location: cols(8, 30) }, - location: cols(1, 31) + location: cols(1, 30) })) ); } #[test] - fn test_class_with_type_parameters() { + fn test_type_with_type_parameters() { assert_eq!( - top(parse("class A[B: X, C] {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A[B: X, C] {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: Some(TypeParameters { values: vec![ TypeParameter { name: Constant { source: None, name: "B".to_string(), - location: cols(9, 9) + location: cols(8, 8) }, requirements: Some(Requirements { values: vec![Requirement::Trait(TypeName { name: Constant { source: None, name: "X".to_string(), - location: cols(12, 12), + location: cols(11, 11), }, arguments: None, - location: cols(12, 12) + location: cols(11, 11) })], - location: cols(12, 12) + location: cols(11, 11) }), - location: cols(9, 12) + location: cols(8, 11) }, TypeParameter { name: Constant { source: None, name: "C".to_string(), - location: cols(15, 15) + location: cols(14, 14) }, requirements: None, - location: cols(15, 15) + location: cols(14, 14) } ], - location: cols(8, 16) + location: cols(7, 15) }), - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(18, 19) + location: cols(17, 18) }, - location: cols(1, 19) + location: cols(1, 18) })) ); assert_eq!( - top(parse("class A[B: a.X] {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A[B: a.X] {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: Some(TypeParameters { values: vec![TypeParameter { name: Constant { source: None, name: "B".to_string(), - location: cols(9, 9) + location: cols(8, 8) }, requirements: Some(Requirements { values: vec![Requirement::Trait(TypeName { name: Constant { source: Some(Identifier { name: "a".to_string(), - location: cols(12, 12) + location: cols(11, 11) }), name: "X".to_string(), - location: cols(14, 14), + location: cols(13, 13), }, arguments: None, - location: cols(12, 14) + location: cols(11, 13) })], - location: cols(12, 14) + location: cols(11, 13) }), - location: cols(9, 14) + location: cols(8, 13) },], - location: cols(8, 15) + location: cols(7, 14) }), - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(17, 18) + location: cols(16, 17) }, - location: cols(1, 18) + location: cols(1, 17) })) ); } #[test] - fn test_class_with_instance_method() { + fn test_type_with_instance_method() { assert_eq!( - top(parse("class A { fn foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: false, public: false, @@ -4928,38 +4928,38 @@ mod tests { kind: MethodKind::Instance, name: Identifier { name: "foo".to_string(), - location: cols(14, 16) + location: cols(13, 15) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(18, 19) + location: cols(17, 18) }), - location: cols(11, 19) + location: cols(10, 18) } ))], - location: cols(9, 21) + location: cols(8, 20) }, - location: cols(1, 21) + location: cols(1, 20) })) ); assert_eq!( - top(parse("class A { fn pub foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn pub foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: false, public: true, @@ -4967,41 +4967,41 @@ mod tests { kind: MethodKind::Instance, name: Identifier { name: "foo".to_string(), - location: cols(18, 20) + location: cols(17, 19) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(22, 23) + location: cols(21, 22) }), - location: cols(11, 23) + location: cols(10, 22) } ))], - location: cols(9, 25) + location: cols(8, 24) }, - location: cols(1, 25) + location: cols(1, 24) })) ); } #[test] - fn test_class_with_moving_method() { + fn test_type_with_moving_method() { assert_eq!( - top(parse("class A { fn move foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn move foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: false, public: false, @@ -5009,41 +5009,41 @@ mod tests { kind: MethodKind::Moving, name: Identifier { name: "foo".to_string(), - location: cols(19, 21) + location: cols(18, 20) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(23, 24) + location: cols(22, 23) }), - location: cols(11, 24) + location: cols(10, 23) } ))], - location: cols(9, 26) + location: cols(8, 25) }, - location: cols(1, 26) + location: cols(1, 25) })) ) } #[test] - fn test_class_with_inline_method() { + fn test_type_with_inline_method() { assert_eq!( - top(parse("class A { fn inline foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn inline foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: true, public: false, @@ -5051,41 +5051,41 @@ mod tests { kind: MethodKind::Instance, name: Identifier { name: "foo".to_string(), - location: cols(21, 23) + location: cols(20, 22) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(25, 26) + location: cols(24, 25) }), - location: cols(11, 26) + location: cols(10, 25) } ))], - location: cols(9, 28) + location: cols(8, 27) }, - location: cols(1, 28) + location: cols(1, 27) })) ) } #[test] - fn test_class_with_mutating_method() { + fn test_type_with_mutating_method() { assert_eq!( - top(parse("class A { fn mut foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn mut foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: false, public: false, @@ -5093,41 +5093,41 @@ mod tests { kind: MethodKind::Mutable, name: Identifier { name: "foo".to_string(), - location: cols(18, 20) + location: cols(17, 19) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(22, 23) + location: cols(21, 22) }), - location: cols(11, 23) + location: cols(10, 22) } ))], - location: cols(9, 25) + location: cols(8, 24) }, - location: cols(1, 25) + location: cols(1, 24) })) ) } #[test] - fn test_class_with_static_method() { + fn test_type_with_static_method() { assert_eq!( - top(parse("class A { fn static foo {} }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { fn static foo {} }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineMethod(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineMethod(Box::new( DefineMethod { inline: false, public: false, @@ -5135,111 +5135,111 @@ mod tests { kind: MethodKind::Static, name: Identifier { name: "foo".to_string(), - location: cols(21, 23) + location: cols(20, 22) }, type_parameters: None, arguments: None, return_type: None, body: Some(Expressions { values: Vec::new(), - location: cols(25, 26) + location: cols(24, 25) }), - location: cols(11, 26) + location: cols(10, 25) } ))], - location: cols(9, 28) + location: cols(8, 27) }, - location: cols(1, 28) + location: cols(1, 27) })) ) } #[test] - fn test_class_with_field() { + fn test_type_with_field() { assert_eq!( - top(parse("class A { let @foo: A }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { let @foo: A }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineField(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineField(Box::new( DefineField { public: false, name: Identifier { name: "foo".to_string(), - location: cols(15, 18) + location: cols(14, 17) }, value_type: Type::Named(Box::new(TypeName { name: Constant { source: None, name: "A".to_string(), - location: cols(21, 21) + location: cols(20, 20) }, arguments: None, - location: cols(21, 21) + location: cols(20, 20) })), - location: cols(11, 21) + location: cols(10, 20) } ))], - location: cols(9, 23) + location: cols(8, 22) }, - location: cols(1, 23) + location: cols(1, 22) })) ); assert_eq!( - top(parse("class A { let pub @foo: A }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type A { let pub @foo: A }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, + semantics: TypeSemantics::Default, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, - kind: ClassKind::Regular, + kind: TypeKind::Regular, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::DefineField(Box::new( + body: TypeExpressions { + values: vec![TypeExpression::DefineField(Box::new( DefineField { public: true, name: Identifier { name: "foo".to_string(), - location: cols(19, 22) + location: cols(18, 21) }, value_type: Type::Named(Box::new(TypeName { name: Constant { source: None, name: "A".to_string(), - location: cols(25, 25) + location: cols(24, 24) }, arguments: None, - location: cols(25, 25) + location: cols(24, 24) })), - location: cols(11, 25) + location: cols(10, 24) } ))], - location: cols(9, 27) + location: cols(8, 26) }, - location: cols(1, 27) + location: cols(1, 26) })) ); } #[test] - fn test_invalid_classes() { - assert_error!("class A { 10 }", cols(11, 12)); - assert_error!("class {}", cols(7, 7)); - assert_error!("class A {", cols(9, 9)); - assert_error!("class extern A[T] {", cols(15, 15)); - assert_error!("class extern A { fn foo { } }", cols(18, 19)); + fn test_invalid_types() { + assert_error!("type A { 10 }", cols(10, 11)); + assert_error!("type {}", cols(6, 6)); + assert_error!("type A {", cols(8, 8)); + assert_error!("type extern A[T] {", cols(14, 14)); + assert_error!("type extern A { fn foo { } }", cols(17, 18)); } #[test] @@ -5256,7 +5256,7 @@ mod tests { arguments: None, location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { source: None, name: "B".to_string(), location: cols(12, 12) @@ -5293,7 +5293,7 @@ mod tests { }), location: cols(6, 9) }, - class_name: Constant { + type_name: Constant { source: None, name: "C".to_string(), location: cols(15, 15) @@ -5319,7 +5319,7 @@ mod tests { arguments: None, location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { source: None, name: "B".to_string(), location: cols(12, 12) @@ -5403,7 +5403,7 @@ mod tests { arguments: None, location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { source: None, name: "B".to_string(), location: cols(12, 12) @@ -5438,11 +5438,11 @@ mod tests { } #[test] - fn test_reopen_class() { + fn test_reopen_type() { assert_eq!( top(parse("impl A {}")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -5458,8 +5458,8 @@ mod tests { assert_eq!( top(parse("impl A { fn foo {} }")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -5494,8 +5494,8 @@ mod tests { assert_eq!( top(parse("impl A { fn async foo {} }")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -5530,8 +5530,8 @@ mod tests { assert_eq!( top(parse("impl A if T: mut {}")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -5561,8 +5561,8 @@ mod tests { assert_eq!( top(parse("impl A if T: copy {}")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -5592,8 +5592,8 @@ mod tests { assert_eq!( top(parse("impl A if T: mut, {}")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -5626,8 +5626,8 @@ mod tests { fn test_reopen_with_static_method() { assert_eq!( top(parse("impl A { fn static foo {} }")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -5665,8 +5665,8 @@ mod tests { fn test_reopen_with_inline_method() { assert_eq!( top(parse("impl A { fn inline foo {} }")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { - class_name: Constant { + TopLevelExpression::ReopenType(Box::new(ReopenType { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -6244,24 +6244,24 @@ mod tests { } #[test] - fn test_builtin_class() { + fn test_builtin_type() { assert_eq!( - top(parse("class builtin A {}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type builtin A {}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, - kind: ClassKind::Builtin, + semantics: TypeSemantics::Default, + kind: TypeKind::Builtin, name: Constant { source: None, name: "A".to_string(), - location: cols(15, 15) + location: cols(14, 14) }, type_parameters: None, - body: ClassExpressions { + body: TypeExpressions { values: Vec::new(), - location: cols(17, 18) + location: cols(16, 17) }, - location: cols(1, 18) + location: cols(1, 17) })) ); } @@ -7750,7 +7750,7 @@ mod tests { ); assert_eq!( - expr("foo(class: 10)"), + expr("foo(type: 10)"), Expression::Call(Box::new(Call { receiver: None, name: Identifier { @@ -7760,18 +7760,18 @@ mod tests { arguments: Some(Arguments { values: vec![Argument::Named(Box::new(NamedArgument { name: Identifier { - name: "class".to_string(), - location: cols(5, 9) + name: "type".to_string(), + location: cols(5, 8) }, value: Expression::Int(Box::new(IntLiteral { value: "10".to_string(), - location: cols(12, 13) + location: cols(11, 12) })), - location: cols(5, 13) + location: cols(5, 12) })),], - location: cols(4, 14) + location: cols(4, 13) }), - location: cols(1, 14) + location: cols(1, 13) })) ); } @@ -9541,7 +9541,7 @@ mod tests { } #[test] - fn test_match_empty_class_pattern() { + fn test_match_empty_type_pattern() { assert_eq!( expr("match 1 { case {} -> {} }"), Expression::Match(Box::new(Match { @@ -9550,7 +9550,7 @@ mod tests { location: cols(7, 7) })), expressions: vec![MatchExpression::Case(Box::new(MatchCase { - pattern: Pattern::Class(Box::new(ClassPattern { + pattern: Pattern::Type(Box::new(TypePattern { values: Vec::new(), location: cols(16, 17) })), @@ -9567,7 +9567,7 @@ mod tests { } #[test] - fn test_match_class_pattern() { + fn test_match_type_pattern() { assert_eq!( expr("match 1 { case { @a = _ } -> {} }"), Expression::Match(Box::new(Match { @@ -9576,7 +9576,7 @@ mod tests { location: cols(7, 7) })), expressions: vec![MatchExpression::Case(Box::new(MatchCase { - pattern: Pattern::Class(Box::new(ClassPattern { + pattern: Pattern::Type(Box::new(TypePattern { values: vec![FieldPattern { field: Field { name: "a".to_string(), @@ -9679,38 +9679,38 @@ mod tests { } #[test] - fn test_enum_class() { + fn test_enum_type() { assert_eq!( - top(parse("class enum Option[T] { case Some(T) case None }")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse("type enum Option[T] { case Some(T) case None }")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, - kind: ClassKind::Enum, + semantics: TypeSemantics::Default, + kind: TypeKind::Enum, name: Constant { source: None, name: "Option".to_string(), - location: cols(12, 17), + location: cols(11, 16), }, type_parameters: Some(TypeParameters { values: vec![TypeParameter { name: Constant { source: None, name: "T".to_string(), - location: cols(19, 19) + location: cols(18, 18) }, requirements: None, - location: cols(19, 19) + location: cols(18, 18) }], - location: cols(18, 20) + location: cols(17, 19) }), - body: ClassExpressions { + body: TypeExpressions { values: vec![ - ClassExpression::DefineConstructor(Box::new( + TypeExpression::DefineConstructor(Box::new( DefineConstructor { name: Constant { source: None, name: "Some".to_string(), - location: cols(29, 32) + location: cols(28, 31) }, members: Some(Types { values: vec![Type::Named(Box::new( @@ -9720,33 +9720,33 @@ mod tests { name: "T".to_string(), location: location( 1..=1, - 34..=34 + 33..=33 ) }, arguments: None, - location: cols(34, 34) + location: cols(33, 33) } ))], - location: cols(33, 35) + location: cols(32, 34) }), - location: cols(24, 35) + location: cols(23, 34) }, )), - ClassExpression::DefineConstructor(Box::new( + TypeExpression::DefineConstructor(Box::new( DefineConstructor { name: Constant { source: None, name: "None".to_string(), - location: cols(42, 45) + location: cols(41, 44) }, members: None, - location: cols(37, 40) + location: cols(36, 39) }, )) ], - location: cols(22, 47) + location: cols(21, 46) }, - location: cols(1, 47) + location: cols(1, 46) })) ); } @@ -9781,23 +9781,23 @@ mod tests { ); assert_eq!( - top(parse_with_comments("class A {\n# foo\n}")), - TopLevelExpression::DefineClass(Box::new(DefineClass { + top(parse_with_comments("type A {\n# foo\n}")), + TopLevelExpression::DefineType(Box::new(DefineType { public: false, - semantics: ClassSemantics::Default, - kind: ClassKind::Regular, + semantics: TypeSemantics::Default, + kind: TypeKind::Regular, name: Constant { source: None, name: "A".to_string(), - location: cols(7, 7) + location: cols(6, 6) }, type_parameters: None, - body: ClassExpressions { - values: vec![ClassExpression::Comment(Box::new(Comment { + body: TypeExpressions { + values: vec![TypeExpression::Comment(Box::new(Comment { value: "foo".to_string(), location: location(2..=2, 1..=5) }))], - location: location(1..=3, 9..=1) + location: location(1..=3, 8..=1) }, location: location(1..=3, 1..=1) })) @@ -9827,9 +9827,9 @@ mod tests { assert_eq!( top(parse_with_comments("impl A {\n# foo\n}")), - TopLevelExpression::ReopenClass(Box::new(ReopenClass { + TopLevelExpression::ReopenType(Box::new(ReopenType { bounds: None, - class_name: Constant { + type_name: Constant { source: None, name: "A".to_string(), location: cols(6, 6) @@ -9860,7 +9860,7 @@ mod tests { arguments: None, location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { source: None, name: "B".to_string(), location: cols(12, 12) diff --git a/compiler/src/diagnostics.rs b/compiler/src/diagnostics.rs index b73a1bcbc..ba1fe6b2b 100644 --- a/compiler/src/diagnostics.rs +++ b/compiler/src/diagnostics.rs @@ -304,14 +304,14 @@ impl Diagnostics { ); } - pub(crate) fn public_field_private_class( + pub(crate) fn public_field_private_type( &mut self, file: PathBuf, location: Location, ) { self.error( DiagnosticId::DuplicateSymbol, - "public fields can't be defined for private classes", + "public fields can't be defined for private types", file, location, ); @@ -331,7 +331,7 @@ impl Diagnostics { ); } - pub(crate) fn not_a_class( + pub(crate) fn not_a_type( &mut self, name: &str, file: PathBuf, @@ -339,7 +339,7 @@ impl Diagnostics { ) { self.error( DiagnosticId::InvalidType, - format!("'{}' isn't a class", name), + format!("'{}' isn't a type", name), file, location, ); diff --git a/compiler/src/docs.rs b/compiler/src/docs.rs index 2e7e941c5..e001a5f3c 100644 --- a/compiler/src/docs.rs +++ b/compiler/src/docs.rs @@ -8,7 +8,7 @@ use std::mem::take; use std::path::Path; use types::format::{format_type, type_parameter_capabilities}; use types::{ - ClassId, ClassKind, Database, MethodId, ModuleId, TraitId, TypeBounds, + Database, MethodId, ModuleId, TraitId, TypeBounds, TypeId, TypeKind, }; fn location_to_json(location: Location) -> Json { @@ -25,12 +25,12 @@ fn location_to_json(location: Location) -> Json { Json::Object(obj) } -fn class_kind(kind: ClassKind, stack: bool) -> i64 { +fn type_kind(kind: TypeKind, stack: bool) -> i64 { match kind { - ClassKind::Enum => 1, - ClassKind::Async => 2, - ClassKind::Extern => 3, - ClassKind::Atomic => 5, + TypeKind::Enum => 1, + TypeKind::Async => 2, + TypeKind::Extern => 3, + TypeKind::Atomic => 5, _ if stack => 4, _ => 0, } @@ -115,21 +115,21 @@ impl<'a> DefineDocumentation<'a> { for expr in &mut module.expressions { match expr { - hir::TopLevelExpression::Class(n) => { - n.class_id.unwrap().set_documentation( + hir::TopLevelExpression::Type(n) => { + n.type_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); - self.define_class(&mut *n); + self.define_type(&mut *n); } - hir::TopLevelExpression::ExternClass(n) => { - n.class_id.unwrap().set_documentation( + hir::TopLevelExpression::ExternType(n) => { + n.type_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); - self.define_extern_class(&mut *n); + self.define_extern_type(&mut *n); } hir::TopLevelExpression::Constant(n) => { n.constant_id.unwrap().set_documentation( @@ -161,41 +161,41 @@ impl<'a> DefineDocumentation<'a> { self.implement_trait(&mut *n); } hir::TopLevelExpression::Reopen(n) => { - self.reopen_class(&mut *n); + self.reopen_type(&mut *n); } _ => {} } } } - fn define_class(&mut self, node: &mut hir::DefineClass) { + fn define_type(&mut self, node: &mut hir::DefineType) { for expr in &mut node.body { match expr { - hir::ClassExpression::InstanceMethod(n) => { + hir::TypeExpression::InstanceMethod(n) => { n.method_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); } - hir::ClassExpression::StaticMethod(n) => { + hir::TypeExpression::StaticMethod(n) => { n.method_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); } - hir::ClassExpression::AsyncMethod(n) => { + hir::TypeExpression::AsyncMethod(n) => { n.method_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); } - hir::ClassExpression::Field(n) => { + hir::TypeExpression::Field(n) => { n.field_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); } - hir::ClassExpression::Constructor(n) => { + hir::TypeExpression::Constructor(n) => { n.constructor_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), @@ -205,7 +205,7 @@ impl<'a> DefineDocumentation<'a> { } } - fn define_extern_class(&mut self, node: &mut hir::DefineExternClass) { + fn define_extern_type(&mut self, node: &mut hir::DefineExternType) { for n in &mut node.fields { n.field_id .unwrap() @@ -240,22 +240,22 @@ impl<'a> DefineDocumentation<'a> { } } - fn reopen_class(&mut self, node: &mut hir::ReopenClass) { + fn reopen_type(&mut self, node: &mut hir::ReopenType) { for expr in &mut node.body { match expr { - hir::ReopenClassExpression::InstanceMethod(n) => { + hir::ReopenTypeExpression::InstanceMethod(n) => { n.method_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); } - hir::ReopenClassExpression::StaticMethod(n) => { + hir::ReopenTypeExpression::StaticMethod(n) => { n.method_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), ); } - hir::ReopenClassExpression::AsyncMethod(n) => { + hir::ReopenTypeExpression::AsyncMethod(n) => { n.method_id.unwrap().set_documentation( self.db_mut(), take(&mut n.documentation), @@ -319,7 +319,7 @@ impl<'a> GenerateDocumentation<'a> { doc.add("documentation", Json::String(docs)); doc.add("constants", self.constants()); doc.add("methods", self.module_methods()); - doc.add("classes", self.classes()); + doc.add("types", self.types()); doc.add("traits", self.traits()); let path = @@ -373,10 +373,10 @@ impl<'a> GenerateDocumentation<'a> { self.methods(methods) } - fn classes(&self) -> Json { + fn types(&self) -> Json { let mut vals = Vec::new(); - for id in self.module.classes(self.db()) { + for id in self.module.types(self.db()) { let kind = id.kind(self.db()); if kind.is_closure() || kind.is_module() { @@ -395,14 +395,14 @@ impl<'a> GenerateDocumentation<'a> { let is_inline = id.is_inline_type(self.db()); let mut obj = Object::new(); let typ = format!( - "class{}{} {}", + "type{}{} {}", if public { " pub" } else { "" }, match kind { - ClassKind::Enum if is_copy => " copy enum", - ClassKind::Enum if is_inline => " inline enum", - ClassKind::Enum => " enum", - ClassKind::Async => " async", - ClassKind::Extern => " extern", + TypeKind::Enum if is_copy => " copy enum", + TypeKind::Enum if is_inline => " inline enum", + TypeKind::Enum => " enum", + TypeKind::Async => " async", + TypeKind::Extern => " extern", _ if id.is_builtin() => " builtin", _ if is_copy => " copy", _ if is_inline => " inline", @@ -412,7 +412,7 @@ impl<'a> GenerateDocumentation<'a> { ); obj.add("name", Json::String(name)); - obj.add("kind", Json::Int(class_kind(kind, is_copy))); + obj.add("kind", Json::Int(type_kind(kind, is_copy))); obj.add("location", location_to_json(id.location(self.db()))); obj.add("public", Json::Bool(public)); obj.add("type", Json::String(typ)); @@ -447,12 +447,12 @@ impl<'a> GenerateDocumentation<'a> { } let mut obj = Object::new(); - let class_name = cid.name(self.db()).clone(); + let tname = cid.name(self.db()).clone(); let module = cid.module(self.db()).name(self.db()).to_string(); let mut typ = format!( "impl {} for {}", format_type(self.db(), imp.instance), - class_name, + tname, ); if !imp.bounds.is_empty() { @@ -460,7 +460,7 @@ impl<'a> GenerateDocumentation<'a> { } obj.add("module", Json::String(module)); - obj.add("name", Json::String(class_name)); + obj.add("name", Json::String(tname)); obj.add("type", Json::String(typ)); obj.add("public", Json::Bool(public)); vals.push(Json::Object(obj)); @@ -469,7 +469,7 @@ impl<'a> GenerateDocumentation<'a> { Json::Array(vals) } - fn implemented_traits(&self, id: ClassId) -> Json { + fn implemented_traits(&self, id: TypeId) -> Json { let mut vals = Vec::new(); for imp in id.implemented_traits(self.db()) { @@ -573,7 +573,7 @@ impl<'a> GenerateDocumentation<'a> { Json::Array(vals) } - fn constructors(&self, id: ClassId) -> Json { + fn constructors(&self, id: TypeId) -> Json { let mut cons = Vec::new(); for con in id.constructors(self.db()) { @@ -599,7 +599,7 @@ impl<'a> GenerateDocumentation<'a> { Json::Array(cons) } - fn fields(&self, id: ClassId) -> Json { + fn fields(&self, id: TypeId) -> Json { let mut fields = Vec::new(); for field in id.fields(self.db()) { diff --git a/compiler/src/format.rs b/compiler/src/format.rs index dd3d6524d..05eef7a47 100644 --- a/compiler/src/format.rs +++ b/compiler/src/format.rs @@ -3,8 +3,8 @@ use crate::config::Config; use crate::diagnostics::{DiagnosticId, Diagnostics}; use crate::hir::Operator; use ast::nodes::{ - self, ClassExpression, Expression, ImplementationExpression, Node as _, - Requirement, TopLevelExpression, TraitExpression, + self, Expression, ImplementationExpression, Node as _, Requirement, + TopLevelExpression, TraitExpression, TypeExpression, }; use ast::parser::Parser; use std::cmp::Ordering; @@ -70,7 +70,7 @@ enum Node { /// many values on a single line as possible. Fill(Vec), - /// A chunk of ASCII text to display, such as "class" or "async". + /// A chunk of ASCII text to display, such as "type" or "async". Text(String), /// A chunk of text (potentially including Unicode symbols) to display, such @@ -528,8 +528,8 @@ impl Document { self.gen.new_line(); } } - TopLevelExpression::DefineClass(n) => { - self.define_class(n); + TopLevelExpression::DefineType(n) => { + self.define_type(n); if iter.peek().is_some() { self.gen.new_line(); @@ -542,8 +542,8 @@ impl Document { self.gen.new_line(); } } - TopLevelExpression::ReopenClass(n) => { - self.reopen_class(n); + TopLevelExpression::ReopenType(n) => { + self.reopen_type(n); if iter.peek().is_some() { self.gen.new_line(); @@ -732,26 +732,26 @@ impl Document { self.gen.generate(nodes); } - fn define_class(&mut self, node: &nodes::DefineClass) { + fn define_type(&mut self, node: &nodes::DefineType) { let header_id = self.new_group_id(); - let mut header = vec![Node::text("class ")]; + let mut header = vec![Node::text("type ")]; if node.public { header.push(Node::text("pub ")); } match node.semantics { - nodes::ClassSemantics::Inline => header.push(Node::text("inline ")), - nodes::ClassSemantics::Copy => header.push(Node::text("copy ")), + nodes::TypeSemantics::Inline => header.push(Node::text("inline ")), + nodes::TypeSemantics::Copy => header.push(Node::text("copy ")), _ => {} } match node.kind { - nodes::ClassKind::Async => header.push(Node::text("async ")), - nodes::ClassKind::Builtin => header.push(Node::text("builtin ")), - nodes::ClassKind::Enum => header.push(Node::text("enum ")), - nodes::ClassKind::Extern => header.push(Node::text("extern ")), - nodes::ClassKind::Regular => {} + nodes::TypeKind::Async => header.push(Node::text("async ")), + nodes::TypeKind::Builtin => header.push(Node::text("builtin ")), + nodes::TypeKind::Enum => header.push(Node::text("enum ")), + nodes::TypeKind::Extern => header.push(Node::text("extern ")), + nodes::TypeKind::Regular => {} } header.push(Node::text(&node.name.name)); @@ -769,7 +769,7 @@ impl Document { while let Some(expr) = iter.next() { let trailing = match iter.peek() { - Some(ClassExpression::Comment(next)) + Some(TypeExpression::Comment(next)) if next.location.is_trailing(expr.location()) => { iter.next(); @@ -780,18 +780,18 @@ impl Document { let next = iter.peek(); let (node, tight) = match expr { - ClassExpression::DefineMethod(n) => { + TypeExpression::DefineMethod(n) => { (self.define_method(n), false) } - ClassExpression::DefineField(n) => ( + TypeExpression::DefineField(n) => ( self.define_field(n), - matches!(next, Some(ClassExpression::DefineField(_))), + matches!(next, Some(TypeExpression::DefineField(_))), ), - ClassExpression::DefineConstructor(n) => ( + TypeExpression::DefineConstructor(n) => ( self.define_constructor(n), - matches!(next, Some(ClassExpression::DefineConstructor(_))), + matches!(next, Some(TypeExpression::DefineConstructor(_))), ), - ClassExpression::Comment(n) => (self.comment(n), true), + TypeExpression::Comment(n) => (self.comment(n), true), }; exprs.push(node); @@ -821,12 +821,12 @@ impl Document { ] }; - let class = vec![ + let typ = vec![ Node::Group(header_id, header), Node::WrapIf(header_id, Box::new(self.group(body))), ]; - self.gen.generate(Node::Nodes(class)); + self.gen.generate(Node::Nodes(typ)); self.gen.new_line(); } @@ -930,10 +930,10 @@ impl Document { self.gen.new_line(); } - fn reopen_class(&mut self, node: &nodes::ReopenClass) { + fn reopen_type(&mut self, node: &nodes::ReopenType) { let header_id = self.new_group_id(); let mut header = - vec![Node::text("impl "), Node::text(&node.class_name.name)]; + vec![Node::text("impl "), Node::text(&node.type_name.name)]; if let Some(node) = &node.bounds { header.push(self.type_bounds(node)); @@ -959,7 +959,7 @@ impl Document { self.type_name(&node.trait_name, None), Node::SpaceOrLine, Node::text("for "), - Node::text(&node.class_name.name), + Node::text(&node.type_name.name), ]; let mut header = vec![self.group(start)]; @@ -1862,7 +1862,7 @@ impl Document { // When parentheses are explicitly used for expressions such as // `User()` and `foo.User()`, we retain the parentheses as they - // might be used to create an instance of a new class. + // might be used to create an instance of a new type. if node.is_some() && node.map_or(false, |v| v.values.is_empty()) && name.chars().next().map_or(false, |v| v.is_uppercase()) @@ -2072,7 +2072,7 @@ impl Document { let arrow_sep = if matches!( node.pattern, nodes::Pattern::Or(_) - | nodes::Pattern::Class(_) + | nodes::Pattern::Type(_) | nodes::Pattern::Tuple(_) | nodes::Pattern::Identifier(_) ) || node.guard.is_some() @@ -2144,7 +2144,7 @@ impl Document { group } - nodes::Pattern::Class(n) => { + nodes::Pattern::Type(n) => { let gid = self.new_group_id(); let vals = self.list(&n.values, gid, |this, pat| { let group = vec![ diff --git a/compiler/src/hir.rs b/compiler/src/hir.rs index c66416c30..4ea59180e 100644 --- a/compiler/src/hir.rs +++ b/compiler/src/hir.rs @@ -119,7 +119,7 @@ pub(crate) struct ConstStringLiteral { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct TupleLiteral { - pub(crate) class_id: Option, + pub(crate) type_id: Option, pub(crate) value_types: Vec, pub(crate) resolved_type: types::TypeRef, pub(crate) values: Vec, @@ -162,7 +162,7 @@ pub(crate) struct Call { pub(crate) arguments: Vec, /// A flag that signals parentheses are used, even if no arguments are /// specified. This is used to disambiguate between `Foo` referring to a - /// class, and `Foo()` that creates an instance of a class. + /// type, and `Foo()` that creates an instance of a type. /// /// We use this flag instead of turning `arguments` into /// `Option>` since we don't care about the presence (or lack) @@ -368,7 +368,7 @@ pub(crate) struct DefineField { } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) enum ClassExpression { +pub(crate) enum TypeExpression { InstanceMethod(Box), StaticMethod(Box), AsyncMethod(Box), @@ -377,7 +377,7 @@ pub(crate) enum ClassExpression { } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) enum ClassKind { +pub(crate) enum TypeKind { Async, Builtin, Enum, @@ -385,30 +385,30 @@ pub(crate) enum ClassKind { } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) enum ClassSemantics { +pub(crate) enum TypeSemantics { Default, Inline, Copy, } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct DefineClass { +pub(crate) struct DefineType { pub(crate) documentation: String, pub(crate) public: bool, - pub(crate) semantics: ClassSemantics, - pub(crate) class_id: Option, - pub(crate) kind: ClassKind, + pub(crate) semantics: TypeSemantics, + pub(crate) type_id: Option, + pub(crate) kind: TypeKind, pub(crate) name: Constant, pub(crate) type_parameters: Vec, - pub(crate) body: Vec, + pub(crate) body: Vec, pub(crate) location: Location, } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct DefineExternClass { +pub(crate) struct DefineExternType { pub(crate) documentation: String, pub(crate) public: bool, - pub(crate) class_id: Option, + pub(crate) type_id: Option, pub(crate) name: Constant, pub(crate) fields: Vec, pub(crate) location: Location, @@ -444,29 +444,29 @@ pub(crate) struct DefineTrait { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum TopLevelExpression { - Class(Box), - ExternClass(Box), + Type(Box), + ExternType(Box), Constant(Box), ModuleMethod(Box), ExternFunction(Box), Trait(Box), Implement(Box), Import(Box), - Reopen(Box), + Reopen(Box), ExternImport(Box), } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct ReopenClass { - pub(crate) class_id: Option, - pub(crate) class_name: Constant, - pub(crate) body: Vec, +pub(crate) struct ReopenType { + pub(crate) type_id: Option, + pub(crate) type_name: Constant, + pub(crate) body: Vec, pub(crate) bounds: Vec, pub(crate) location: Location, } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) enum ReopenClassExpression { +pub(crate) enum ReopenTypeExpression { InstanceMethod(Box), StaticMethod(Box), AsyncMethod(Box), @@ -484,12 +484,12 @@ pub(crate) struct TypeBound { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct ImplementTrait { pub(crate) trait_name: TypeName, - pub(crate) class_name: Constant, + pub(crate) type_name: Constant, pub(crate) body: Vec, pub(crate) location: Location, pub(crate) bounds: Vec, pub(crate) trait_instance: Option, - pub(crate) class_instance: Option, + pub(crate) type_instance: Option, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -1003,8 +1003,8 @@ pub(crate) struct FieldPattern { } #[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct ClassPattern { - pub(crate) class_id: Option, +pub(crate) struct TypePattern { + pub(crate) type_id: Option, pub(crate) values: Vec, pub(crate) location: Location, } @@ -1053,7 +1053,7 @@ pub struct StringPattern { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum Pattern { - Class(Box), + Type(Box), Constant(Box), Identifier(Box), Int(Box), @@ -1075,7 +1075,7 @@ impl Pattern { Pattern::String(ref n) => n.location, Pattern::Identifier(ref n) => n.location, Pattern::Tuple(ref n) => n.location, - Pattern::Class(ref n) => n.location, + Pattern::Type(ref n) => n.location, Pattern::Wildcard(ref n) => n.location, Pattern::True(ref n) => n.location, Pattern::False(ref n) => n.location, @@ -1197,18 +1197,18 @@ impl<'a> LowerToHir<'a> { exprs.push(self.define_module_method(*node, doc)); } - ast::TopLevelExpression::DefineClass(node) => { + ast::TopLevelExpression::DefineType(node) => { let doc = comments.documentation_for(&node.location); - exprs.push(self.define_class(*node, doc)); + exprs.push(self.define_type(*node, doc)); } ast::TopLevelExpression::DefineTrait(node) => { let doc = comments.documentation_for(&node.location); exprs.push(self.define_trait(*node, doc)); } - ast::TopLevelExpression::ReopenClass(node) => { - exprs.push(self.reopen_class(*node)); + ast::TopLevelExpression::ReopenType(node) => { + exprs.push(self.reopen_type(*node)); } ast::TopLevelExpression::ImplementTrait(node) => { exprs.push(self.implement_trait(*node)); @@ -1311,14 +1311,14 @@ impl<'a> LowerToHir<'a> { } } - fn define_class( + fn define_type( &mut self, - node: ast::DefineClass, + node: ast::DefineType, documentation: String, ) -> TopLevelExpression { - if !matches!(node.semantics, ast::ClassSemantics::Default) { + if !matches!(node.semantics, ast::TypeSemantics::Default) { match node.kind { - ast::ClassKind::Enum | ast::ClassKind::Regular => {} + ast::TypeKind::Enum | ast::TypeKind::Regular => {} _ => { self.state.diagnostics.error( DiagnosticId::InvalidType, @@ -1331,36 +1331,36 @@ impl<'a> LowerToHir<'a> { } } - if let ast::ClassKind::Extern = node.kind { - return self.define_extern_class(node, documentation); + if let ast::TypeKind::Extern = node.kind { + return self.define_extern_type(node, documentation); } - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation, public: node.public, semantics: match node.semantics { - ast::ClassSemantics::Default => ClassSemantics::Default, - ast::ClassSemantics::Inline => ClassSemantics::Inline, - ast::ClassSemantics::Copy => ClassSemantics::Copy, + ast::TypeSemantics::Default => TypeSemantics::Default, + ast::TypeSemantics::Inline => TypeSemantics::Inline, + ast::TypeSemantics::Copy => TypeSemantics::Copy, }, - class_id: None, + type_id: None, kind: match node.kind { - ast::ClassKind::Async => ClassKind::Async, - ast::ClassKind::Enum => ClassKind::Enum, - ast::ClassKind::Builtin => ClassKind::Builtin, - _ => ClassKind::Regular, + ast::TypeKind::Async => TypeKind::Async, + ast::TypeKind::Enum => TypeKind::Enum, + ast::TypeKind::Builtin => TypeKind::Builtin, + _ => TypeKind::Regular, }, name: self.constant(node.name), type_parameters: self .optional_type_parameters(node.type_parameters), - body: self.class_expressions(node.body), + body: self.type_expressions(node.body), location: node.location, })) } - fn define_extern_class( + fn define_extern_type( &mut self, - node: ast::DefineClass, + node: ast::DefineType, documentation: String, ) -> TopLevelExpression { let mut fields = Vec::new(); @@ -1368,55 +1368,55 @@ impl<'a> LowerToHir<'a> { for expr in node.body.values { match expr { - ast::ClassExpression::DefineField(n) => { + ast::TypeExpression::DefineField(n) => { let doc = comments.documentation_for(&n.location); fields.push(self.define_field(*n, doc)); } - ast::ClassExpression::Comment(c) => { + ast::TypeExpression::Comment(c) => { comments.push(*c); } _ => unreachable!(), } } - TopLevelExpression::ExternClass(Box::new(DefineExternClass { + TopLevelExpression::ExternType(Box::new(DefineExternType { documentation, public: node.public, - class_id: None, + type_id: None, name: self.constant(node.name), fields, location: node.location, })) } - fn class_expressions( + fn type_expressions( &mut self, - node: ast::ClassExpressions, - ) -> Vec { + node: ast::TypeExpressions, + ) -> Vec { let mut exprs = Vec::new(); let mut comments = Comments::new(); for n in node.values { match n { - ast::ClassExpression::DefineMethod(node) => { + ast::TypeExpression::DefineMethod(node) => { let doc = comments.documentation_for(&node.location); - exprs.push(self.define_method_in_class(*node, doc)); + exprs.push(self.define_method_in_type(*node, doc)); } - ast::ClassExpression::DefineField(node) => { + ast::TypeExpression::DefineField(node) => { let doc = comments.documentation_for(&node.location); - exprs.push(ClassExpression::Field(Box::new( + exprs.push(TypeExpression::Field(Box::new( self.define_field(*node, doc), ))); } - ast::ClassExpression::DefineConstructor(node) => { + ast::TypeExpression::DefineConstructor(node) => { let doc = comments.documentation_for(&node.location); exprs.push(self.define_case(*node, doc)); } - ast::ClassExpression::Comment(c) => { + ast::TypeExpression::Comment(c) => { comments.push(*c); } } @@ -1444,8 +1444,8 @@ impl<'a> LowerToHir<'a> { &mut self, node: ast::DefineConstructor, documentation: String, - ) -> ClassExpression { - ClassExpression::Constructor(Box::new(DefineConstructor { + ) -> TypeExpression { + TypeExpression::Constructor(Box::new(DefineConstructor { documentation, method_id: None, constructor_id: None, @@ -1455,21 +1455,21 @@ impl<'a> LowerToHir<'a> { })) } - fn define_method_in_class( + fn define_method_in_type( &mut self, node: ast::DefineMethod, documentation: String, - ) -> ClassExpression { + ) -> TypeExpression { match node.kind { ast::MethodKind::Async | ast::MethodKind::AsyncMutable => { - ClassExpression::AsyncMethod( + TypeExpression::AsyncMethod( self.define_async_method(node, documentation), ) } - ast::MethodKind::Static => ClassExpression::StaticMethod( + ast::MethodKind::Static => TypeExpression::StaticMethod( self.define_static_method(node, documentation), ), - _ => ClassExpression::InstanceMethod(Box::new( + _ => TypeExpression::InstanceMethod(Box::new( self.define_instance_method(node, documentation), )), } @@ -1704,20 +1704,20 @@ impl<'a> LowerToHir<'a> { } } - fn reopen_class(&mut self, node: ast::ReopenClass) -> TopLevelExpression { - TopLevelExpression::Reopen(Box::new(ReopenClass { - class_id: None, - class_name: self.constant(node.class_name), - body: self.reopen_class_expressions(node.body), + fn reopen_type(&mut self, node: ast::ReopenType) -> TopLevelExpression { + TopLevelExpression::Reopen(Box::new(ReopenType { + type_id: None, + type_name: self.constant(node.type_name), + body: self.reopen_type_expressions(node.body), bounds: self.optional_type_bounds(node.bounds), location: node.location, })) } - fn reopen_class_expressions( + fn reopen_type_expressions( &mut self, nodes: ast::ImplementationExpressions, - ) -> Vec { + ) -> Vec { let mut exprs = Vec::new(); let mut comments = Comments::new(); @@ -1726,7 +1726,7 @@ impl<'a> LowerToHir<'a> { ast::ImplementationExpression::DefineMethod(n) => { let doc = comments.documentation_for(&n.location); - exprs.push(self.define_method_in_reopen_class(*n, doc)); + exprs.push(self.define_method_in_reopen_type(*n, doc)); } ast::ImplementationExpression::Comment(c) => { comments.push(*c); @@ -1737,21 +1737,21 @@ impl<'a> LowerToHir<'a> { exprs } - fn define_method_in_reopen_class( + fn define_method_in_reopen_type( &mut self, node: ast::DefineMethod, documentation: String, - ) -> ReopenClassExpression { + ) -> ReopenTypeExpression { match node.kind { - ast::MethodKind::Static => ReopenClassExpression::StaticMethod( + ast::MethodKind::Static => ReopenTypeExpression::StaticMethod( self.define_static_method(node, documentation), ), ast::MethodKind::Async | ast::MethodKind::AsyncMutable => { - ReopenClassExpression::AsyncMethod( + ReopenTypeExpression::AsyncMethod( self.define_async_method(node, documentation), ) } - _ => ReopenClassExpression::InstanceMethod(Box::new( + _ => ReopenTypeExpression::InstanceMethod(Box::new( self.define_instance_method(node, documentation), )), } @@ -1763,12 +1763,12 @@ impl<'a> LowerToHir<'a> { ) -> TopLevelExpression { TopLevelExpression::Implement(Box::new(ImplementTrait { trait_name: self.type_name(node.trait_name), - class_name: self.constant(node.class_name), + type_name: self.constant(node.type_name), bounds: self.optional_type_bounds(node.bounds), body: self.trait_implementation_expressions(node.body), location: node.location, trait_instance: None, - class_instance: None, + type_instance: None, })) } @@ -2233,7 +2233,7 @@ impl<'a> LowerToHir<'a> { fn tuple_literal(&mut self, node: ast::Tuple) -> Box { Box::new(TupleLiteral { - class_id: None, + type_id: None, value_types: Vec::new(), resolved_type: types::TypeRef::Unknown, values: self.values(node.values), @@ -3198,8 +3198,8 @@ impl<'a> LowerToHir<'a> { values: self.patterns(n.values), location: n.location, })), - ast::Pattern::Class(n) => Pattern::Class(Box::new(ClassPattern { - class_id: None, + ast::Pattern::Type(n) => Pattern::Type(Box::new(TypePattern { + type_id: None, values: n .values .into_iter() @@ -3956,76 +3956,76 @@ mod tests { } #[test] - fn test_lower_class() { - let hir = lower_top_expr("class A[B: C] { let @a: B }").0; + fn test_lower_type() { + let hir = lower_top_expr("type A[B: C] { let @a: B }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - kind: ClassKind::Regular, - class_id: None, - name: Constant { name: "A".to_string(), location: cols(7, 7) }, + semantics: TypeSemantics::Default, + kind: TypeKind::Regular, + type_id: None, + name: Constant { name: "A".to_string(), location: cols(6, 6) }, type_parameters: vec![TypeParameter { type_parameter_id: None, name: Constant { name: "B".to_string(), - location: cols(9, 9) + location: cols(8, 8) }, requirements: vec![TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "C".to_string(), - location: cols(12, 12) + location: cols(11, 11) }, arguments: Vec::new(), - location: cols(12, 12) + location: cols(11, 11) }], mutable: false, copy: false, - location: cols(9, 12) + location: cols(8, 11) }], - body: vec![ClassExpression::Field(Box::new(DefineField { + body: vec![TypeExpression::Field(Box::new(DefineField { documentation: String::new(), public: false, field_id: None, name: Identifier { name: "a".to_string(), - location: cols(21, 22) + location: cols(20, 21) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "B".to_string(), - location: cols(25, 25) + location: cols(24, 24) }, arguments: Vec::new(), - location: cols(25, 25) + location: cols(24, 24) })), - location: cols(17, 25), + location: cols(16, 24), }))], - location: cols(1, 27) + location: cols(1, 26) })), ); } #[test] - fn test_lower_extern_class() { - let hir = lower_top_expr("class extern A { let @a: B }").0; + fn test_lower_extern_type() { + let hir = lower_top_expr("type extern A { let @a: B }").0; assert_eq!( hir, - TopLevelExpression::ExternClass(Box::new(DefineExternClass { + TopLevelExpression::ExternType(Box::new(DefineExternType { documentation: String::new(), public: false, - class_id: None, + type_id: None, name: Constant { name: "A".to_string(), - location: cols(14, 14) + location: cols(13, 13) }, fields: vec![DefineField { documentation: String::new(), @@ -4033,380 +4033,380 @@ mod tests { field_id: None, name: Identifier { name: "a".to_string(), - location: cols(22, 23) + location: cols(21, 22) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "B".to_string(), - location: cols(26, 26) + location: cols(25, 25) }, arguments: Vec::new(), - location: cols(26, 26) + location: cols(25, 25) })), - location: cols(18, 26), + location: cols(17, 25), }], - location: cols(1, 28) + location: cols(1, 27) })), ); } #[test] - fn test_lower_copy_class() { - let hir = lower_top_expr("class copy A { let @a: B }").0; + fn test_lower_copy_type() { + let hir = lower_top_expr("type copy A { let @a: B }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Copy, - class_id: None, - kind: ClassKind::Regular, + semantics: TypeSemantics::Copy, + type_id: None, + kind: TypeKind::Regular, name: Constant { name: "A".to_string(), - location: cols(12, 12) + location: cols(11, 11) }, - body: vec![ClassExpression::Field(Box::new(DefineField { + body: vec![TypeExpression::Field(Box::new(DefineField { documentation: String::new(), public: false, field_id: None, name: Identifier { name: "a".to_string(), - location: cols(20, 21) + location: cols(19, 20) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "B".to_string(), - location: cols(24, 24) + location: cols(23, 23) }, arguments: Vec::new(), - location: cols(24, 24) + location: cols(23, 23) })), - location: cols(16, 24), + location: cols(15, 23), }))], type_parameters: Vec::new(), - location: cols(1, 26) + location: cols(1, 25) })), ); } #[test] - fn test_lower_public_class() { - let hir = lower_top_expr("class pub A {}").0; + fn test_lower_public_type() { + let hir = lower_top_expr("type pub A {}").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: true, - semantics: ClassSemantics::Default, - kind: ClassKind::Regular, - class_id: None, + semantics: TypeSemantics::Default, + kind: TypeKind::Regular, + type_id: None, name: Constant { name: "A".to_string(), - location: cols(11, 11) + location: cols(10, 10) }, type_parameters: Vec::new(), body: Vec::new(), - location: cols(1, 14) + location: cols(1, 13) })), ); } #[test] - fn test_lower_class_with_public_field() { - let hir = lower_top_expr("class A { let pub @a: A }").0; + fn test_lower_type_with_public_field() { + let hir = lower_top_expr("type A { let pub @a: A }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - kind: ClassKind::Regular, - class_id: None, - name: Constant { name: "A".to_string(), location: cols(7, 7) }, + semantics: TypeSemantics::Default, + kind: TypeKind::Regular, + type_id: None, + name: Constant { name: "A".to_string(), location: cols(6, 6) }, type_parameters: Vec::new(), - body: vec![ClassExpression::Field(Box::new(DefineField { + body: vec![TypeExpression::Field(Box::new(DefineField { documentation: String::new(), public: true, field_id: None, name: Identifier { name: "a".to_string(), - location: cols(19, 20) + location: cols(18, 19) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "A".to_string(), - location: cols(23, 23) + location: cols(22, 22) }, arguments: Vec::new(), - location: cols(23, 23) + location: cols(22, 22) })), - location: cols(11, 23) + location: cols(10, 22) }))], - location: cols(1, 25) + location: cols(1, 24) })), ); } #[test] - fn test_lower_builtin_class() { - let hir = lower_top_expr("class builtin A[B: C] { let @a: B }").0; + fn test_lower_builtin_type() { + let hir = lower_top_expr("type builtin A[B: C] { let @a: B }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - class_id: None, - kind: ClassKind::Builtin, + semantics: TypeSemantics::Default, + type_id: None, + kind: TypeKind::Builtin, name: Constant { name: "A".to_string(), - location: cols(15, 15) + location: cols(14, 14) }, type_parameters: vec![TypeParameter { type_parameter_id: None, name: Constant { name: "B".to_string(), - location: cols(17, 17) + location: cols(16, 16) }, requirements: vec![TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "C".to_string(), - location: cols(20, 20) + location: cols(19, 19) }, arguments: Vec::new(), - location: cols(20, 20) + location: cols(19, 19) }], mutable: false, copy: false, - location: cols(17, 20) + location: cols(16, 19) }], - body: vec![ClassExpression::Field(Box::new(DefineField { + body: vec![TypeExpression::Field(Box::new(DefineField { documentation: String::new(), public: false, field_id: None, name: Identifier { name: "a".to_string(), - location: cols(29, 30) + location: cols(28, 29) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "B".to_string(), - location: cols(33, 33) + location: cols(32, 32) }, arguments: Vec::new(), - location: cols(33, 33) + location: cols(32, 32) })), - location: cols(25, 33), + location: cols(24, 32), }))], - location: cols(1, 35) + location: cols(1, 34) })), ); } #[test] - fn test_lower_async_class() { - let hir = lower_top_expr("class async A {}").0; + fn test_lower_async_type() { + let hir = lower_top_expr("type async A {}").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - class_id: None, - kind: ClassKind::Async, + semantics: TypeSemantics::Default, + type_id: None, + kind: TypeKind::Async, name: Constant { name: "A".to_string(), - location: cols(13, 13) + location: cols(12, 12) }, type_parameters: Vec::new(), body: Vec::new(), - location: cols(1, 16) + location: cols(1, 15) })), ); } #[test] - fn test_lower_class_with_static_method() { + fn test_lower_type_with_static_method() { let hir = - lower_top_expr("class A { fn static a[A](b: B) -> D { 10 } }").0; + lower_top_expr("type A { fn static a[A](b: B) -> D { 10 } }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - class_id: None, - kind: ClassKind::Regular, - name: Constant { name: "A".to_string(), location: cols(7, 7) }, + semantics: TypeSemantics::Default, + type_id: None, + kind: TypeKind::Regular, + name: Constant { name: "A".to_string(), location: cols(6, 6) }, type_parameters: Vec::new(), - body: vec![ClassExpression::StaticMethod(Box::new( + body: vec![TypeExpression::StaticMethod(Box::new( DefineStaticMethod { inline: false, documentation: String::new(), public: false, name: Identifier { name: "a".to_string(), - location: cols(21, 21) + location: cols(20, 20) }, type_parameters: vec![TypeParameter { type_parameter_id: None, name: Constant { name: "A".to_string(), - location: cols(23, 23) + location: cols(22, 22) }, requirements: Vec::new(), mutable: false, copy: false, - location: cols(23, 23) + location: cols(22, 22) }], arguments: vec![MethodArgument { name: Identifier { name: "b".to_string(), - location: cols(26, 26) + location: cols(25, 25) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "B".to_string(), - location: cols(29, 29) + location: cols(28, 28) }, arguments: Vec::new(), - location: cols(29, 29) + location: cols(28, 28) })), - location: cols(26, 29) + location: cols(25, 28) }], return_type: Some(Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "D".to_string(), - location: cols(35, 35) + location: cols(34, 34) }, arguments: Vec::new(), - location: cols(35, 35) + location: cols(34, 34) }))), body: vec![Expression::Int(Box::new(IntLiteral { value: 10, resolved_type: types::TypeRef::Unknown, - location: cols(39, 40) + location: cols(38, 39) }))], method_id: None, - location: cols(11, 42), + location: cols(10, 41), } ))], - location: cols(1, 44) + location: cols(1, 43) })), ); } #[test] - fn test_lower_class_with_async_method() { + fn test_lower_type_with_async_method() { let hir = - lower_top_expr("class A { fn async a[A](b: B) -> D { 10 } }").0; + lower_top_expr("type A { fn async a[A](b: B) -> D { 10 } }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - class_id: None, - kind: ClassKind::Regular, - name: Constant { name: "A".to_string(), location: cols(7, 7) }, + semantics: TypeSemantics::Default, + type_id: None, + kind: TypeKind::Regular, + name: Constant { name: "A".to_string(), location: cols(6, 6) }, type_parameters: Vec::new(), - body: vec![ClassExpression::AsyncMethod(Box::new( + body: vec![TypeExpression::AsyncMethod(Box::new( DefineAsyncMethod { documentation: String::new(), mutable: false, public: false, name: Identifier { name: "a".to_string(), - location: cols(20, 20) + location: cols(19, 19) }, type_parameters: vec![TypeParameter { type_parameter_id: None, name: Constant { name: "A".to_string(), - location: cols(22, 22) + location: cols(21, 21) }, requirements: Vec::new(), mutable: false, copy: false, - location: cols(22, 22) + location: cols(21, 21) }], arguments: vec![MethodArgument { name: Identifier { name: "b".to_string(), - location: cols(25, 25) + location: cols(24, 24) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "B".to_string(), - location: cols(28, 28) + location: cols(27, 27) }, arguments: Vec::new(), - location: cols(28, 28) + location: cols(27, 27) })), - location: cols(25, 28) + location: cols(24, 27) }], return_type: Some(Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "D".to_string(), - location: cols(34, 34) + location: cols(33, 33) }, arguments: Vec::new(), - location: cols(34, 34) + location: cols(33, 33) }))), body: vec![Expression::Int(Box::new(IntLiteral { value: 10, resolved_type: types::TypeRef::Unknown, - location: cols(38, 39) + location: cols(37, 38) }))], method_id: None, - location: cols(11, 41), + location: cols(10, 40), } ))], - location: cols(1, 43) + location: cols(1, 42) })), ); } #[test] - fn test_lower_class_with_instance_method() { - let hir = lower_top_expr("class A { fn a[A](b: B) -> D { 10 } }").0; + fn test_lower_type_with_instance_method() { + let hir = lower_top_expr("type A { fn a[A](b: B) -> D { 10 } }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - class_id: None, - kind: ClassKind::Regular, - name: Constant { name: "A".to_string(), location: cols(7, 7) }, + semantics: TypeSemantics::Default, + type_id: None, + kind: TypeKind::Regular, + name: Constant { name: "A".to_string(), location: cols(6, 6) }, type_parameters: Vec::new(), - body: vec![ClassExpression::InstanceMethod(Box::new( + body: vec![TypeExpression::InstanceMethod(Box::new( DefineInstanceMethod { inline: false, documentation: String::new(), @@ -4414,75 +4414,75 @@ mod tests { kind: MethodKind::Regular, name: Identifier { name: "a".to_string(), - location: cols(14, 14) + location: cols(13, 13) }, type_parameters: vec![TypeParameter { type_parameter_id: None, name: Constant { name: "A".to_string(), - location: cols(16, 16) + location: cols(15, 15) }, requirements: Vec::new(), mutable: false, copy: false, - location: cols(16, 16) + location: cols(15, 15) }], arguments: vec![MethodArgument { name: Identifier { name: "b".to_string(), - location: cols(19, 19) + location: cols(18, 18) }, value_type: Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "B".to_string(), - location: cols(22, 22) + location: cols(21, 21) }, arguments: Vec::new(), - location: cols(22, 22) + location: cols(21, 21) })), - location: cols(19, 22) + location: cols(18, 21) }], return_type: Some(Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "D".to_string(), - location: cols(28, 28) + location: cols(27, 27) }, arguments: Vec::new(), - location: cols(28, 28) + location: cols(27, 27) }))), body: vec![Expression::Int(Box::new(IntLiteral { value: 10, resolved_type: types::TypeRef::Unknown, - location: cols(32, 33) + location: cols(31, 32) }))], method_id: None, - location: cols(11, 35) + location: cols(10, 34) } ))], - location: cols(1, 37) + location: cols(1, 36) })), ); } #[test] - fn test_lower_class_with_inline_method() { - let hir = lower_top_expr("class A { fn inline foo {} }").0; + fn test_lower_type_with_inline_method() { + let hir = lower_top_expr("type A { fn inline foo {} }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - class_id: None, - kind: ClassKind::Regular, - name: Constant { name: "A".to_string(), location: cols(7, 7) }, + semantics: TypeSemantics::Default, + type_id: None, + kind: TypeKind::Regular, + name: Constant { name: "A".to_string(), location: cols(6, 6) }, type_parameters: Vec::new(), - body: vec![ClassExpression::InstanceMethod(Box::new( + body: vec![TypeExpression::InstanceMethod(Box::new( DefineInstanceMethod { inline: true, documentation: String::new(), @@ -4490,31 +4490,31 @@ mod tests { kind: MethodKind::Regular, name: Identifier { name: "foo".to_string(), - location: cols(21, 23) + location: cols(20, 22) }, type_parameters: Vec::new(), arguments: Vec::new(), return_type: None, body: Vec::new(), method_id: None, - location: cols(11, 26) + location: cols(10, 25) } ))], - location: cols(1, 28) + location: cols(1, 27) })), ); } #[test] fn test_lower_static_operator_method() { - let diags = lower_top_expr("class A { fn static + {} }").1; + let diags = lower_top_expr("type A { fn static + {} }").1; assert_eq!(diags, 1); } #[test] fn test_lower_module_operator_method() { - let diags = lower_top_expr("class A { fn static + {} }").1; + let diags = lower_top_expr("type A { fn static + {} }").1; assert_eq!(diags, 1); } @@ -4830,12 +4830,12 @@ mod tests { } #[test] - fn test_lower_reopen_empty_class() { + fn test_lower_reopen_empty_type() { assert_eq!( lower_top_expr("impl A {}").0, - TopLevelExpression::Reopen(Box::new(ReopenClass { - class_id: None, - class_name: Constant { + TopLevelExpression::Reopen(Box::new(ReopenType { + type_id: None, + type_name: Constant { name: "A".to_string(), location: cols(6, 6) }, @@ -4847,9 +4847,9 @@ mod tests { assert_eq!( lower_top_expr("impl A if T: mut {}").0, - TopLevelExpression::Reopen(Box::new(ReopenClass { - class_id: None, - class_name: Constant { + TopLevelExpression::Reopen(Box::new(ReopenType { + type_id: None, + type_name: Constant { name: "A".to_string(), location: cols(6, 6) }, @@ -4870,18 +4870,18 @@ mod tests { } #[test] - fn test_lower_reopen_class_with_instance_method() { + fn test_lower_reopen_type_with_instance_method() { let hir = lower_top_expr("impl A { fn foo {} }").0; assert_eq!( hir, - TopLevelExpression::Reopen(Box::new(ReopenClass { - class_id: None, - class_name: Constant { + TopLevelExpression::Reopen(Box::new(ReopenType { + type_id: None, + type_name: Constant { name: "A".to_string(), location: cols(6, 6) }, - body: vec![ReopenClassExpression::InstanceMethod(Box::new( + body: vec![ReopenTypeExpression::InstanceMethod(Box::new( DefineInstanceMethod { inline: false, documentation: String::new(), @@ -4906,18 +4906,18 @@ mod tests { } #[test] - fn test_lower_reopen_class_with_static_method() { + fn test_lower_reopen_type_with_static_method() { let hir = lower_top_expr("impl A { fn static foo {} }").0; assert_eq!( hir, - TopLevelExpression::Reopen(Box::new(ReopenClass { - class_id: None, - class_name: Constant { + TopLevelExpression::Reopen(Box::new(ReopenType { + type_id: None, + type_name: Constant { name: "A".to_string(), location: cols(6, 6) }, - body: vec![ReopenClassExpression::StaticMethod(Box::new( + body: vec![ReopenTypeExpression::StaticMethod(Box::new( DefineStaticMethod { inline: false, documentation: String::new(), @@ -4941,18 +4941,18 @@ mod tests { } #[test] - fn test_lower_reopen_class_with_async_method() { + fn test_lower_reopen_type_with_async_method() { let hir = lower_top_expr("impl A { fn async foo {} }").0; assert_eq!( hir, - TopLevelExpression::Reopen(Box::new(ReopenClass { - class_id: None, - class_name: Constant { + TopLevelExpression::Reopen(Box::new(ReopenType { + type_id: None, + type_name: Constant { name: "A".to_string(), location: cols(6, 6) }, - body: vec![ReopenClassExpression::AsyncMethod(Box::new( + body: vec![ReopenTypeExpression::AsyncMethod(Box::new( DefineAsyncMethod { documentation: String::new(), mutable: false, @@ -4976,18 +4976,18 @@ mod tests { } #[test] - fn test_lower_reopen_class_with_async_mutable_method() { + fn test_lower_reopen_type_with_async_mutable_method() { let hir = lower_top_expr("impl A { fn async mut foo {} }").0; assert_eq!( hir, - TopLevelExpression::Reopen(Box::new(ReopenClass { - class_id: None, - class_name: Constant { + TopLevelExpression::Reopen(Box::new(ReopenType { + type_id: None, + type_name: Constant { name: "A".to_string(), location: cols(6, 6) }, - body: vec![ReopenClassExpression::AsyncMethod(Box::new( + body: vec![ReopenTypeExpression::AsyncMethod(Box::new( DefineAsyncMethod { documentation: String::new(), mutable: true, @@ -5027,7 +5027,7 @@ mod tests { arguments: Vec::new(), location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { name: "B".to_string(), location: cols(12, 12) }, @@ -5035,7 +5035,7 @@ mod tests { body: Vec::new(), location: cols(1, 15), trait_instance: None, - class_instance: None, + type_instance: None, })) ); } @@ -5066,7 +5066,7 @@ mod tests { }))], location: cols(6, 9) }, - class_name: Constant { + type_name: Constant { name: "B".to_string(), location: cols(15, 15) }, @@ -5074,7 +5074,7 @@ mod tests { body: Vec::new(), location: cols(1, 18), trait_instance: None, - class_instance: None, + type_instance: None, })) ); } @@ -5096,7 +5096,7 @@ mod tests { arguments: Vec::new(), location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { name: "B".to_string(), location: cols(12, 12) }, @@ -5122,7 +5122,7 @@ mod tests { body: Vec::new(), location: cols(1, 29), trait_instance: None, - class_instance: None, + type_instance: None, })) ); } @@ -5144,7 +5144,7 @@ mod tests { arguments: Vec::new(), location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { name: "B".to_string(), location: cols(12, 12) }, @@ -5167,7 +5167,7 @@ mod tests { }], location: cols(1, 26), trait_instance: None, - class_instance: None, + type_instance: None, })) ); } @@ -5189,7 +5189,7 @@ mod tests { arguments: Vec::new(), location: cols(6, 6) }, - class_name: Constant { + type_name: Constant { name: "B".to_string(), location: cols(12, 12) }, @@ -5212,7 +5212,7 @@ mod tests { }], location: cols(1, 31), trait_instance: None, - class_instance: None, + type_instance: None, })) ); } @@ -5649,7 +5649,7 @@ mod tests { assert_eq!( hir, Expression::Tuple(Box::new(TupleLiteral { - class_id: None, + type_id: None, resolved_type: types::TypeRef::Unknown, value_types: Vec::new(), values: vec![Expression::Int(Box::new(IntLiteral { @@ -5669,7 +5669,7 @@ mod tests { assert_eq!( hir, Expression::Tuple(Box::new(TupleLiteral { - class_id: None, + type_id: None, resolved_type: types::TypeRef::Unknown, value_types: Vec::new(), values: vec![Expression::Int(Box::new(IntLiteral { @@ -6764,67 +6764,67 @@ mod tests { } #[test] - fn test_lower_enum_class() { + fn test_lower_enum_type() { let hir = - lower_top_expr("class enum Option[T] { case Some(T) case None }").0; + lower_top_expr("type enum Option[T] { case Some(T) case None }").0; assert_eq!( hir, - TopLevelExpression::Class(Box::new(DefineClass { + TopLevelExpression::Type(Box::new(DefineType { documentation: String::new(), public: false, - semantics: ClassSemantics::Default, - kind: ClassKind::Enum, - class_id: None, + semantics: TypeSemantics::Default, + kind: TypeKind::Enum, + type_id: None, name: Constant { name: "Option".to_string(), - location: cols(12, 17), + location: cols(11, 16), }, type_parameters: vec![TypeParameter { type_parameter_id: None, name: Constant { name: "T".to_string(), - location: cols(19, 19) + location: cols(18, 18) }, requirements: Vec::new(), mutable: false, copy: false, - location: cols(19, 19) + location: cols(18, 18) }], body: vec![ - ClassExpression::Constructor(Box::new(DefineConstructor { + TypeExpression::Constructor(Box::new(DefineConstructor { documentation: String::new(), method_id: None, constructor_id: None, name: Constant { name: "Some".to_string(), - location: cols(29, 32) + location: cols(28, 31) }, members: vec![Type::Named(Box::new(TypeName { source: None, resolved_type: types::TypeRef::Unknown, name: Constant { name: "T".to_string(), - location: cols(34, 34) + location: cols(33, 33) }, arguments: Vec::new(), - location: cols(34, 34) + location: cols(33, 33) }))], - location: cols(24, 35) + location: cols(23, 34) },)), - ClassExpression::Constructor(Box::new(DefineConstructor { + TypeExpression::Constructor(Box::new(DefineConstructor { documentation: String::new(), method_id: None, constructor_id: None, name: Constant { name: "None".to_string(), - location: cols(42, 45) + location: cols(41, 44) }, members: Vec::new(), - location: cols(37, 40) + location: cols(36, 39) },)) ], - location: cols(1, 47) + location: cols(1, 46) })) ); } diff --git a/compiler/src/llvm/builder.rs b/compiler/src/llvm/builder.rs index 0bff03552..d0bdc6191 100644 --- a/compiler/src/llvm/builder.rs +++ b/compiler/src/llvm/builder.rs @@ -20,7 +20,7 @@ use inkwell::values::{ use inkwell::{AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate}; use std::collections::HashMap; use std::path::Path; -use types::{ClassId, Database, MethodId}; +use types::{Database, MethodId, TypeId}; /// A wrapper around an LLVM Builder that provides some additional methods. pub(crate) struct Builder<'ctx> { @@ -753,13 +753,13 @@ impl<'ctx> Builder<'ctx> { module: &'a mut Module<'b, 'ctx>, db: &Database, names: &crate::symbol_names::SymbolNames, - class: ClassId, + type_id: TypeId, ) -> PointerValue<'ctx> { - let atomic = class.is_atomic(db); - let name = &names.classes[&class]; - let global = module.add_class(name).as_pointer_value(); - let class_ptr = self.load_pointer(global); - let typ = module.layouts.instances[class.0 as usize]; + let atomic = type_id.is_atomic(db); + let name = &names.types[&type_id]; + let global = module.add_type(name).as_pointer_value(); + let type_ptr = self.load_pointer(global); + let typ = module.layouts.instances[type_id.0 as usize]; let res = self.malloc(module, typ); let header = module.layouts.header; @@ -768,7 +768,7 @@ impl<'ctx> Builder<'ctx> { // have been created (instead of underflowing). let refs = self.u32_literal(if atomic { 1 } else { 0 }); - self.store_field(header, res, HEADER_CLASS_INDEX, class_ptr); + self.store_field(header, res, HEADER_CLASS_INDEX, type_ptr); self.store_field(header, res, HEADER_REFS_INDEX, refs); res } diff --git a/compiler/src/llvm/context.rs b/compiler/src/llvm/context.rs index 333834c3c..e3c78d2e6 100644 --- a/compiler/src/llvm/context.rs +++ b/compiler/src/llvm/context.rs @@ -14,8 +14,8 @@ use inkwell::{context, AddressSpace}; use std::cmp::max; use std::mem::size_of; use types::{ - Block, Database, ForeignType, MethodId, TypeId, TypeRef, BOOL_ID, FLOAT_ID, - INT_ID, NIL_ID, + Block, Database, ForeignType, MethodId, TypeEnum, TypeRef, BOOL_ID, + FLOAT_ID, INT_ID, NIL_ID, }; fn size_in_bits(bytes: u32) -> u32 { @@ -116,14 +116,14 @@ impl Context { self.inner.struct_type(&[word, word], false) } - pub(crate) fn class_type<'a>( + pub(crate) fn empty_type<'a>( &'a self, method_type: StructType<'a>, ) -> StructType<'a> { let name_type = self.rust_string_type(); - let class_type = self.inner.opaque_struct_type(""); + let typ = self.inner.opaque_struct_type(""); - class_type.set_body( + typ.set_body( &[ // Name name_type.into(), @@ -138,7 +138,7 @@ impl Context { ], false, ); - class_type + typ } /// Returns the layout for a built-in type such as Int or String (i.e a type @@ -179,21 +179,21 @@ impl Context { return self.pointer_type().as_basic_type_enum(); } - let Ok(id) = type_ref.type_id(db) else { + let Ok(id) = type_ref.as_type_enum(db) else { return self.pointer_type().as_basic_type_enum(); }; match id { - TypeId::Foreign(ForeignType::Int(size, _)) => { + TypeEnum::Foreign(ForeignType::Int(size, _)) => { self.custom_int(size).as_basic_type_enum() } - TypeId::Foreign(ForeignType::Float(32)) => { + TypeEnum::Foreign(ForeignType::Float(32)) => { self.f32_type().as_basic_type_enum() } - TypeId::Foreign(ForeignType::Float(_)) => { + TypeEnum::Foreign(ForeignType::Float(_)) => { self.f64_type().as_basic_type_enum() } - TypeId::ClassInstance(ins) => { + TypeEnum::TypeInstance(ins) => { let cls = ins.instance_of(); match cls.0 { diff --git a/compiler/src/llvm/layouts.rs b/compiler/src/llvm/layouts.rs index 29523173b..b1654bb93 100644 --- a/compiler/src/llvm/layouts.rs +++ b/compiler/src/llvm/layouts.rs @@ -8,7 +8,7 @@ use inkwell::types::{ }; use std::collections::VecDeque; use types::{ - CallConvention, ClassId, Database, MethodId, TypeRef, BOOL_ID, + CallConvention, Database, MethodId, TypeId, TypeRef, BOOL_ID, BYTE_ARRAY_ID, FLOAT_ID, INT_ID, NIL_ID, STRING_ID, }; @@ -25,13 +25,13 @@ impl Sized { } fn has_size(&self, db: &Database, typ: TypeRef) -> bool { - // TypeRef::as_class_instance() returns a TypeId for a pointer, but + // TypeRef::as_type_instance() returns a TypeId for a pointer, but // pointers have a known size, so we need to skip the logic below. if typ.is_pointer(db) { return true; } - if let Some(ins) = typ.as_class_instance(db) { + if let Some(ins) = typ.as_type_instance(db) { let cls = ins.instance_of(); cls.is_heap_allocated(db) || self.map[cls.0 as usize] @@ -42,7 +42,7 @@ impl Sized { } } - fn set_has_size(&mut self, id: ClassId) { + fn set_has_size(&mut self, id: TypeId) { self.map[id.0 as usize] = true; } } @@ -176,16 +176,16 @@ impl<'ctx> Method<'ctx> { pub(crate) struct Layouts<'ctx> { pub(crate) target_data: &'ctx TargetData, - /// The layout of an empty class. + /// The layout of an empty type. /// /// This is used for generating dynamic dispatch code, as we don't know the - /// exact class in such cases. - pub(crate) empty_class: StructType<'ctx>, + /// exact type in such cases. + pub(crate) empty_type: StructType<'ctx>, /// The type to use for Inko methods (used for dynamic dispatch). pub(crate) method: StructType<'ctx>, - /// The structure layouts for all class instances. + /// The structure layouts for all type instances. /// /// This `Vec` is indexed using `ClassId` values. pub(crate) instances: Vec>, @@ -218,15 +218,15 @@ impl<'ctx> Layouts<'ctx> { ) -> Self { let db = &state.db; let empty_struct = context.struct_type(&[]); - let num_classes = db.number_of_classes(); + let num_types = db.number_of_types(); // Instead of using a HashMap, we use a Vec that's indexed using a - // ClassId. This works since class IDs are sequential numbers starting + // ClassId. This works since type IDs are sequential numbers starting // at zero. // - // This may over-allocate the number of classes, depending on how many + // This may over-allocate the number of types, depending on how many // are removed through optimizations, but at worst we'd waste a few KiB. - let mut instances = vec![empty_struct; num_classes]; + let mut instances = vec![empty_struct; num_types]; let header = context.struct_type(&[ context.pointer_type().into(), // Class context.i32_type().into(), // References @@ -241,8 +241,8 @@ impl<'ctx> Layouts<'ctx> { // fine/safe is we only use the state type through pointers, so the // exact size doesn't matter. let state_layout = context.struct_type(&[ - context.pointer_type().into(), // String class - context.pointer_type().into(), // ByteArray class + context.pointer_type().into(), // String type + context.pointer_type().into(), // ByteArray type context.pointer_type().into(), // hash_key0 context.pointer_type().into(), // hash_key1 context.i32_type().into(), // scheduler_epoch @@ -260,9 +260,9 @@ impl<'ctx> Layouts<'ctx> { ]); // We generate the bare structs first, that way method signatures can - // refer to them, regardless of the order in which methods/classes are + // refer to them, regardless of the order in which methods/types are // defined. - for &id in mir.classes.keys() { + for &id in mir.types.keys() { let instance = match id.0 { INT_ID | FLOAT_ID | BOOL_ID | NIL_ID => { let typ = context.opaque_struct(""); @@ -275,7 +275,7 @@ impl<'ctx> Layouts<'ctx> { } _ => { // First we forward-declare the structures, as fields may - // need to refer to other classes regardless of ordering. + // need to refer to other types regardless of ordering. context.opaque_struct("") } }; @@ -289,7 +289,7 @@ impl<'ctx> Layouts<'ctx> { let num_methods = db.number_of_methods(); let mut layouts = Self { target_data, - empty_class: context.class_type(method), + empty_type: context.empty_type(method), method, instances, state: state_layout, @@ -314,7 +314,7 @@ impl<'ctx> Layouts<'ctx> { context: &'ctx Context, ) { let db = &state.db; - let num_classes = db.number_of_classes(); + let num_types = db.number_of_types(); let process_size = match state.config.target.os { OperatingSystem::Linux | OperatingSystem::Freebsd => { // Mutexes are smaller on Linux, resulting in a smaller process @@ -335,25 +335,25 @@ impl<'ctx> Layouts<'ctx> { // calculate it of B and C. We do this using a work list approach: if // the size of a type can be calculated immediately we do just that, // otherwise we reschedule it for later (re)processing. - let mut queue = mir.classes.keys().cloned().collect::>(); - let mut sized = Sized::new(num_classes); + let mut queue = mir.types.keys().cloned().collect::>(); + let mut sized = Sized::new(num_types); // These types have a fixed size and don't define any fields. To ensure // the work loop terminates, we manually flag them as known. for id in [BYTE_ARRAY_ID, INT_ID, FLOAT_ID, BOOL_ID, NIL_ID] { - sized.set_has_size(ClassId(id as _)); + sized.set_has_size(TypeId(id as _)); } while let Some(id) = queue.pop_front() { let kind = id.kind(db); - // String is a built-in class, but it's defined like a regular one, + // String is a built-in type, but it's defined like a regular one, // so we _don't_ want to skip it here. if id.is_builtin() && id.0 != STRING_ID { continue; } - // If the type we're checking is _not_ a class instance then we + // If the type we're checking is _not_ a type instance then we // default to _true_ instead of false, since this means we can // trivially calculate the size of that field (e.g. it's a pointer). let size_known = if kind.is_enum() { @@ -418,7 +418,7 @@ impl<'ctx> Layouts<'ctx> { let layout = self.instances[id.0 as usize]; let fields = id.fields(db); - // We add 1 to account for the header that almost all classes + // We add 1 to account for the header that almost all types // processed here will have. let mut types = Vec::with_capacity(fields.len() + 1); @@ -472,8 +472,8 @@ impl<'ctx> Layouts<'ctx> { ) { let db = &state.db; - for mir_class in mir.classes.values() { - for &id in &mir_class.methods { + for mir_typ in mir.types.values() { + for &id in &mir_typ.methods { self.methods[id.0 as usize] = if id.is_async(db) { let args = vec![ArgumentType::Regular( context.pointer_type().as_basic_type_enum(), diff --git a/compiler/src/llvm/methods.rs b/compiler/src/llvm/methods.rs index 38373dd24..fd66685b5 100644 --- a/compiler/src/llvm/methods.rs +++ b/compiler/src/llvm/methods.rs @@ -51,7 +51,7 @@ fn hash_key(db: &Database, method: MethodId, shapes: &[Shape]) -> String { #[derive(Copy, Clone)] pub(crate) struct Method { - /// The index of this method in the owning class' method table. + /// The index of this method in the owning type's method table. pub(crate) index: u16, /// The hash code to use for dynamic dispatch. @@ -69,7 +69,7 @@ pub(crate) struct Methods { /// This `Vec` is indexed using `MethodId` values. pub(crate) info: Vec, - /// The number of method slots for each class. + /// The number of method slots for each type. /// /// This `Vec` is indexed using `ClassId` values. pub(crate) counts: Vec, @@ -79,7 +79,7 @@ impl Methods { pub(crate) fn new(db: &Database, mir: &Mir) -> Methods { let dummy_method = Method { index: 0, hash: 0, collision: false }; let mut info = vec![dummy_method; db.number_of_methods()]; - let mut counts = vec![0; db.number_of_classes()]; + let mut counts = vec![0; db.number_of_types()]; let mut method_hasher = MethodHasher::new(); // This information is defined first so we can update the `collision` @@ -93,22 +93,22 @@ impl Methods { } } - // `mir.classes` is a HashMap, and the order of iterating over a HashMap + // `mir.types` is a HashMap, and the order of iterating over a HashMap // isn't consistent. Should there be conflicting hashes, the order in - // which classes (and thus methods) are processed may affect the hash + // which types (and thus methods) are processed may affect the hash // code. By sorting the list of IDs first and iterating over that, we // ensure we always process the data in a consistent order. - let mut ids = mir.classes.keys().cloned().collect::>(); + let mut ids = mir.types.keys().cloned().collect::>(); ids.sort_by_key(|i| i.name(db)); for id in ids { - let mir_class = &mir.classes[&id]; + let mir_typ = &mir.types[&id]; - // We size classes larger than actually needed in an attempt to + // We size types larger than actually needed in an attempt to // reduce collisions when performing dynamic dispatch. let methods_len = max( - round_methods(mir_class.instance_methods_count(db)) + round_methods(mir_typ.instance_methods_count(db)) * METHOD_TABLE_FACTOR, METHOD_TABLE_MIN_SIZE, ); @@ -125,12 +125,12 @@ impl Methods { buckets[DROPPER_INDEX as usize] = true; } - let is_closure = mir_class.id.is_closure(db); + let is_closure = mir_typ.id.is_closure(db); // Define the method signatures once (so we can cheaply retrieve // them whenever needed), and assign the methods to their method // table slots. - for &method in &mir_class.methods { + for &method in &mir_typ.methods { let name = method.name(db); let hash = method_hasher.hash(hash_key(db, method, method.shapes(db))); @@ -164,7 +164,7 @@ impl Methods { // We track collisions so we can generate more optimal dynamic // dispatch code if we statically know one method never collides - // with another method in the same class. + // with another method in the same type. if collision { if let Some(orig) = method.original_method(db) { if let Some(calls) = mir.dynamic_calls.get(&orig) { diff --git a/compiler/src/llvm/module.rs b/compiler/src/llvm/module.rs index dea811d06..461743831 100644 --- a/compiler/src/llvm/module.rs +++ b/compiler/src/llvm/module.rs @@ -84,7 +84,7 @@ impl<'a, 'ctx> Module<'a, 'ctx> { .unwrap_or_else(|| self.add_global_pointer(name)) } - pub(crate) fn add_class(&mut self, name: &str) -> GlobalValue<'ctx> { + pub(crate) fn add_type(&mut self, name: &str) -> GlobalValue<'ctx> { self.inner.get_global(name).unwrap_or_else(|| { let typ = self.context.pointer_type(); let space = typ.get_address_space(); diff --git a/compiler/src/llvm/passes.rs b/compiler/src/llvm/passes.rs index 39bcb05cc..042bb59d4 100644 --- a/compiler/src/llvm/passes.rs +++ b/compiler/src/llvm/passes.rs @@ -47,7 +47,7 @@ use std::thread::scope; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use types::module_name::ModuleName; use types::{ - ClassId, Database, Intrinsic, Shape, SpecializationKey, TypeRef, + Database, Intrinsic, Shape, SpecializationKey, TypeId, TypeRef, BYTE_ARRAY_ID, STRING_ID, }; @@ -172,8 +172,8 @@ fn check_object_cache( names.push(&symbol_names.constants[id]); } - for id in &module.classes { - names.push(&symbol_names.classes[id]); + for id in &module.types { + names.push(&symbol_names.types[id]); } for id in &module.methods { @@ -628,14 +628,14 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { .run(); } - self.setup_classes(); + self.setup_types(); self.setup_constants(); self.module.debug_builder.finalize(); } - fn setup_classes(&mut self) { + fn setup_types(&mut self) { let mod_id = self.shared.mir.modules[self.index].id; - let fn_name = &self.shared.names.setup_classes[&mod_id]; + let fn_name = &self.shared.names.setup_types[&mod_id]; let fn_val = self.module.add_setup_function(fn_name); let builder = Builder::new(self.module.context, fn_val); let entry_block = self.module.context.append_basic_block(fn_val); @@ -648,31 +648,31 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { builder.jump(body); builder.switch_to_block(body); - // Allocate all classes defined in this module, and store them in their + // Allocate all types defined in this module, and store them in their // corresponding globals. - for &class_id in &self.shared.mir.modules[self.index].classes { - let raw_name = class_id.name(&self.shared.state.db); + for &tid in &self.shared.mir.modules[self.index].types { + let raw_name = tid.name(&self.shared.state.db); let name_ptr = builder.string_literal(raw_name).0.into(); let methods_len = self .module .context .i16_type() .const_int( - self.shared.methods.counts[class_id.0 as usize] as _, + self.shared.methods.counts[tid.0 as usize] as _, false, ) .into(); - let class_new = if class_id.kind(&self.shared.state.db).is_async() { - self.module.runtime_function(RuntimeFunction::ClassProcess) + let type_new = if tid.kind(&self.shared.state.db).is_async() { + self.module.runtime_function(RuntimeFunction::NewProcess) } else { - self.module.runtime_function(RuntimeFunction::ClassObject) + self.module.runtime_function(RuntimeFunction::NewType) }; - let global_name = &self.shared.names.classes[&class_id]; - let global = self.module.add_class(global_name); + let global_name = &self.shared.names.types[&tid]; + let global = self.module.add_type(global_name); - // The class globals must have an initializer, otherwise LLVM treats + // The type globals must have an initializer, otherwise LLVM treats // them as external globals. global.set_initializer( &builder @@ -682,9 +682,9 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { .as_basic_value_enum(), ); - // Built-in classes are defined in the runtime library, so we should + // Built-in types are defined in the runtime library, so we should // look them up instead of creating a new one. - let class_ptr = match class_id.0 { + let type_ptr = match tid.0 { STRING_ID => builder .load_field(self.layouts.state, state, 0) .into_pointer_value(), @@ -693,7 +693,7 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { .into_pointer_value(), _ => { let size = builder.int_to_int( - self.layouts.instances[class_id.0 as usize] + self.layouts.instances[tid.0 as usize] .size_of() .unwrap(), 32, @@ -702,15 +702,15 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { builder .call_with_return( - class_new, + type_new, &[name_ptr, size.into(), methods_len], ) .into_pointer_value() } }; - for method in &self.shared.mir.classes[&class_id].methods { - // Static methods aren't stored in classes, nor can we call them + for method in &self.shared.mir.types[&tid].methods { + // Static methods aren't stored in types, nor can we call them // through dynamic dispatch, so we can skip the rest. if method.is_static(&self.shared.state.db) { continue; @@ -727,8 +727,8 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { let slot = builder.u32_literal(info.index as u32); let method_addr = builder.array_field_index_address( - self.layouts.empty_class, - class_ptr, + self.layouts.empty_type, + type_ptr, CLASS_METHODS_INDEX, slot, ); @@ -747,7 +747,7 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { builder.store(method_addr, method); } - builder.store(global.as_pointer_value(), class_ptr); + builder.store(global.as_pointer_value(), type_ptr); } builder.return_value(None); @@ -859,14 +859,14 @@ impl<'shared, 'module, 'ctx> LowerModule<'shared, 'module, 'ctx> { }; let key = SpecializationKey::new(vec![shape]); - let class_id = ClassId::array() + let tid = TypeId::array() .specializations(&self.shared.state.db)[&key]; - let layout = self.layouts.instances[class_id.0 as usize]; + let layout = self.layouts.instances[tid.0 as usize]; let array = builder.allocate_instance( self.module, &self.shared.state.db, self.shared.names, - class_id, + tid, ); let buf_typ = val_typ.array_type(values.len() as _); @@ -1949,7 +1949,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let info = &self.shared.methods.info[ins.method.0 as usize]; let layout = &self.layouts.methods[ins.method.0 as usize]; let fn_typ = layout.signature(self.builder.context); - let rec_class = self + let rec_type_ptr = self .builder .load_field( self.layouts.header, @@ -1958,15 +1958,15 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { ) .into_pointer_value(); - let rec_type = self.layouts.empty_class; + let rec_type = self.layouts.empty_type; - // (class.method_slots - 1) as u64 + // (type.method_slots - 1) as u64 let len = self.builder.int_to_int( self.builder.int_sub( self.builder .load_field( rec_type, - rec_class, + rec_type_ptr, CLASS_METHODS_COUNT_INDEX, ) .into_int_value(), @@ -1994,7 +1994,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let slot = self.builder.bit_and(idx, len); let method_addr = self.builder.array_field_index_address( rec_type, - rec_class, + rec_type_ptr, CLASS_METHODS_INDEX, slot, ); @@ -2084,7 +2084,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { // Load the method from the method table. let rec = self.builder.load(rec_typ, rec_var); - let class = self + let typ_ptr = self .builder .load_field( self.layouts.header, @@ -2095,8 +2095,8 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let slot = self.builder.u32_literal(CLOSURE_CALL_INDEX); let method_addr = self.builder.array_field_index_address( - self.layouts.empty_class, - class, + self.layouts.empty_type, + typ_ptr, CLASS_METHODS_INDEX, slot, ); @@ -2136,7 +2136,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { )); let rec = self.builder.load(rec_typ, rec_var); - let class = self + let rec_type_ptr = self .builder .load_field( self.layouts.header, @@ -2146,8 +2146,8 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { .into_pointer_value(); let slot = self.builder.u32_literal(DROPPER_INDEX); let addr = self.builder.array_field_index_address( - self.layouts.empty_class, - class, + self.layouts.empty_type, + rec_type_ptr, CLASS_METHODS_INDEX, slot, ); @@ -2215,14 +2215,14 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { ); } Instruction::GetField(ins) - if ins.class.is_heap_allocated(&self.shared.state.db) => + if ins.type_id.is_heap_allocated(&self.shared.state.db) => { let reg_var = self.variables[&ins.register]; let reg_typ = self.variable_types[&ins.register]; let rec_var = self.variables[&ins.receiver]; let rec_typ = self.variable_types[&ins.receiver]; - let class_kind = ins.class.kind(&self.shared.state.db); - let base = if class_kind.is_async() { + let tkind = ins.type_id.kind(&self.shared.state.db); + let base = if tkind.is_async() { PROCESS_FIELD_OFFSET } else { FIELD_OFFSET @@ -2230,7 +2230,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let index = (base + ins.field.index(&self.shared.state.db)) as u32; - let layout = self.layouts.instances[ins.class.0 as usize]; + let layout = self.layouts.instances[ins.type_id.0 as usize]; let rec = self.builder.load(rec_typ, rec_var); // When loading fields from enums we may load from an opaque @@ -2252,7 +2252,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let reg_typ = self.variable_types[&ins.register]; let rec_var = self.variables[&ins.receiver]; let rec_typ = self.variable_types[&ins.receiver]; - let layout = self.layouts.instances[ins.class.0 as usize]; + let layout = self.layouts.instances[ins.type_id.0 as usize]; let index = ins.field.index(&self.shared.state.db) as u32; let field = if rec_typ.is_pointer_type() { let rec = self @@ -2273,13 +2273,14 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { self.builder.store(reg_var, field); } Instruction::SetField(ins) - if ins.class.is_heap_allocated(&self.shared.state.db) => + if ins.type_id.is_heap_allocated(&self.shared.state.db) => { let rec_var = self.variables[&ins.receiver]; let rec_typ = self.variable_types[&ins.receiver]; let val_var = self.variables[&ins.value]; let val_typ = self.variable_types[&ins.value]; - let base = if ins.class.kind(&self.shared.state.db).is_async() { + let base = if ins.type_id.kind(&self.shared.state.db).is_async() + { PROCESS_FIELD_OFFSET } else { FIELD_OFFSET @@ -2288,7 +2289,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let index = (base + ins.field.index(&self.shared.state.db)) as u32; let val = self.builder.load(val_typ, val_var); - let layout = self.layouts.instances[ins.class.0 as usize]; + let layout = self.layouts.instances[ins.type_id.0 as usize]; let rec = self.builder.load(rec_typ, rec_var); self.builder.store_field( @@ -2302,7 +2303,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let rec_var = self.variables[&ins.receiver]; let rec_typ = self.variable_types[&ins.receiver]; let val_var = self.variables[&ins.value]; - let layout = self.layouts.instances[ins.class.0 as usize]; + let layout = self.layouts.instances[ins.type_id.0 as usize]; let index = ins.field.index(&self.shared.state.db) as u32; let val_typ = self.variable_types[&ins.value]; let val = self.builder.load(val_typ, val_var); @@ -2319,12 +2320,13 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { } } Instruction::FieldPointer(ins) - if ins.class.is_heap_allocated(&self.shared.state.db) => + if ins.type_id.is_heap_allocated(&self.shared.state.db) => { let reg_var = self.variables[&ins.register]; let rec_var = self.variables[&ins.receiver]; let rec_typ = self.variable_types[&ins.receiver]; - let base = if ins.class.kind(&self.shared.state.db).is_async() { + let base = if ins.type_id.kind(&self.shared.state.db).is_async() + { PROCESS_FIELD_OFFSET } else { FIELD_OFFSET @@ -2332,7 +2334,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let index = (base + ins.field.index(&self.shared.state.db)) as u32; - let layout = self.layouts.instances[ins.class.0 as usize]; + let layout = self.layouts.instances[ins.type_id.0 as usize]; let rec = self.builder.load(rec_typ, rec_var); let addr = self.builder.field_address( layout, @@ -2346,7 +2348,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { let reg_var = self.variables[&ins.register]; let rec_var = self.variables[&ins.receiver]; let rec_typ = self.variable_types[&ins.receiver]; - let layout = self.layouts.instances[ins.class.0 as usize]; + let layout = self.layouts.instances[ins.type_id.0 as usize]; let rec = self.builder.load(rec_typ, rec_var); let index = ins.field.index(&self.shared.state.db) as u32; let src = if rec_typ.is_pointer_type() { @@ -2465,7 +2467,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { self.builder.branch(is_zero, drop_block, after_block); } Instruction::Allocate(ins) - if ins.class.is_stack_allocated(&self.shared.state.db) => + if ins.type_id.is_stack_allocated(&self.shared.state.db) => { // Defining the alloca already reserves (uninitialised) memory, // so there's nothing we actually need to do here. Setting the @@ -2475,7 +2477,7 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { self.set_debug_location(ins.location); let reg_var = self.variables[&ins.register]; - let ptr = self.allocate(ins.class).as_basic_value_enum(); + let ptr = self.allocate(ins.type_id).as_basic_value_enum(); self.builder.store(reg_var, ptr); } @@ -2483,13 +2485,14 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { self.set_debug_location(ins.location); let reg_var = self.variables[&ins.register]; - let name = &self.shared.names.classes[&ins.class]; - let global = self.module.add_class(name).as_pointer_value(); - let class = self.builder.load_pointer(global).into(); + let name = &self.shared.names.types[&ins.type_id]; + let global = self.module.add_type(name).as_pointer_value(); + let proc_type = self.builder.load_pointer(global).into(); let proc = self.load_process().into(); let func = self.module.runtime_function(RuntimeFunction::ProcessNew); - let ptr = self.builder.call_with_return(func, &[proc, class]); + let ptr = + self.builder.call_with_return(func, &[proc, proc_type]); self.builder.store(reg_var, ptr); } @@ -2896,12 +2899,12 @@ impl<'shared, 'module, 'ctx> LowerMethod<'shared, 'module, 'ctx> { .into_int_value() } - fn allocate(&mut self, class: ClassId) -> PointerValue<'ctx> { + fn allocate(&mut self, type_id: TypeId) -> PointerValue<'ctx> { self.builder.allocate_instance( self.module, &self.shared.state.db, self.shared.names, - class, + type_id, ) } } @@ -2957,8 +2960,8 @@ impl<'a, 'ctx> GenerateMain<'a, 'ctx> { let layout = self.layouts.method_counts; let counts = self.builder.new_temporary(layout); - self.set_method_count(counts, ClassId::string()); - self.set_method_count(counts, ClassId::byte_array()); + self.set_method_count(counts, TypeId::string()); + self.set_method_count(counts, TypeId::byte_array()); let rt_new = self.module.runtime_function(RuntimeFunction::RuntimeNew); let rt_start = @@ -3017,20 +3020,20 @@ impl<'a, 'ctx> GenerateMain<'a, 'ctx> { self.builder.store(stack_size_global.as_pointer_value(), stack_size); - // Allocate and store all the classes in their corresponding globals. + // Allocate and store all the types in their corresponding globals. // We iterate over the values here and below such that the order is // stable between compilations. This doesn't matter for the code that we // generate here, but it makes it easier to inspect the resulting // executable (e.g. using `objdump --disassemble`). for module in self.mir.modules.values() { - let name = &self.names.setup_classes[&module.id]; + let name = &self.names.setup_types[&module.id]; let func = self.module.add_setup_function(name); self.builder.direct_call(func, &[]); } // Constants need to be defined in a separate pass, as they may depends - // on the classes (e.g. array constants need the Array class to be set + // on the types (e.g. array constants need the Array type to be set // up). for module in self.mir.modules.values() { let name = &self.names.setup_constants[&module.id]; @@ -3039,11 +3042,11 @@ impl<'a, 'ctx> GenerateMain<'a, 'ctx> { self.builder.direct_call(func, &[]); } - let main_class_id = self.db.main_class().unwrap(); + let main_tid = self.db.main_type().unwrap(); let main_method_id = self.db.main_method().unwrap(); - let main_class_ptr = self + let main_type_ptr = self .module - .add_global_pointer(&self.names.classes[&main_class_id]) + .add_global_pointer(&self.names.types[&main_tid]) .as_pointer_value(); let main_method = self @@ -3059,16 +3062,16 @@ impl<'a, 'ctx> GenerateMain<'a, 'ctx> { .as_global_value() .as_pointer_value(); - let main_class = self.builder.load_pointer(main_class_ptr); + let main_type = self.builder.load_pointer(main_type_ptr); self.builder.direct_call( rt_start, - &[runtime.into(), main_class.into(), main_method.into()], + &[runtime.into(), main_type.into(), main_method.into()], ); // We'll only reach this code upon successfully finishing the program. // - // We don't drop the classes and other data as there's no point since + // We don't drop the types and other data as there's no point since // we're exiting here. We _do_ drop the runtime in case we want to hook // any additional logic into that step at some point, though technically // this isn't necessary. @@ -3076,14 +3079,14 @@ impl<'a, 'ctx> GenerateMain<'a, 'ctx> { self.builder.return_value(Some(&self.builder.u32_literal(0))); } - fn set_method_count(&self, counts: PointerValue<'ctx>, class: ClassId) { + fn set_method_count(&self, counts: PointerValue<'ctx>, type_id: TypeId) { let layout = self.layouts.method_counts; let count = self .module .context .i16_type() - .const_int(self.methods.counts[class.0 as usize] as _, false); + .const_int(self.methods.counts[type_id.0 as usize] as _, false); - self.builder.store_field(layout, counts, class.0, count); + self.builder.store_field(layout, counts, type_id.0, count); } } diff --git a/compiler/src/llvm/runtime_function.rs b/compiler/src/llvm/runtime_function.rs index 7293c3a3b..e6234cb88 100644 --- a/compiler/src/llvm/runtime_function.rs +++ b/compiler/src/llvm/runtime_function.rs @@ -4,8 +4,8 @@ use inkwell::values::FunctionValue; #[derive(Copy, Clone)] pub(crate) enum RuntimeFunction { ReferenceCountError, - ClassObject, - ClassProcess, + NewType, + NewProcess, ProcessFinishMessage, ProcessNew, ProcessPanic, @@ -28,8 +28,8 @@ impl RuntimeFunction { RuntimeFunction::ReferenceCountError => { "inko_reference_count_error" } - RuntimeFunction::ClassObject => "inko_class_object", - RuntimeFunction::ClassProcess => "inko_class_process", + RuntimeFunction::NewType => "inko_type_object", + RuntimeFunction::NewProcess => "inko_type_process", RuntimeFunction::ProcessFinishMessage => { "inko_process_finish_message" } @@ -98,11 +98,11 @@ impl RuntimeFunction { } RuntimeFunction::RuntimeStart => { let runtime = context.pointer_type().into(); - let class = context.pointer_type().into(); + let typ = context.pointer_type().into(); let method = context.pointer_type().into(); let ret = context.void_type(); - ret.fn_type(&[runtime, class, method], false) + ret.fn_type(&[runtime, typ, method], false) } RuntimeFunction::RuntimeState => { let runtime = context.pointer_type().into(); @@ -110,7 +110,7 @@ impl RuntimeFunction { ret.fn_type(&[runtime], false) } - RuntimeFunction::ClassObject | RuntimeFunction::ClassProcess => { + RuntimeFunction::NewType | RuntimeFunction::NewProcess => { let name = context.pointer_type().into(); let size = context.i32_type().into(); let methods = context.i16_type().into(); @@ -130,10 +130,10 @@ impl RuntimeFunction { } RuntimeFunction::ProcessNew => { let process = context.pointer_type().into(); - let class = context.pointer_type().into(); + let typ = context.pointer_type().into(); let ret = context.pointer_type(); - ret.fn_type(&[process, class], false) + ret.fn_type(&[process, typ], false) } RuntimeFunction::StringConcat => { let state = context.pointer_type().into(); diff --git a/compiler/src/mir/inline.rs b/compiler/src/mir/inline.rs index be808c26a..6948839f4 100644 --- a/compiler/src/mir/inline.rs +++ b/compiler/src/mir/inline.rs @@ -32,7 +32,7 @@ fn instruction_weight(db: &Database, instruction: &Instruction) -> u16 { // give them a weight of zero. Regular allocations and spawning // processes translate into a function call, so we give them the same // weight as calls. - Instruction::Allocate(ins) if ins.class.is_stack_allocated(db) => 0, + Instruction::Allocate(ins) if ins.type_id.is_stack_allocated(db) => 0, Instruction::Allocate(_) => 1, Instruction::Spawn(_) => 1, diff --git a/compiler/src/mir/mod.rs b/compiler/src/mir/mod.rs index 7aed01ee4..7863ec8d9 100644 --- a/compiler/src/mir/mod.rs +++ b/compiler/src/mir/mod.rs @@ -9,7 +9,7 @@ pub(crate) mod printer; pub(crate) mod specialize; use crate::state::State; -use crate::symbol_names::{qualified_class_name, SymbolNames}; +use crate::symbol_names::{qualified_type_name, SymbolNames}; use indexmap::IndexMap; use location::Location; use std::collections::{HashMap, HashSet}; @@ -20,7 +20,7 @@ use std::ops::{Add, AddAssign, Sub, SubAssign}; use types::module_name::ModuleName; use types::{ Database, ForeignType, Intrinsic, MethodId, Module as ModuleType, Shape, - Sign, TypeArguments, TypeId, TypeRef, BOOL_ID, DROPPER_METHOD, FLOAT_ID, + Sign, TypeArguments, TypeEnum, TypeRef, BOOL_ID, DROPPER_METHOD, FLOAT_ID, INT_ID, NIL_ID, }; @@ -481,12 +481,12 @@ impl Block { pub(crate) fn free( &mut self, register: RegisterId, - class: types::ClassId, + type_id: types::TypeId, location: InstructionLocation, ) { self.instructions.push(Instruction::Free(Box::new(Free { register, - class, + type_id, location, }))); } @@ -632,12 +632,12 @@ impl Block { &mut self, register: RegisterId, receiver: RegisterId, - class: types::ClassId, + type_id: types::TypeId, field: types::FieldId, location: InstructionLocation, ) { self.instructions.push(Instruction::GetField(Box::new(GetField { - class, + type_id, register, receiver, field, @@ -648,7 +648,7 @@ impl Block { pub(crate) fn set_field( &mut self, receiver: RegisterId, - class: types::ClassId, + type_id: types::TypeId, field: types::FieldId, value: RegisterId, location: InstructionLocation, @@ -656,7 +656,7 @@ impl Block { self.instructions.push(Instruction::SetField(Box::new(SetField { receiver, value, - class, + type_id, field, location, }))); @@ -679,12 +679,12 @@ impl Block { &mut self, register: RegisterId, receiver: RegisterId, - class: types::ClassId, + type_id: types::TypeId, field: types::FieldId, location: InstructionLocation, ) { self.instructions.push(Instruction::FieldPointer(Box::new( - FieldPointer { class, register, receiver, field, location }, + FieldPointer { type_id, register, receiver, field, location }, ))); } @@ -724,12 +724,12 @@ impl Block { pub(crate) fn allocate( &mut self, register: RegisterId, - class: types::ClassId, + type_id: types::TypeId, location: InstructionLocation, ) { self.instructions.push(Instruction::Allocate(Box::new(Allocate { register, - class, + type_id, location, }))); } @@ -737,12 +737,12 @@ impl Block { pub(crate) fn spawn( &mut self, register: RegisterId, - class: types::ClassId, + type_id: types::TypeId, location: InstructionLocation, ) { self.instructions.push(Instruction::Spawn(Box::new(Spawn { register, - class, + type_id, location, }))); } @@ -995,7 +995,7 @@ pub(crate) struct CallDropper { #[derive(Clone)] pub(crate) struct Free { - pub(crate) class: types::ClassId, + pub(crate) type_id: types::TypeId, pub(crate) register: RegisterId, pub(crate) location: InstructionLocation, } @@ -1138,7 +1138,7 @@ pub(crate) struct Send { #[derive(Clone)] pub(crate) struct GetField { - pub(crate) class: types::ClassId, + pub(crate) type_id: types::TypeId, pub(crate) register: RegisterId, pub(crate) receiver: RegisterId, pub(crate) field: types::FieldId, @@ -1147,7 +1147,7 @@ pub(crate) struct GetField { #[derive(Clone)] pub(crate) struct SetField { - pub(crate) class: types::ClassId, + pub(crate) type_id: types::TypeId, pub(crate) receiver: RegisterId, pub(crate) value: RegisterId, pub(crate) field: types::FieldId, @@ -1164,14 +1164,14 @@ pub(crate) struct GetConstant { #[derive(Clone)] pub(crate) struct Allocate { pub(crate) register: RegisterId, - pub(crate) class: types::ClassId, + pub(crate) type_id: types::TypeId, pub(crate) location: InstructionLocation, } #[derive(Clone)] pub(crate) struct Spawn { pub(crate) register: RegisterId, - pub(crate) class: types::ClassId, + pub(crate) type_id: types::TypeId, pub(crate) location: InstructionLocation, } @@ -1208,26 +1208,26 @@ impl CastType { if let TypeRef::Pointer(_) = typ { CastType::Pointer } else { - match typ.type_id(db) { - Ok(TypeId::Foreign(ForeignType::Int(8, sign))) => { + match typ.as_type_enum(db) { + Ok(TypeEnum::Foreign(ForeignType::Int(8, sign))) => { CastType::Int(8, sign) } - Ok(TypeId::Foreign(ForeignType::Int(16, sign))) => { + Ok(TypeEnum::Foreign(ForeignType::Int(16, sign))) => { CastType::Int(16, sign) } - Ok(TypeId::Foreign(ForeignType::Int(32, sign))) => { + Ok(TypeEnum::Foreign(ForeignType::Int(32, sign))) => { CastType::Int(32, sign) } - Ok(TypeId::Foreign(ForeignType::Int(64, sign))) => { + Ok(TypeEnum::Foreign(ForeignType::Int(64, sign))) => { CastType::Int(64, sign) } - Ok(TypeId::Foreign(ForeignType::Float(32))) => { + Ok(TypeEnum::Foreign(ForeignType::Float(32))) => { CastType::Float(32) } - Ok(TypeId::Foreign(ForeignType::Float(64))) => { + Ok(TypeEnum::Foreign(ForeignType::Float(64))) => { CastType::Float(64) } - Ok(TypeId::ClassInstance(ins)) => match ins.instance_of().0 { + Ok(TypeEnum::TypeInstance(ins)) => match ins.instance_of().0 { BOOL_ID | NIL_ID => CastType::Int(1, Sign::Unsigned), INT_ID => CastType::Int(64, Sign::Signed), FLOAT_ID => CastType::Float(64), @@ -1255,7 +1255,7 @@ pub(crate) struct MethodPointer { #[derive(Clone)] pub(crate) struct FieldPointer { - pub(crate) class: types::ClassId, + pub(crate) type_id: types::TypeId, pub(crate) register: RegisterId, pub(crate) receiver: RegisterId, pub(crate) field: types::FieldId, @@ -1430,8 +1430,8 @@ impl Instruction { format!( "free r{} {}#{}", v.register.0, - v.class.name(db), - v.class.0 + v.type_id.name(db), + v.type_id.0 ) } Instruction::CheckRefs(ref v) => { @@ -1444,12 +1444,12 @@ impl Instruction { format!( "r{} = allocate {}#{}", v.register.0, - v.class.name(db), - v.class.0, + v.type_id.name(db), + v.type_id.0, ) } Instruction::Spawn(ref v) => { - format!("r{} = spawn {}", v.register.0, v.class.name(db)) + format!("r{} = spawn {}", v.register.0, v.type_id.name(db)) } Instruction::CallStatic(ref v) => { format!( @@ -1596,13 +1596,13 @@ impl Instruction { } } -pub(crate) struct Class { - pub(crate) id: types::ClassId, +pub(crate) struct Type { + pub(crate) id: types::TypeId, pub(crate) methods: Vec, } -impl Class { - pub(crate) fn new(id: types::ClassId) -> Self { +impl Type { + pub(crate) fn new(id: types::TypeId) -> Self { Self { id, methods: Vec::new() } } @@ -1620,7 +1620,7 @@ impl Class { #[derive(Clone)] pub(crate) struct Module { pub(crate) id: types::ModuleId, - pub(crate) classes: Vec, + pub(crate) types: Vec, pub(crate) constants: Vec, pub(crate) methods: Vec, @@ -1634,7 +1634,7 @@ impl Module { pub(crate) fn new(id: types::ModuleId) -> Self { Self { id, - classes: Vec::new(), + types: Vec::new(), constants: Vec::new(), methods: Vec::new(), inlined_methods: HashSet::new(), @@ -2010,7 +2010,7 @@ impl Method { pub(crate) struct Mir { pub(crate) constants: HashMap, pub(crate) modules: IndexMap, - pub(crate) classes: HashMap, + pub(crate) types: HashMap, pub(crate) methods: IndexMap, /// Externally defined methods/functions that are called at some point. @@ -2042,7 +2042,7 @@ impl Mir { Self { constants: HashMap::new(), modules: IndexMap::new(), - classes: HashMap::new(), + types: HashMap::new(), methods: IndexMap::new(), extern_methods: HashSet::new(), type_arguments: Vec::new(), @@ -2076,12 +2076,12 @@ impl Mir { // inconsistent order when many values share the same name. for module in self.modules.values_mut() { module.constants.sort_by_key(|i| &names.constants[i]); - module.classes.sort_by_key(|i| &names.classes[i]); + module.types.sort_by_key(|i| &names.types[i]); module.methods.sort_by_key(|i| &names.methods[i]); } - for class in self.classes.values_mut() { - class.methods.sort_by_key(|i| &names.methods[i]); + for typ in self.types.values_mut() { + typ.methods.sort_by_key(|i| &names.methods[i]); } // When populating object caches we need to be able to iterate over the @@ -2129,16 +2129,16 @@ impl Mir { let mut new_modules = Vec::new(); for old_module in self.modules.values_mut() { - let mut moved_classes = HashSet::new(); + let mut moved_types = HashSet::new(); let mut moved_methods = HashSet::new(); - for &class_id in &old_module.classes { + for &tid in &old_module.types { let file = old_module.id.file(&state.db); let orig_name = old_module.id.name(&state.db).clone(); - let name = ModuleName::new(qualified_class_name( + let name = ModuleName::new(qualified_type_name( &state.db, old_module.id, - class_id, + tid, )); let new_mod_id = ModuleType::alloc(&mut state.db, name.clone(), file); @@ -2161,8 +2161,7 @@ impl Mir { // module changes _or_ the module of the closure's `self` type, // because changes to the `self` type may affect how the closure // is generated. - if let Some(stype) = - class_id.specialization_key(&state.db).self_type + if let Some(stype) = tid.specialization_key(&state.db).self_type { let self_node = state.dependency_graph.add_module( stype.instance_of().module(&state.db).name(&state.db), @@ -2176,12 +2175,12 @@ impl Mir { let mut new_module = Module::new(new_mod_id); // We don't deal with static methods as those have their - // receiver typed as the original class ID, because they don't - // really belong to a class (i.e. they're basically scoped + // receiver typed as the original type ID, because they don't + // really belong to a type (i.e. they're basically scoped // module methods). - new_module.methods = self.classes[&class_id].methods.clone(); - new_module.classes.push(class_id); - moved_classes.insert(class_id); + new_module.methods = self.types[&tid].methods.clone(); + new_module.types.push(tid); + moved_types.insert(tid); // When generating symbol names we use the module as stored in // the method, so we need to make sure that's set to our newly @@ -2191,12 +2190,12 @@ impl Mir { moved_methods.insert(id); } - class_id.set_module(&mut state.db, new_mod_id); + tid.set_module(&mut state.db, new_mod_id); new_modules.push(new_module); } old_module.methods.retain(|id| !moved_methods.contains(id)); - old_module.classes.retain(|i| !moved_classes.contains(i)); + old_module.types.retain(|i| !moved_types.contains(i)); } for module in new_modules { @@ -2269,9 +2268,9 @@ impl Mir { // possible target methods as used, since we can't // statically determine which implementation is // called. - for &class in tid.implemented_by(db) { + for &typ in tid.implemented_by(db) { let method_impl = - class.method(db, id.name(db)).unwrap(); + typ.method(db, id.name(db)).unwrap(); let mut methods = method_impl.specializations(db); @@ -2311,7 +2310,7 @@ impl Mir { let keep = method .id .receiver(db) - .class_id(db) + .type_id(db) .map_or(false, |v| v.is_closure(db)) || used[method.id.0 as usize] || method.id.name(db) == DROPPER_METHOD; @@ -2327,8 +2326,8 @@ impl Mir { module.methods.retain(|i| !removed[i.0 as usize]); } - for class in self.classes.values_mut() { - class.methods.retain(|i| !removed[i.0 as usize]); + for typ in self.types.values_mut() { + typ.methods.retain(|i| !removed[i.0 as usize]); } } diff --git a/compiler/src/mir/passes.rs b/compiler/src/mir/passes.rs index 646c4023e..705501222 100644 --- a/compiler/src/mir/passes.rs +++ b/compiler/src/mir/passes.rs @@ -3,8 +3,8 @@ use crate::diagnostics::DiagnosticId; use crate::hir; use crate::mir::pattern_matching as pmatch; use crate::mir::{ - Block, BlockId, CastType, Class, Constant, InstructionLocation, Method, - Mir, Module, RegisterId, SELF_ID, + Block, BlockId, CastType, Constant, InstructionLocation, Method, Mir, + Module, RegisterId, Type, SELF_ID, }; use crate::state::State; use location::Location; @@ -16,10 +16,10 @@ use std::str::FromStr; use types::format::format_type; use types::module_name::ModuleName; use types::{ - self, Block as _, ClassId, ConstantId, FieldId, Inline, MethodId, ModuleId, - Symbol, TypeBounds, TypeRef, VerificationError, ENUM_TAG_INDEX, EQ_METHOD, - OPTION_NONE, OPTION_SOME, RESULT_CLASS, RESULT_ERROR, RESULT_MODULE, - RESULT_OK, + self, Block as _, ConstantId, FieldId, Inline, MethodId, ModuleId, Symbol, + TypeBounds, TypeId, TypeRef, VerificationError, ENUM_TAG_INDEX, EQ_METHOD, + OPTION_NONE, OPTION_SOME, RESULT_ERROR, RESULT_MODULE, RESULT_OK, + RESULT_TYPE, }; const SELF_NAME: &str = "self"; @@ -396,7 +396,7 @@ pub(crate) struct GenerateDropper<'a> { pub(crate) state: &'a mut State, pub(crate) mir: &'a mut Mir, pub(crate) module: ModuleId, - pub(crate) class: ClassId, + pub(crate) type_id: TypeId, pub(crate) location: Location, } @@ -404,22 +404,22 @@ impl<'a> GenerateDropper<'a> { pub(crate) fn run(mut self) { // `copy` types only contain data that's trivial to copy, so droppers // aren't necessary nor used. - if self.class.is_copy_type(&self.state.db) { + if self.type_id.is_copy_type(&self.state.db) { return; } - match self.class.kind(&self.state.db) { - types::ClassKind::Async => self.async_class(), - types::ClassKind::Enum => self.enum_class(), - _ => self.regular_class(), + match self.type_id.kind(&self.state.db) { + types::TypeKind::Async => self.async_type(), + types::TypeKind::Enum => self.enum_type(), + _ => self.regular_type(), }; } - /// Generates the dropper method for a regular class. + /// Generates the dropper method for a regular type. /// /// This version runs the destructor (if any), followed by running the /// dropper of every field. Finally, it frees the receiver. - fn regular_class(&mut self) { + fn regular_type(&mut self) { self.generate_dropper( types::DROPPER_METHOD, types::MethodKind::Mutable, @@ -428,14 +428,14 @@ impl<'a> GenerateDropper<'a> { ); } - /// Generates the dropper methods for an async class. + /// Generates the dropper methods for an async type. /// - /// Async classes are dropped asynchronously. This is achieved as follows: + /// Async types are dropped asynchronously. This is achieved as follows: /// the regular dropper simply schedules an async version of the drop glue. /// Because this only runs when removing the last reference to the process, /// the async dropper is the last message. When run, it cleans up the object - /// like a regular class, and the process shuts down. - fn async_class(&mut self) { + /// like a regular type, and the process shuts down. + fn async_type(&mut self) { let async_dropper = self.generate_dropper( types::ASYNC_DROPPER_METHOD, types::MethodKind::AsyncMutable, @@ -473,15 +473,15 @@ impl<'a> GenerateDropper<'a> { self.add_method(types::DROPPER_METHOD, dropper_type, dropper_method); } - /// Generates the dropper method for an enum class. + /// Generates the dropper method for an enum type. /// /// For enums the drop logic is a bit different: based on the value of the /// tag, certain fields may be set to NULL. As such we branch based on the /// tag value, and only drop the fields relevant for that tag. - fn enum_class(&mut self) { + fn enum_type(&mut self) { let name = types::DROPPER_METHOD; - let class = self.class; - let drop_method_opt = class.method(&self.state.db, types::DROP_METHOD); + let tid = self.type_id; + let drop_method_opt = tid.method(&self.state.db, types::DROP_METHOD); let method_type = self.method_type(name, types::MethodKind::Mutable); let mut method = Method::new(method_type); let mut lower = @@ -506,16 +506,16 @@ impl<'a> GenerateDropper<'a> { ); } - lower.each_enum_constructer_field(class, loc, |this, field, typ| { + lower.each_enum_constructer_field(tid, loc, |this, field, typ| { let reg = this.new_register(typ); - this.current_block_mut().get_field(reg, rec, class, field, loc); + this.current_block_mut().get_field(reg, rec, tid, field, loc); this.drop_register(reg, loc); }); - if class.is_heap_allocated(lower.db()) { + if tid.is_heap_allocated(lower.db()) { lower.current_block_mut().check_refs(rec, loc); - lower.current_block_mut().free(rec, class, loc); + lower.current_block_mut().free(rec, tid, loc); } let nil_reg = lower.get_nil(loc); @@ -531,7 +531,7 @@ impl<'a> GenerateDropper<'a> { free_self: bool, terminate: bool, ) -> MethodId { - let class = self.class; + let tid = self.type_id; let method_type = self.method_type(name, kind); let mut method = Method::new(method_type); let mut lower = @@ -542,7 +542,7 @@ impl<'a> GenerateDropper<'a> { let rec = lower.self_register; - if let Some(id) = class.method(lower.db(), types::DROP_METHOD) { + if let Some(id) = tid.method(lower.db(), types::DROP_METHOD) { let typ = TypeRef::nil(); let res = lower.new_register(typ); @@ -556,17 +556,17 @@ impl<'a> GenerateDropper<'a> { ); } - for field in class.fields(lower.db()).into_iter().rev() { + for field in tid.fields(lower.db()).into_iter().rev() { let typ = field.value_type(lower.db()); let reg = lower.new_register(typ); - lower.current_block_mut().get_field(reg, rec, class, field, loc); + lower.current_block_mut().get_field(reg, rec, tid, field, loc); lower.drop_register(reg, loc); } - if class.is_heap_allocated(lower.db()) && free_self { + if tid.is_heap_allocated(lower.db()) && free_self { lower.current_block_mut().check_refs(rec, loc); - lower.current_block_mut().free(rec, class, loc); + lower.current_block_mut().free(rec, tid, loc); } if terminate { @@ -594,9 +594,9 @@ impl<'a> GenerateDropper<'a> { ); let self_type = - types::TypeId::ClassInstance(types::ClassInstance::rigid( + types::TypeEnum::TypeInstance(types::TypeInstance::rigid( &mut self.state.db, - self.class, + self.type_id, &types::TypeBounds::new(), )); let receiver = TypeRef::Mut(self_type); @@ -614,10 +614,10 @@ impl<'a> GenerateDropper<'a> { } fn add_method(&mut self, name: &str, id: MethodId, method: Method) { - let cid = self.class; + let cid = self.type_id; cid.add_method(&mut self.state.db, name.to_string(), id); - self.mir.classes.get_mut(&cid).unwrap().methods.push(id); + self.mir.types.get_mut(&cid).unwrap().methods.push(id); self.mir.methods.insert(id, method); } } @@ -628,30 +628,30 @@ pub(crate) struct GenerateInlineMethods<'a> { pub(crate) state: &'a mut State, pub(crate) mir: &'a mut Mir, pub(crate) module: ModuleId, - pub(crate) class: ClassId, + pub(crate) type_id: TypeId, pub(crate) location: Location, } impl<'a> GenerateInlineMethods<'a> { pub(crate) fn run(mut self) { - match self.class.kind(&self.state.db) { - types::ClassKind::Enum => self.enum_class(), - _ => self.regular_class(), + match self.type_id.kind(&self.state.db) { + types::TypeKind::Enum => self.enum_type(), + _ => self.regular_type(), }; } - fn regular_class(&mut self) { + fn regular_type(&mut self) { self.regular_increment(); self.regular_decrement(); } - fn enum_class(&mut self) { + fn enum_type(&mut self) { self.enum_increment(); self.enum_decrement(); } fn regular_increment(&mut self) { - let cls = self.class; + let cls = self.type_id; let name = types::INCREMENT_METHOD; let mtype = self.method_type(name); let mut method = Method::new(mtype); @@ -679,7 +679,7 @@ impl<'a> GenerateInlineMethods<'a> { } fn enum_increment(&mut self) { - let cls = self.class; + let cls = self.type_id; let name = types::INCREMENT_METHOD; let mtype = self.method_type(name); let mut method = Method::new(mtype); @@ -704,7 +704,7 @@ impl<'a> GenerateInlineMethods<'a> { } fn regular_decrement(&mut self) { - let cls = self.class; + let cls = self.type_id; let name = types::DECREMENT_METHOD; let mtype = self.method_type(name); let mut method = Method::new(mtype); @@ -731,7 +731,7 @@ impl<'a> GenerateInlineMethods<'a> { } fn enum_decrement(&mut self) { - let cls = self.class; + let cls = self.type_id; let name = types::DECREMENT_METHOD; let mtype = self.method_type(name); let mut method = Method::new(mtype); @@ -765,9 +765,9 @@ impl<'a> GenerateInlineMethods<'a> { ); let self_type = - types::TypeId::ClassInstance(types::ClassInstance::rigid( + types::TypeEnum::TypeInstance(types::TypeInstance::rigid( &mut self.state.db, - self.class, + self.type_id, &types::TypeBounds::new(), )); let receiver = TypeRef::Ref(self_type); @@ -779,10 +779,10 @@ impl<'a> GenerateInlineMethods<'a> { } fn add_method(&mut self, name: &str, id: MethodId, method: Method) { - let cls = self.class; + let cls = self.type_id; cls.add_method(&mut self.state.db, name.to_string(), id); - self.mir.classes.get_mut(&cls).unwrap().methods.push(id); + self.mir.types.get_mut(&cls).unwrap().methods.push(id); self.mir.methods.insert(id, method); } } @@ -1001,15 +1001,15 @@ impl<'a> LowerToMir<'a> { let mut mod_types = Vec::new(); let mut mod_nodes = Vec::new(); - // Traits and classes must be lowered first, so we can process + // Traits and types must be lowered first, so we can process // implementations later. for module in nodes { let (types, rest) = module.expressions.into_iter().partition(|v| { matches!( v, hir::TopLevelExpression::Trait(_) - | hir::TopLevelExpression::Class(_) - | hir::TopLevelExpression::ExternClass(_) + | hir::TopLevelExpression::Type(_) + | hir::TopLevelExpression::ExternType(_) ) }); @@ -1038,11 +1038,11 @@ impl<'a> LowerToMir<'a> { hir::TopLevelExpression::Trait(n) => { self.define_trait(*n); } - hir::TopLevelExpression::Class(n) => { - self.define_class(*n); + hir::TopLevelExpression::Type(n) => { + self.define_type(*n); } - hir::TopLevelExpression::ExternClass(n) => { - self.define_extern_class(*n); + hir::TopLevelExpression::ExternType(n) => { + self.define_extern_type(*n); } _ => {} } @@ -1072,18 +1072,18 @@ impl<'a> LowerToMir<'a> { self.implement_trait(*n); } hir::TopLevelExpression::Reopen(n) => { - self.reopen_class(*n); + self.reopen_type(*n); } _ => {} } } - let mod_class_id = id.class(self.db()); - let mut mod_class = Class::new(mod_class_id); + let mod_type_id = id.type_id(self.db()); + let mut mod_type = Type::new(mod_type_id); - mod_class.add_methods(&mod_methods); + mod_type.add_methods(&mod_methods); self.mir.add_methods(mod_methods); - self.add_class(mod_class_id, mod_class); + self.add_type(mod_type_id, mod_type); } fn define_trait(&mut self, node: hir::DefineTrait) { @@ -1099,7 +1099,7 @@ impl<'a> LowerToMir<'a> { } fn implement_trait(&mut self, node: hir::ImplementTrait) { - let class_id = node.class_instance.unwrap().instance_of(); + let type_id = node.type_instance.unwrap().instance_of(); let trait_id = node.trait_instance.unwrap().instance_of(); let mut methods = Vec::new(); let mut names = HashSet::new(); @@ -1115,47 +1115,47 @@ impl<'a> LowerToMir<'a> { if !names.contains(id.name(self.db())) { let mut method = self.mir.methods.get(&id).unwrap().clone(); - // We need to make sure to use the ID of the class' + // We need to make sure to use the ID of the type's // implementation of the method, rather than the ID of the // method as defined in its source trait. method.id = - class_id.method(self.db(), id.name(self.db())).unwrap(); + type_id.method(self.db(), id.name(self.db())).unwrap(); methods.push(method); } } - self.mir.classes.get_mut(&class_id).unwrap().add_methods(&methods); + self.mir.types.get_mut(&type_id).unwrap().add_methods(&methods); self.mir.add_methods(methods); } - fn define_class(&mut self, node: hir::DefineClass) { - let id = node.class_id.unwrap(); + fn define_type(&mut self, node: hir::DefineType) { + let id = node.type_id.unwrap(); let mut methods = Vec::new(); for expr in node.body { match expr { - hir::ClassExpression::InstanceMethod(n) => { + hir::TypeExpression::InstanceMethod(n) => { methods.push(self.define_instance_method(*n)); } - hir::ClassExpression::StaticMethod(n) => { + hir::TypeExpression::StaticMethod(n) => { self.define_static_method(*n); } - hir::ClassExpression::AsyncMethod(n) => { + hir::TypeExpression::AsyncMethod(n) => { methods.push(self.define_async_method(*n)); } - hir::ClassExpression::Constructor(n) => { + hir::TypeExpression::Constructor(n) => { methods.push(self.define_constructor_method(*n, id)); } _ => {} } } - let mut class = Class::new(id); + let mut typ = Type::new(id); - class.add_methods(&methods); + typ.add_methods(&methods); self.mir.add_methods(methods); - self.add_class(id, class); + self.add_type(id, typ); let loc = node.location; @@ -1163,45 +1163,46 @@ impl<'a> LowerToMir<'a> { let mir = &mut self.mir; let module = self.module; - GenerateDropper { state, mir, module, class: id, location: loc }.run(); + GenerateDropper { state, mir, module, type_id: id, location: loc } + .run(); if id.is_inline_type(&state.db) { GenerateInlineMethods { state, mir, module, - class: id, + type_id: id, location: loc, } .run(); } } - fn define_extern_class(&mut self, node: hir::DefineExternClass) { - let id = node.class_id.unwrap(); + fn define_extern_type(&mut self, node: hir::DefineExternType) { + let id = node.type_id.unwrap(); - self.add_class(id, Class::new(id)); + self.add_type(id, Type::new(id)); } - fn reopen_class(&mut self, node: hir::ReopenClass) { - let id = node.class_id.unwrap(); + fn reopen_type(&mut self, node: hir::ReopenType) { + let id = node.type_id.unwrap(); let mut methods = Vec::new(); for expr in node.body { match expr { - hir::ReopenClassExpression::InstanceMethod(n) => { + hir::ReopenTypeExpression::InstanceMethod(n) => { methods.push(self.define_instance_method(*n)); } - hir::ReopenClassExpression::StaticMethod(n) => { + hir::ReopenTypeExpression::StaticMethod(n) => { self.define_static_method(*n); } - hir::ReopenClassExpression::AsyncMethod(n) => { + hir::ReopenTypeExpression::AsyncMethod(n) => { methods.push(self.define_async_method(*n)); } } } - self.mir.classes.get_mut(&id).unwrap().add_methods(&methods); + self.mir.types.get_mut(&id).unwrap().add_methods(&methods); self.mir.add_methods(methods); } @@ -1258,15 +1259,15 @@ impl<'a> LowerToMir<'a> { fn define_constructor_method( &mut self, node: hir::DefineConstructor, - class: types::ClassId, + type_id: types::TypeId, ) -> Method { let id = node.method_id.unwrap(); let constructor_id = node.constructor_id.unwrap(); let mut method = Method::new(id); - let fields = class.enum_fields(self.db()); + let fields = type_id.enum_fields(self.db()); let bounds = TypeBounds::new(); - let ins = TypeRef::Owned(types::TypeId::ClassInstance( - types::ClassInstance::rigid(self.db_mut(), class, &bounds), + let ins = TypeRef::Owned(types::TypeEnum::TypeInstance( + types::TypeInstance::rigid(self.db_mut(), type_id, &bounds), )); let mut lower = LowerMethod::new(self.state, self.mir, self.module, &mut method); @@ -1277,14 +1278,14 @@ impl<'a> LowerToMir<'a> { let ins_reg = lower.new_register(ins); let tag_val = constructor_id.id(lower.db()); let tag_field = - class.field_by_index(lower.db(), ENUM_TAG_INDEX).unwrap(); + type_id.field_by_index(lower.db(), ENUM_TAG_INDEX).unwrap(); let tag_reg = lower.new_register(tag_field.value_type(lower.db())); - lower.current_block_mut().allocate(ins_reg, class, loc); + lower.current_block_mut().allocate(ins_reg, type_id, loc); lower.current_block_mut().u16_literal(tag_reg, tag_val, loc); lower .current_block_mut() - .set_field(ins_reg, class, tag_field, tag_reg, loc); + .set_field(ins_reg, type_id, tag_field, tag_reg, loc); for (arg, field) in id.arguments(lower.db()).into_iter().zip(fields.into_iter()) @@ -1293,7 +1294,7 @@ impl<'a> LowerToMir<'a> { lower .current_block_mut() - .set_field(ins_reg, class, field, reg, loc); + .set_field(ins_reg, type_id, field, reg, loc); lower.mark_register_as_moved(reg); } @@ -1310,11 +1311,11 @@ impl<'a> LowerToMir<'a> { &mut self.state.db } - fn add_class(&mut self, id: types::ClassId, class: Class) { + fn add_type(&mut self, id: types::TypeId, typ: Type) { let mod_id = self.module; - self.mir.classes.insert(id, class); - self.mir.modules.get_mut(&mod_id).unwrap().classes.push(id); + self.mir.types.insert(id, typ); + self.mir.modules.get_mut(&mod_id).unwrap().types.push(id); } } @@ -1548,10 +1549,10 @@ impl<'a> LowerMethod<'a> { // the closure itself. let captured = self.field_register(field, field_type, location); let closure = self.surrounding_type_register; - let class = self.register_type(closure).class_id(self.db()).unwrap(); + let tid = self.register_type(closure).type_id(self.db()).unwrap(); self.current_block_mut() - .get_field(captured, closure, class, field, location); + .get_field(captured, closure, tid, field, location); self.self_register = captured; } @@ -1810,7 +1811,7 @@ impl<'a> LowerMethod<'a> { self.check_inferred(node.resolved_type, node.location); let tup = self.new_register(node.resolved_type); - let id = node.class_id.unwrap(); + let id = node.type_id.unwrap(); let loc = InstructionLocation::new(node.location); let fields = id.fields(self.db()); @@ -1942,11 +1943,21 @@ impl<'a> LowerMethod<'a> { let reg = self.new_register(typ); if info.as_pointer { - self.current_block_mut() - .field_pointer(reg, rec, info.class, info.id, loc); + self.current_block_mut().field_pointer( + reg, + rec, + info.type_id, + info.id, + loc, + ); } else { - self.current_block_mut() - .get_field(reg, rec, info.class, info.id, loc); + self.current_block_mut().get_field( + reg, + rec, + info.type_id, + info.id, + loc, + ); } // When returning a field using the syntax `x.y`, we _must_ copy @@ -2002,16 +2013,16 @@ impl<'a> LowerMethod<'a> { self.get_constant(reg, id, loc); reg } - types::CallKind::ClassInstance(info) => { + types::CallKind::TypeInstance(info) => { self.check_inferred(info.resolved_type, node.location); let ins = self.new_register(info.resolved_type); - let class = info.class_id; + let tid = info.type_id; - if class.kind(self.db()).is_async() { - self.current_block_mut().spawn(ins, class, loc); + if tid.kind(self.db()).is_async() { + self.current_block_mut().spawn(ins, tid, loc); } else { - self.current_block_mut().allocate(ins, class, loc); + self.current_block_mut().allocate(ins, tid, loc); } for (arg, (id, exp)) in @@ -2021,8 +2032,7 @@ impl<'a> LowerMethod<'a> { let val = self.input_expression(arg.into_value(), Some(exp)); - self.current_block_mut() - .set_field(ins, class, id, val, loc); + self.current_block_mut().set_field(ins, tid, id, val, loc); } ins @@ -2074,7 +2084,7 @@ impl<'a> LowerMethod<'a> { return result; } - types::Receiver::Class => { + types::Receiver::Type => { let arg_regs = self.call_arguments(info.id, arguments); let targs = self.mir.add_type_arguments(info.type_arguments); let result = self.new_register(info.returns); @@ -2234,13 +2244,23 @@ impl<'a> LowerMethod<'a> { let old = self.new_register(info.variable_type); if !info.variable_type.is_copy_type(self.db()) { - self.current_block_mut() - .get_field(old, rec, info.class, info.id, loc); + self.current_block_mut().get_field( + old, + rec, + info.type_id, + info.id, + loc, + ); self.drop_register(old, loc); } - self.current_block_mut() - .set_field(rec, info.class, info.id, arg, loc); + self.current_block_mut().set_field( + rec, + info.type_id, + info.id, + arg, + loc, + ); self.get_nil(loc) } types::CallKind::WritePointer => { @@ -2264,10 +2284,10 @@ impl<'a> LowerMethod<'a> { let new_val = self.input_expression(node.value, Some(exp)); let old_val = self.new_register(exp); let rec = self.expression(node.receiver); - let class = self.register_type(rec).class_id(self.db()).unwrap(); + let tid = self.register_type(rec).type_id(self.db()).unwrap(); - self.current_block_mut().get_field(old_val, rec, class, id, loc); - self.current_block_mut().set_field(rec, class, id, new_val, loc); + self.current_block_mut().get_field(old_val, rec, tid, id, loc); + self.current_block_mut().set_field(rec, tid, id, new_val, loc); old_val } @@ -2287,7 +2307,7 @@ impl<'a> LowerMethod<'a> { } else { let &field = self.variable_fields.get(&id).unwrap(); let rec = self.surrounding_type_register; - let class = self.register_type(rec).class_id(self.db()).unwrap(); + let tid = self.register_type(rec).type_id(self.db()).unwrap(); if !exp.is_copy_type(self.db()) { // The captured variable may be exposed as a reference in `reg`, @@ -2295,11 +2315,11 @@ impl<'a> LowerMethod<'a> { // it. let old = self.new_register(exp); - self.current_block_mut().get_field(old, rec, class, field, loc); + self.current_block_mut().get_field(old, rec, tid, field, loc); self.drop_register(old, loc); } - self.current_block_mut().set_field(rec, class, field, val, loc); + self.current_block_mut().set_field(rec, tid, field, val, loc); } self.get_nil(loc) @@ -2324,10 +2344,10 @@ impl<'a> LowerMethod<'a> { } else { let &field = self.variable_fields.get(&id).unwrap(); let rec = self.surrounding_type_register; - let class = self.register_type(rec).class_id(self.db()).unwrap(); + let tid = self.register_type(rec).type_id(self.db()).unwrap(); - self.current_block_mut().get_field(old_val, rec, class, field, loc); - self.current_block_mut().set_field(rec, class, field, new_val, loc); + self.current_block_mut().get_field(old_val, rec, tid, field, loc); + self.current_block_mut().set_field(rec, tid, field, new_val, loc); } old_val @@ -2341,7 +2361,7 @@ impl<'a> LowerMethod<'a> { if let Some(®) = self.field_mapping.get(&id) { let rec = self.surrounding_type_register; - let class = self.register_type(rec).class_id(self.db()).unwrap(); + let tid = self.register_type(rec).type_id(self.db()).unwrap(); let is_moved = self.register_is_moved(reg); if !is_moved && !exp.is_copy_type(self.db()) { @@ -2350,7 +2370,7 @@ impl<'a> LowerMethod<'a> { // instead. let old = self.new_register(exp); - self.current_block_mut().get_field(old, rec, class, id, loc); + self.current_block_mut().get_field(old, rec, tid, id, loc); self.drop_register(old, loc); } @@ -2365,21 +2385,21 @@ impl<'a> LowerMethod<'a> { } self.update_register_state(reg, RegisterState::Available); - self.current_block_mut().set_field(rec, class, id, new_val, loc); + self.current_block_mut().set_field(rec, tid, id, new_val, loc); } else { let rec = self.self_register; - let class = self.register_type(rec).class_id(self.db()).unwrap(); + let tid = self.register_type(rec).type_id(self.db()).unwrap(); if !exp.is_copy_type(self.db()) { let old = self.new_register(exp); // Closures capture `self` as a whole, so we can't end up with a // case where we try to drop an already dropped value here. - self.current_block_mut().get_field(old, rec, class, id, loc); + self.current_block_mut().get_field(old, rec, tid, id, loc); self.drop_register(old, loc); } - self.current_block_mut().set_field(rec, class, id, new_val, loc); + self.current_block_mut().set_field(rec, tid, id, new_val, loc); }; self.get_nil(loc) @@ -2396,11 +2416,11 @@ impl<'a> LowerMethod<'a> { } else { (self.self_register, self.self_register) }; - let class = self.register_type(rec).class_id(self.db()).unwrap(); + let tid = self.register_type(rec).type_id(self.db()).unwrap(); self.check_if_moved(check_reg, &node.field.name, node.field.location); - self.current_block_mut().get_field(old_val, rec, class, id, loc); - self.current_block_mut().set_field(rec, class, id, new_val, loc); + self.current_block_mut().get_field(old_val, rec, tid, id, loc); + self.current_block_mut().set_field(rec, tid, id, new_val, loc); old_val } @@ -2458,12 +2478,11 @@ impl<'a> LowerMethod<'a> { fn try_expression(&mut self, node: hir::Try) -> RegisterId { let loc = InstructionLocation::new(node.location); let reg = self.expression(node.expression); - let class = self.register_type(reg).class_id(self.db()).unwrap(); - let tag_field = - class.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); + let tid = self.register_type(reg).type_id(self.db()).unwrap(); + let tag_field = tid.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); let tag_typ = tag_field.value_type(self.db()); let tag_reg = self.new_untracked_register(tag_typ); - let val_field = class.enum_fields(self.db())[0]; + let val_field = tid.enum_fields(self.db())[0]; let ok_block = self.add_block(); let err_block = self.add_block(); let after_block = self.add_block(); @@ -2476,15 +2495,15 @@ impl<'a> LowerMethod<'a> { self.add_edge(ok_block, after_block); self.mark_register_as_moved(reg); - self.current_block_mut().get_field(tag_reg, reg, class, tag_field, loc); + self.current_block_mut().get_field(tag_reg, reg, tid, tag_field, loc); let out_reg = match node.kind { types::ThrowKind::Option(typ) => { - let some_id = class + let some_id = tid .constructor(self.db(), OPTION_SOME) .unwrap() .id(self.db()); - let none_id = class + let none_id = tid .constructor(self.db(), OPTION_NONE) .unwrap() .id(self.db()); @@ -2497,17 +2516,17 @@ impl<'a> LowerMethod<'a> { // The block to jump to for a Some. self.block_mut(ok_block) - .get_field(ok_reg, reg, class, val_field, loc); + .get_field(ok_reg, reg, tid, val_field, loc); self.block_mut(ok_block).drop_without_dropper(reg, loc); self.block_mut(ok_block).goto(after_block, loc); // The block to jump to for a None self.current_block = err_block; - self.current_block_mut().allocate(ret_reg, class, loc); + self.current_block_mut().allocate(ret_reg, tid, loc); self.current_block_mut().u16_literal(err_tag, none_id, loc); self.current_block_mut() - .set_field(ret_reg, class, tag_field, err_tag, loc); + .set_field(ret_reg, tid, tag_field, err_tag, loc); self.current_block_mut().drop_without_dropper(reg, loc); self.drop_all_registers(loc); @@ -2515,11 +2534,11 @@ impl<'a> LowerMethod<'a> { ok_reg } types::ThrowKind::Result(ok_typ, err_typ) => { - let ok_id = class + let ok_id = tid .constructor(self.db(), RESULT_OK) .unwrap() .id(self.db()); - let err_id = class + let err_id = tid .constructor(self.db(), RESULT_ERROR) .unwrap() .id(self.db()); @@ -2533,21 +2552,21 @@ impl<'a> LowerMethod<'a> { // The block to jump to for an Ok. self.block_mut(ok_block) - .get_field(ok_reg, reg, class, val_field, loc); + .get_field(ok_reg, reg, tid, val_field, loc); self.block_mut(ok_block).drop_without_dropper(reg, loc); self.block_mut(ok_block).goto(after_block, loc); // The block to jump to for an Error. self.current_block = err_block; - self.current_block_mut().allocate(ret_reg, class, loc); + self.current_block_mut().allocate(ret_reg, tid, loc); self.current_block_mut().u16_literal(err_tag, err_id, loc); self.current_block_mut() - .get_field(err_val, reg, class, val_field, loc); + .get_field(err_val, reg, tid, val_field, loc); self.current_block_mut() - .set_field(ret_reg, class, tag_field, err_tag, loc); + .set_field(ret_reg, tid, tag_field, err_tag, loc); self.current_block_mut() - .set_field(ret_reg, class, val_field, err_val, loc); + .set_field(ret_reg, tid, val_field, err_val, loc); self.current_block_mut().drop_without_dropper(reg, loc); self.drop_all_registers(loc); @@ -2573,21 +2592,20 @@ impl<'a> LowerMethod<'a> { fn throw_expression(&mut self, node: hir::Throw) -> RegisterId { let loc = InstructionLocation::new(node.location); let reg = self.expression(node.value); - let class = self.db().class_in_module(RESULT_MODULE, RESULT_CLASS); + let tid = self.db().type_in_module(RESULT_MODULE, RESULT_TYPE); let err_id = - class.constructor(self.db(), RESULT_ERROR).unwrap().id(self.db()); - let tag_field = - class.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); + tid.constructor(self.db(), RESULT_ERROR).unwrap().id(self.db()); + let tag_field = tid.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); let tag_reg = self.new_register(tag_field.value_type(self.db())); - let val_field = class.enum_fields(self.db())[0]; + let val_field = tid.enum_fields(self.db())[0]; let result_reg = self.new_register(node.return_type); - self.current_block_mut().allocate(result_reg, class, loc); + self.current_block_mut().allocate(result_reg, tid, loc); self.current_block_mut().u16_literal(tag_reg, err_id, loc); self.current_block_mut() - .set_field(result_reg, class, tag_field, tag_reg, loc); + .set_field(result_reg, tid, tag_field, tag_reg, loc); self.current_block_mut() - .set_field(result_reg, class, val_field, reg, loc); + .set_field(result_reg, tid, val_field, reg, loc); self.mark_register_as_moved(reg); self.mark_register_as_moved(result_reg); @@ -2950,7 +2968,7 @@ impl<'a> LowerMethod<'a> { registers, ), pmatch::Constructor::Tuple(_) - | pmatch::Constructor::Class(_) => self.class_patterns( + | pmatch::Constructor::Class(_) => self.type_patterns( state, test, cases, @@ -3235,7 +3253,7 @@ impl<'a> LowerMethod<'a> { let fail_block = blocks.get(index + 1).cloned().unwrap_or(fallback); let res_reg = self.new_untracked_register(TypeRef::boolean()); let val_reg = self.new_untracked_register(TypeRef::string()); - let eq_method = ClassId::string() + let eq_method = TypeId::string() .method(self.db(), EQ_METHOD) .expect("String.== is undefined"); @@ -3318,7 +3336,7 @@ impl<'a> LowerMethod<'a> { blocks[0] } - fn class_patterns( + fn type_patterns( &mut self, state: &mut DecisionState, test_reg: RegisterId, @@ -3336,7 +3354,7 @@ impl<'a> LowerMethod<'a> { let test_type = self.register_type(test_reg); let owned = test_type.is_owned_or_uni(self.db()); - let class = self.register_type(test_reg).class_id(self.db()).unwrap(); + let tid = self.register_type(test_reg).type_id(self.db()).unwrap(); registers.push(test_reg); @@ -3350,7 +3368,7 @@ impl<'a> LowerMethod<'a> { state.load_child(reg, test_reg, action); self.block_mut(parent_block) - .get_field(reg, test_reg, class, field, loc); + .get_field(reg, test_reg, tid, field, loc); } self.decision(state, case.node, parent_block, registers) @@ -3372,12 +3390,11 @@ impl<'a> LowerMethod<'a> { registers.push(test_reg); let test_type = self.register_type(test_reg); - let class = test_type.class_id(self.db()).unwrap(); - let tag_field = - class.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); + let tid = test_type.type_id(self.db()).unwrap(); + let tag_field = tid.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); let tag_reg = self.new_untracked_register(tag_field.value_type(self.db())); - let member_fields = class.enum_fields(self.db()); + let member_fields = tid.enum_fields(self.db()); for case in cases { let case_registers = registers.clone(); @@ -3396,15 +3413,14 @@ impl<'a> LowerMethod<'a> { }; state.load_child(reg, test_reg, action); - self.block_mut(block) - .get_field(reg, test_reg, class, field, loc); + self.block_mut(block).get_field(reg, test_reg, tid, field, loc); } self.decision(state, case.node, block, case_registers); } self.block_mut(test_block) - .get_field(tag_reg, test_reg, class, tag_field, loc); + .get_field(tag_reg, test_reg, tid, tag_field, loc); self.block_mut(test_block).switch(tag_reg, blocks, loc); test_block } @@ -3445,7 +3461,7 @@ impl<'a> LowerMethod<'a> { }; let rec = self.self_register; - let class = info.class; + let tid = info.type_id; let name = &node.name; let check_loc = node.location; @@ -3463,9 +3479,9 @@ impl<'a> LowerMethod<'a> { } if info.as_pointer { - self.current_block_mut().field_pointer(reg, rec, class, id, loc); + self.current_block_mut().field_pointer(reg, rec, tid, id, loc); } else { - self.current_block_mut().get_field(reg, rec, class, id, loc); + self.current_block_mut().get_field(reg, rec, tid, id, loc); } reg @@ -3507,10 +3523,10 @@ impl<'a> LowerMethod<'a> { let closure_id = node.closure_id.unwrap(); let moving = closure_id.is_moving(self.db()); let loc = node.location; - let class_id = types::Class::alloc( + let tid = types::Type::alloc( self.db_mut(), "".to_string(), - types::ClassKind::Closure, + types::TypeKind::Closure, types::Visibility::Private, module, loc, @@ -3525,10 +3541,10 @@ impl<'a> LowerMethod<'a> { types::MethodKind::Mutable, ); - let gen_class_ins = - types::TypeId::ClassInstance(types::ClassInstance::new(class_id)); + let gen_type_ins = + types::TypeEnum::TypeInstance(types::TypeInstance::new(tid)); - let call_rec_type = TypeRef::Mut(gen_class_ins); + let call_rec_type = TypeRef::Mut(gen_type_ins); let returns = closure_id.return_type(self.db()); method_id.set_receiver(self.db_mut(), call_rec_type); @@ -3542,21 +3558,21 @@ impl<'a> LowerMethod<'a> { method_id.add_argument(self.db_mut(), arg); } - class_id.add_method( + tid.add_method( self.db_mut(), types::CALL_METHOD.to_string(), method_id, ); - let gen_class_type = TypeRef::Owned(gen_class_ins); - let gen_class_reg = self.new_register(gen_class_type); + let gen_type_ref = TypeRef::Owned(gen_type_ins); + let gen_type_reg = self.new_register(gen_type_ref); let loc = node.location; let ins_loc = InstructionLocation::new(loc); // We generate the allocation first, that way when we generate any // fields we can populate then right away, without having to store field // IDs. - self.current_block_mut().allocate(gen_class_reg, class_id, ins_loc); + self.current_block_mut().allocate(gen_type_reg, tid, ins_loc); let mut field_index = 0; let field_vis = types::Visibility::TypePrivate; @@ -3576,8 +3592,8 @@ impl<'a> LowerMethod<'a> { }; let name = SELF_NAME.to_string(); - let field_loc = class_id.location(self.db()); - let field = class_id.new_field( + let field_loc = tid.location(self.db()); + let field = tid.new_field( self.db_mut(), name.clone(), field_index, @@ -3600,8 +3616,8 @@ impl<'a> LowerMethod<'a> { let val = self.input_register(self_reg, captured_as, None, loc); self.current_block_mut().set_field( - gen_class_reg, - class_id, + gen_type_reg, + tid, field, val, ins_loc, @@ -3614,8 +3630,8 @@ impl<'a> LowerMethod<'a> { for (var, captured_as) in closure_id.captured(self.db()) { let name = var.name(self.db()).clone(); - let field_loc = class_id.location(self.db()); - let field = class_id.new_field( + let field_loc = tid.location(self.db()); + let field = tid.new_field( self.db_mut(), name.clone(), field_index, @@ -3635,7 +3651,7 @@ impl<'a> LowerMethod<'a> { ); } - // If the value is an external class, it's always captured as a + // If the value is an external type, it's always captured as a // pointer to the data. This is useful when dealing with FFI code // where a closure is used to mutate a C structure (e.g. as part of // a loop) in-place. @@ -3651,8 +3667,8 @@ impl<'a> LowerMethod<'a> { }; self.current_block_mut().set_field( - gen_class_reg, - class_id, + gen_type_reg, + tid, field, val, ins_loc, @@ -3664,7 +3680,7 @@ impl<'a> LowerMethod<'a> { variable_fields.insert(var, field); } - let mut mir_class = Class::new(class_id); + let mut mir_type = Type::new(tid); let mut mir_method = Method::new(method_id); let mut lower = LowerMethod::new( self.state, @@ -3683,10 +3699,10 @@ impl<'a> LowerMethod<'a> { let mod_id = self.module; - mir_class.methods.push(method_id); + mir_type.methods.push(method_id); self.mir.methods.insert(method_id, mir_method); - self.mir.classes.insert(class_id, mir_class); - self.mir.modules.get_mut(&mod_id).unwrap().classes.push(class_id); + self.mir.types.insert(tid, mir_type); + self.mir.modules.get_mut(&mod_id).unwrap().types.push(tid); let loc = node.location; @@ -3694,12 +3710,12 @@ impl<'a> LowerMethod<'a> { state: self.state, mir: self.mir, module: self.module, - class: class_id, + type_id: tid, location: loc, } .run(); - gen_class_reg + gen_type_reg } fn get_local( @@ -3715,10 +3731,9 @@ impl<'a> LowerMethod<'a> { let &field = self.variable_fields.get(&id).unwrap(); let ® = self.field_mapping.get(&field).unwrap(); let rec = self.surrounding_type_register; - let class = self.register_type(rec).class_id(self.db()).unwrap(); + let tid = self.register_type(rec).type_id(self.db()).unwrap(); - self.current_block_mut() - .get_field(reg, rec, class, field, location); + self.current_block_mut().get_field(reg, rec, tid, field, location); reg } } @@ -4019,9 +4034,9 @@ impl<'a> LowerMethod<'a> { } let reg = self.new_register(typ); - let class = typ.class_id(self.db()).unwrap(); + let tid = typ.type_id(self.db()).unwrap(); - if class.is_atomic(self.db()) { + if tid.is_atomic(self.db()) { self.current_block_mut().increment_atomic(source, location); } @@ -4288,10 +4303,10 @@ impl<'a> LowerMethod<'a> { register: RegisterId, location: InstructionLocation, ) { - let class = self.register_type(receiver).class_id(self.db()).unwrap(); + let tid = self.register_type(receiver).type_id(self.db()).unwrap(); self.current_block_mut() - .get_field(register, receiver, class, field, location); + .get_field(register, receiver, tid, field, location); self.unconditional_drop_register(register, location); } @@ -4573,7 +4588,7 @@ impl<'a> LowerMethod<'a> { self.module.file(&self.state.db) } - fn self_type(&self) -> types::TypeId { + fn self_type(&self) -> types::TypeEnum { self.method.id.receiver_id(self.db()) } @@ -4654,18 +4669,18 @@ impl<'a> LowerMethod<'a> { F: FnMut(&mut LowerMethod, FieldId, TypeRef), >( &mut self, - class: ClassId, + type_id: TypeId, location: InstructionLocation, mut func: F, ) { let rec = self.self_register; - let cons = class.constructors(self.db()); + let cons = type_id.constructors(self.db()); let mut blocks = Vec::new(); let before = self.current_block; let after = self.add_block(); - let enum_fields = class.enum_fields(self.db()); + let enum_fields = type_id.enum_fields(self.db()); let tag_field = - class.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); + type_id.field_by_index(self.db(), ENUM_TAG_INDEX).unwrap(); let tag_reg = self.new_register(tag_field.value_type(self.db())); for con in cons { @@ -4686,7 +4701,7 @@ impl<'a> LowerMethod<'a> { } self.block_mut(before) - .get_field(tag_reg, rec, class, tag_field, location); + .get_field(tag_reg, rec, type_id, tag_field, location); self.block_mut(before).switch(tag_reg, blocks, location); self.current_block = after; } diff --git a/compiler/src/mir/pattern_matching.rs b/compiler/src/mir/pattern_matching.rs index 061dab98f..32207be16 100644 --- a/compiler/src/mir/pattern_matching.rs +++ b/compiler/src/mir/pattern_matching.rs @@ -24,8 +24,8 @@ use crate::state::State; use std::collections::{HashMap, HashSet}; use types::resolve::TypeResolver; use types::{ - ClassInstance, ClassKind, ConstructorId, Database, FieldId, TypeArguments, - TypeBounds, TypeId, TypeRef, VariableId, BOOL_ID, INT_ID, STRING_ID, + ConstructorId, Database, FieldId, TypeArguments, TypeBounds, TypeEnum, + TypeInstance, TypeKind, TypeRef, VariableId, BOOL_ID, INT_ID, STRING_ID, }; fn add_missing_patterns( @@ -260,8 +260,8 @@ impl Pattern { node: hir::Pattern, ) -> Self { match node { - hir::Pattern::Class(n) => { - let len = n.class_id.unwrap().number_of_fields(db); + hir::Pattern::Type(n) => { + let len = n.type_id.unwrap().number_of_fields(db); let mut args = vec![Pattern::Wildcard; len]; let mut fields = vec![FieldId(0); len]; @@ -765,7 +765,7 @@ impl<'a> Compiler<'a> { fn new_variables( &mut self, - instance: ClassInstance, + instance: TypeInstance, source_variable_type: TypeRef, types: Vec, ) -> Vec { @@ -780,7 +780,7 @@ impl<'a> Compiler<'a> { .collect(); } - let args = TypeArguments::for_class(self.db_mut(), instance); + let args = TypeArguments::for_type(self.db_mut(), instance); types .into_iter() @@ -797,24 +797,24 @@ impl<'a> Compiler<'a> { fn variable_type(&mut self, variable: &Variable) -> Type { let typ = variable.value_type(&self.variables); - let type_id = typ.type_id(self.db()).unwrap(); - let class_ins = if let TypeId::ClassInstance(ins) = type_id { + let type_id = typ.as_type_enum(self.db()).unwrap(); + let type_ins = if let TypeEnum::TypeInstance(ins) = type_id { ins } else { unreachable!() }; - let class_id = class_ins.instance_of(); + let type_id = type_ins.instance_of(); - match class_id.0 { + match type_id.0 { INT_ID => Type::Int, STRING_ID => Type::String, BOOL_ID => Type::Finite(vec![ (Constructor::False, Vec::new(), Vec::new()), (Constructor::True, Vec::new(), Vec::new()), ]), - _ => match class_id.kind(self.db()) { - ClassKind::Enum => { - let cons = class_id + _ => match type_id.kind(self.db()) { + TypeKind::Enum => { + let cons = type_id .constructors(self.db()) .into_iter() .map(|constructor| { @@ -823,7 +823,7 @@ impl<'a> Compiler<'a> { ( Constructor::Constructor(constructor), - self.new_variables(class_ins, typ, members), + self.new_variables(type_ins, typ, members), Vec::new(), ) }) @@ -831,8 +831,8 @@ impl<'a> Compiler<'a> { Type::Finite(cons) } - ClassKind::Regular | ClassKind::Extern => { - let fields = class_id.fields(self.db()); + TypeKind::Regular | TypeKind::Extern => { + let fields = type_id.fields(self.db()); let args = fields .iter() .map(|f| f.value_type(self.db())) @@ -840,12 +840,12 @@ impl<'a> Compiler<'a> { Type::Finite(vec![( Constructor::Class(fields), - self.new_variables(class_ins, typ, args), + self.new_variables(type_ins, typ, args), Vec::new(), )]) } - ClassKind::Tuple => { - let fields = class_id.fields(self.db()); + TypeKind::Tuple => { + let fields = type_id.fields(self.db()); let args = fields .iter() .map(|f| f.value_type(self.db())) @@ -853,7 +853,7 @@ impl<'a> Compiler<'a> { Type::Finite(vec![( Constructor::Tuple(fields), - self.new_variables(class_ins, typ, args), + self.new_variables(type_ins, typ, args), Vec::new(), )]) } @@ -879,7 +879,7 @@ mod tests { use similar_asserts::assert_eq; use types::module_name::ModuleName; use types::{ - Class, ClassInstance, ClassKind, Module, TypeId, + Module, Type, TypeEnum, TypeInstance, TypeKind, Variable as VariableType, Visibility, }; @@ -1245,10 +1245,10 @@ mod tests { ModuleName::new("test"), "test.inko".into(), ); - let option_type = Class::alloc( + let option_type = Type::alloc( &mut state.db, "Option".to_string(), - ClassKind::Enum, + TypeKind::Enum, Visibility::Public, module, Location::default(), @@ -1267,7 +1267,7 @@ mod tests { ); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(option_type)), + TypeEnum::TypeInstance(TypeInstance::new(option_type)), )); let int_var = Variable(1); let result = compiler.compile(rules( @@ -1318,10 +1318,10 @@ mod tests { ModuleName::new("test"), "test.inko".into(), ); - let option_type = Class::alloc( + let option_type = Type::alloc( &mut state.db, "Option".to_string(), - ClassKind::Enum, + TypeKind::Enum, Visibility::Public, module, Location::default(), @@ -1340,7 +1340,7 @@ mod tests { ); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(option_type)), + TypeEnum::TypeInstance(TypeInstance::new(option_type)), )); let int_var = Variable(1); let result = compiler.compile(rules( @@ -1388,17 +1388,17 @@ mod tests { } #[test] - fn test_nonexhaustive_class() { + fn test_nonexhaustive_type() { let mut state = state(); let module = Module::alloc( &mut state.db, ModuleName::new("test"), "test.inko".into(), ); - let person_type = Class::alloc( + let person_type = Type::alloc( &mut state.db, "Person".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, module, Location::default(), @@ -1427,7 +1427,7 @@ mod tests { let fields = person_type.fields(&state.db); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(person_type)), + TypeEnum::TypeInstance(TypeInstance::new(person_type)), )); let name_var = Variable(1); let age_var = Variable(2); @@ -1482,10 +1482,10 @@ mod tests { ModuleName::new("test"), "test.inko".into(), ); - let tuple2 = Class::alloc( + let tuple2 = Type::alloc( &mut state.db, "Tuple2".to_string(), - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Public, module, Location::default(), @@ -1514,7 +1514,7 @@ mod tests { let tuple_fields = tuple2.fields(&state.db); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(tuple2)), + TypeEnum::TypeInstance(TypeInstance::new(tuple2)), )); let var1 = Variable(1); let var2 = Variable(2); @@ -1565,17 +1565,17 @@ mod tests { } #[test] - fn test_exhaustive_class() { + fn test_exhaustive_type() { let mut state = state(); let module = Module::alloc( &mut state.db, ModuleName::new("test"), "test.inko".into(), ); - let person_type = Class::alloc( + let person_type = Type::alloc( &mut state.db, "Person".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, module, Location::default(), @@ -1604,7 +1604,7 @@ mod tests { let fields = person_type.fields(&state.db); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(person_type)), + TypeEnum::TypeInstance(TypeInstance::new(person_type)), )); let name_var = Variable(1); let age_var = Variable(2); @@ -1647,10 +1647,10 @@ mod tests { ModuleName::new("test"), "test.inko".into(), ); - let tuple2 = Class::alloc( + let tuple2 = Type::alloc( &mut state.db, "Tuple2".to_string(), - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Public, module, Location::default(), @@ -1679,7 +1679,7 @@ mod tests { let tuple_fields = tuple2.fields(&state.db); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(tuple2)), + TypeEnum::TypeInstance(TypeInstance::new(tuple2)), )); let var1 = Variable(1); let var2 = Variable(2); @@ -1948,10 +1948,10 @@ mod tests { ModuleName::new("test"), "test.inko".into(), ); - let tuple2 = Class::alloc( + let tuple2 = Type::alloc( &mut state.db, "Tuple2".to_string(), - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Public, module, Location::default(), @@ -1980,7 +1980,7 @@ mod tests { let tuple_fields = tuple2.fields(&state.db); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(tuple2)), + TypeEnum::TypeInstance(TypeInstance::new(tuple2)), )); let var1 = Variable(1); let var2 = Variable(2); @@ -2054,10 +2054,10 @@ mod tests { ModuleName::new("test"), "test.inko".into(), ); - let tuple2 = Class::alloc( + let tuple2 = Type::alloc( &mut state.db, "Tuple2".to_string(), - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Public, module, Location::default(), @@ -2086,7 +2086,7 @@ mod tests { let tuple_fields = tuple2.fields(&state.db); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(tuple2)), + TypeEnum::TypeInstance(TypeInstance::new(tuple2)), )); let var1 = Variable(1); let var2 = Variable(2); @@ -2170,10 +2170,10 @@ mod tests { ModuleName::new("test"), "test.inko".into(), ); - let tuple2 = Class::alloc( + let tuple2 = Type::alloc( &mut state.db, "Tuple2".to_string(), - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Public, module, Location::default(), @@ -2202,7 +2202,7 @@ mod tests { let tuple_fields = tuple2.fields(&state.db); let mut compiler = compiler(&mut state); let input = compiler.new_variable(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(tuple2)), + TypeEnum::TypeInstance(TypeInstance::new(tuple2)), )); let var1 = Variable(1); let var2 = Variable(2); diff --git a/compiler/src/mir/printer.rs b/compiler/src/mir/printer.rs index d0cdbcb5b..74f0cecfa 100644 --- a/compiler/src/mir/printer.rs +++ b/compiler/src/mir/printer.rs @@ -2,7 +2,7 @@ use crate::mir::inline::method_weight; use crate::mir::{BlockId, Method}; use std::fmt::Write; -use types::{Database, MethodId, TypeId}; +use types::{Database, MethodId, TypeEnum}; fn method_name(db: &Database, id: MethodId) -> String { format!("{}#{}", id.name(db), id.0,) @@ -23,10 +23,10 @@ pub(crate) fn to_dot(db: &Database, methods: &[&Method]) -> String { buffer.push_str("edge[fontname=\"monospace\", fontsize=10];\n"); let rec_name = match method.id.receiver_id(db) { - TypeId::Class(id) => id.name(db).clone(), - TypeId::Trait(id) => id.name(db).clone(), - TypeId::ClassInstance(ins) => ins.instance_of().name(db).clone(), - TypeId::TraitInstance(ins) => ins.instance_of().name(db).clone(), + TypeEnum::Type(id) => id.name(db).clone(), + TypeEnum::Trait(id) => id.name(db).clone(), + TypeEnum::TypeInstance(ins) => ins.instance_of().name(db).clone(), + TypeEnum::TraitInstance(ins) => ins.instance_of().name(db).clone(), _ => String::new(), }; diff --git a/compiler/src/mir/specialize.rs b/compiler/src/mir/specialize.rs index cd522a624..31882a514 100644 --- a/compiler/src/mir/specialize.rs +++ b/compiler/src/mir/specialize.rs @@ -1,7 +1,6 @@ use crate::mir::{ - Block, BlockId, Borrow, CallDynamic, CallInstance, CastType, - Class as MirClass, Drop, Instruction, InstructionLocation, Method, Mir, - RegisterId, + Block, BlockId, Borrow, CallDynamic, CallInstance, CastType, Drop, + Instruction, InstructionLocation, Method, Mir, RegisterId, Type as MirType, }; use crate::state::State; use indexmap::{IndexMap, IndexSet}; @@ -10,8 +9,8 @@ use std::mem::swap; use types::check::TypeChecker; use types::specialize::{ordered_shapes_from_map, TypeSpecializer}; use types::{ - Block as _, ClassId, ClassInstance, Database, InternedTypeArguments, - MethodId, Shape, TypeArguments, TypeParameterId, TypeRef, CALL_METHOD, + Block as _, Database, InternedTypeArguments, MethodId, Shape, + TypeArguments, TypeId, TypeInstance, TypeParameterId, TypeRef, CALL_METHOD, DECREMENT_METHOD, DROPPER_METHOD, INCREMENT_METHOD, }; @@ -30,28 +29,28 @@ fn specialize_constants( mir: &mut Mir, interned: &mut InternedTypeArguments, ) { - let mut classes = Vec::new(); + let mut types = Vec::new(); let shapes = HashMap::new(); // Constants never need access to the self type, so we just use a dummy // value here. - let stype = ClassInstance::new(ClassId::nil()); + let stype = TypeInstance::new(TypeId::nil()); for &id in mir.constants.keys() { let old_typ = id.value_type(db); let new_typ = - TypeSpecializer::new(db, interned, &shapes, &mut classes, stype) + TypeSpecializer::new(db, interned, &shapes, &mut types, stype) .specialize(old_typ); id.set_value_type(db, new_typ); } - for class in classes { - mir.classes.insert(class, MirClass::new(class)); + for typ in types { + mir.types.insert(typ, MirType::new(typ)); - let mod_id = class.module(db); + let mod_id = typ.module(db); - mir.modules.get_mut(&mod_id).unwrap().classes.push(class); + mir.modules.get_mut(&mod_id).unwrap().types.push(typ); } } @@ -87,7 +86,7 @@ fn shapes_compatible_with_bounds( // implements a certain trait when it doesn't. let Some(ins) = shape.as_stack_instance() else { continue }; - if !TypeChecker::new(db).class_compatible_with_bound(ins, bound) { + if !TypeChecker::new(db).type_compatible_with_bound(ins, bound) { return false; } } @@ -98,7 +97,7 @@ fn shapes_compatible_with_bounds( struct Job { /// The type of `self` within the method. - self_type: ClassInstance, + self_type: TypeInstance, /// The ID of the method that's being specialized. method: MethodId, @@ -125,7 +124,7 @@ impl Work { fn push( &mut self, - self_type: ClassInstance, + self_type: TypeInstance, method: MethodId, shapes: HashMap, ) -> bool { @@ -160,7 +159,7 @@ struct DynamicCall { shapes: Vec<(TypeParameterId, Shape)>, } -/// A type that tracks classes along with their methods that are called using +/// A type that tracks types along with their methods that are called using /// dynamic dispatch, and the shapes of those calls. /// /// When specializing types and methods, we may encounter a dynamic dispatch @@ -178,7 +177,7 @@ struct DynamicCall { /// value.to_string /// } /// -/// class async Main { +/// type async Main { /// fn async main { /// to_string([10, 20]) /// [10.2] @@ -200,7 +199,7 @@ struct DynamicCalls { /// The values are an _ordered_ hash set to ensure the data is always /// processed in a deterministic order. This is important in order to /// maintain the incremental compilation caches. - mapping: HashMap>, + mapping: HashMap>, } impl DynamicCalls { @@ -210,26 +209,26 @@ impl DynamicCalls { fn add( &mut self, - class: ClassId, + type_id: TypeId, method: MethodId, key: Vec, shapes: Vec<(TypeParameterId, Shape)>, ) { - self.mapping.entry(class).or_default().insert(DynamicCall { + self.mapping.entry(type_id).or_default().insert(DynamicCall { method, key, shapes, }); } - fn get(&self, class: ClassId) -> Option<&IndexSet> { - self.mapping.get(&class) + fn get(&self, type_id: TypeId) -> Option<&IndexSet> { + self.mapping.get(&type_id) } } /// A compiler pass that specializes generic types. pub(crate) struct Specialize<'a, 'b> { - self_type: ClassInstance, + self_type: TypeInstance, method: MethodId, state: &'a mut State, work: &'b mut Work, @@ -249,39 +248,39 @@ pub(crate) struct Specialize<'a, 'b> { /// Classes created when specializing types. /// - /// These classes are tracked so we can generate their droppers, and + /// These types are tracked so we can generate their droppers, and /// specialize any implemented trait methods that are called through dynamic /// dispatch. - classes: Vec, + types: Vec, } impl<'a, 'b> Specialize<'a, 'b> { pub(crate) fn run_all(state: &'a mut State, mir: &'a mut Mir) { // As part of specialization we create specializations for generics, and - // discover all the classes that are in use. This ensures that once - // we're done, anything that we didn't encounter is removed, ensuring - // future passes don't operate on unused classes and methods. - for class in mir.classes.values_mut() { - class.methods.clear(); + // discover all the types that are in use. This ensures that once we're + // done, anything that we didn't encounter is removed, ensuring future + // passes don't operate on unused types and methods. + for typ in mir.types.values_mut() { + typ.methods.clear(); } for module in mir.modules.values_mut() { - module.classes.clear(); + module.types.clear(); module.methods.clear(); } let mut work = Work::new(); let mut dcalls = DynamicCalls::new(); let mut intern = InternedTypeArguments::new(); - let main_class = state.db.main_class().unwrap(); + let main_type = state.db.main_type().unwrap(); let main_method = state.db.main_method().unwrap(); - let main_mod = main_class.module(&state.db); + let main_mod = main_type.module(&state.db); - work.push(ClassInstance::new(main_class), main_method, HashMap::new()); + work.push(TypeInstance::new(main_type), main_method, HashMap::new()); // The main() method isn't called explicitly, so we have to manually - // record it in the main class. - mir.classes.get_mut(&main_class).unwrap().methods.push(main_method); + // record it in the main type. + mir.types.get_mut(&main_type).unwrap().methods.push(main_method); mir.modules.get_mut(&main_mod).unwrap().methods.push(main_method); while let Some(job) = work.pop() { @@ -294,13 +293,13 @@ impl<'a, 'b> Specialize<'a, 'b> { work: &mut work, regular_methods: Vec::new(), specialized_methods: Vec::new(), - classes: Vec::new(), + types: Vec::new(), } .run(mir, &mut dcalls); } // Constants may contain arrays, so we need to make sure those use the - // correct classes. + // correct types. // // This is done _after_ processing methods. This way we don't need to // handle generating droppers for constants, because if we encounter @@ -328,11 +327,10 @@ impl<'a, 'b> Specialize<'a, 'b> { } } - // The specialization source is also set for regular classes that we - // encounter. Thus, this filters out any classes that we don't encounter + // The specialization source is also set for regular types that we + // encounter. Thus, this filters out any types that we don't encounter // anywhere; generic or not. - mir.classes - .retain(|id, _| id.specialization_source(&state.db).is_some()); + mir.types.retain(|id, _| id.specialization_source(&state.db).is_some()); // We don't need the type arguments after this point. mir.type_arguments = Vec::new(); @@ -362,7 +360,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, &self.shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(reg.value_type); @@ -390,7 +388,7 @@ impl<'a, 'b> Specialize<'a, 'b> { } Instruction::CallStatic(ins) => { let rec = ins.method.receiver(&self.state.db); - let cls = rec.class_id(&self.state.db).unwrap(); + let cls = rec.type_id(&self.state.db).unwrap(); let targs = ins .type_arguments .and_then(|i| mir.type_arguments.get(i)); @@ -399,7 +397,7 @@ impl<'a, 'b> Specialize<'a, 'b> { } Instruction::CallInstance(ins) => { let rec = method.registers.value_type(ins.receiver); - let cls = rec.class_id(&self.state.db).unwrap(); + let cls = rec.type_id(&self.state.db).unwrap(); let targs = ins .type_arguments .and_then(|i| mir.type_arguments.get(i)); @@ -408,7 +406,7 @@ impl<'a, 'b> Specialize<'a, 'b> { } Instruction::Send(ins) => { let rec = method.registers.value_type(ins.receiver); - let cls = rec.class_id(&self.state.db).unwrap(); + let cls = rec.type_id(&self.state.db).unwrap(); let targs = ins .type_arguments .and_then(|i| mir.type_arguments.get(i)); @@ -418,10 +416,10 @@ impl<'a, 'b> Specialize<'a, 'b> { Instruction::CallDynamic(call) => match method .registers .value_type(call.receiver) - .as_class_instance(&self.state.db) + .as_type_instance(&self.state.db) { // As part of specialization, we may encounter a dynamic - // call that's now acting on a class instance. We need + // call that's now acting on a type instance. We need // to change the instruction in this case, otherwise we // may compile code that performs dynamic dispatch on // unboxed values (e.g. Int), which isn't supported. @@ -456,14 +454,14 @@ impl<'a, 'b> Specialize<'a, 'b> { } }, Instruction::Allocate(ins) => { - let old = ins.class; + let old = ins.type_id; let new = method .registers .value_type(ins.register) - .class_id(&self.state.db) + .type_id(&self.state.db) .unwrap(); - ins.class = new; + ins.type_id = new; self.schedule_regular_dropper(old, new); self.schedule_regular_inline_type_methods(new); } @@ -471,67 +469,67 @@ impl<'a, 'b> Specialize<'a, 'b> { let cls = method .registers .value_type(ins.register) - .class_id(&self.state.db) + .type_id(&self.state.db) .unwrap(); - ins.class = cls; + ins.type_id = cls; } Instruction::Spawn(ins) => { - let old = ins.class; + let old = ins.type_id; let new = method .registers .value_type(ins.register) - .class_id(&self.state.db) + .type_id(&self.state.db) .unwrap(); - ins.class = new; + ins.type_id = new; self.schedule_regular_dropper(old, new); } Instruction::SetField(ins) => { let db = &mut self.state.db; - ins.class = method + ins.type_id = method .registers .value_type(ins.receiver) - .class_id(db) + .type_id(db) .unwrap(); ins.field = ins - .class + .type_id .field_by_index(db, ins.field.index(db)) .unwrap(); } Instruction::GetField(ins) => { let db = &mut self.state.db; - ins.class = method + ins.type_id = method .registers .value_type(ins.receiver) - .class_id(db) + .type_id(db) .unwrap(); ins.field = ins - .class + .type_id .field_by_index(db, ins.field.index(db)) .unwrap(); } Instruction::FieldPointer(ins) => { let db = &mut self.state.db; - ins.class = method + ins.type_id = method .registers .value_type(ins.receiver) - .class_id(db) + .type_id(db) .unwrap(); ins.field = ins - .class + .type_id .field_by_index(db, ins.field.index(db)) .unwrap(); } Instruction::MethodPointer(ins) => { let rec = ins.method.receiver(&self.state.db); - let cls = rec.class_id(&self.state.db).unwrap(); + let cls = rec.type_id(&self.state.db).unwrap(); ins.method = self.call_static(cls, ins.method, None); } @@ -550,7 +548,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, &self.shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(ins.argument); @@ -586,50 +584,50 @@ impl<'a, 'b> Specialize<'a, 'b> { mir: &mut Mir, dynamic_calls: &mut DynamicCalls, ) { - while let Some(class) = self.classes.pop() { - mir.classes.entry(class).or_insert_with(|| MirClass::new(class)); + while let Some(typ) = self.types.pop() { + mir.types.entry(typ).or_insert_with(|| MirType::new(typ)); - let mod_id = class.module(&self.state.db); + let mod_id = typ.module(&self.state.db); let module = mir.modules.get_mut(&mod_id).unwrap(); - let kind = class.kind(&self.state.db); + let kind = typ.kind(&self.state.db); - module.classes.push(class); + module.types.push(typ); if kind.is_extern() { - // We don't generate methods for extern classes, nor can they be + // We don't generate methods for extern types, nor can they be // used for receivers as method calls. continue; } - // New classes are only added for types to specialize, so the source + // New types are only added for types to specialize, so the source // is always set at this point. - let orig = class.specialization_source(&self.state.db).unwrap(); + let orig = typ.specialization_source(&self.state.db).unwrap(); - self.generate_dropper(orig, class); - self.generate_inline_type_methods(orig, class); + self.generate_dropper(orig, typ); + self.generate_inline_type_methods(orig, typ); - if orig == class { - // For regular classes the rest of the work doesn't apply. + if orig == typ { + // For regular types the rest of the work doesn't apply. continue; } if kind.is_closure() { - self.generate_closure_methods(orig, class); + self.generate_closure_methods(orig, typ); } if let Some(calls) = dynamic_calls.get(orig) { - let mut class_shapes = HashMap::new(); + let mut type_shapes = HashMap::new(); - for (param, &shape) in class + for (param, &shape) in typ .type_parameters(&self.state.db) .into_iter() - .zip(class.shapes(&self.state.db)) + .zip(typ.shapes(&self.state.db)) { - class_shapes.insert(param, shape); + type_shapes.insert(param, shape); } for call in calls { - let mut shapes = class_shapes.clone(); + let mut shapes = type_shapes.clone(); for &(par, shape) in &call.shapes { shapes.insert(par, shape); @@ -654,7 +652,7 @@ impl<'a, 'b> Specialize<'a, 'b> { self.add_implementation_shapes(call.method, &mut shapes); self.add_method_bound_shapes(call.method, &mut shapes); - self.specialize_method(class, call.method, &shapes, None); + self.specialize_method(typ, call.method, &shapes, None); } } } @@ -675,25 +673,24 @@ impl<'a, 'b> Specialize<'a, 'b> { } fn track_method(&self, method: MethodId, mir: &mut Mir) { - let class = - method.receiver(&self.state.db).class_id(&self.state.db).unwrap(); + let typ = + method.receiver(&self.state.db).type_id(&self.state.db).unwrap(); mir.modules - .get_mut(&class.module(&self.state.db)) + .get_mut(&typ.module(&self.state.db)) .unwrap() .methods .push(method); - // Static methods aren't tracked in any classes, so we can skip the - // rest. + // Static methods aren't tracked in any types, so we can skip the rest. if method.is_instance(&self.state.db) { - mir.classes.get_mut(&class).unwrap().methods.push(method); + mir.types.get_mut(&typ).unwrap().methods.push(method); } } fn call_static( &mut self, - class: ClassId, + type_id: TypeId, method: MethodId, type_arguments: Option<&TypeArguments>, ) -> MethodId { @@ -707,17 +704,17 @@ impl<'a, 'b> Specialize<'a, 'b> { // call the type's drop method if it exists. Because those calls are // generated, they won't have any `TypeArguments` to expose to the // instruction. As such, we have to handle such calls explicitly. - if shapes.is_empty() && class.is_generic(&self.state.db) { - for (par, &shape) in class + if shapes.is_empty() && type_id.is_generic(&self.state.db) { + for (par, &shape) in type_id .type_parameters(&self.state.db) .into_iter() - .zip(class.shapes(&self.state.db)) + .zip(type_id.shapes(&self.state.db)) { shapes.insert(par, shape); } } - self.specialize_method(class, method, &shapes, None) + self.specialize_method(type_id, method, &shapes, None) } fn call_dynamic( @@ -741,7 +738,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, &self.shapes, - &mut self.classes, + &mut self.types, self.self_type, shape, ); @@ -763,13 +760,13 @@ impl<'a, 'b> Specialize<'a, 'b> { .map(|(&k, &v)| (k, v)) .collect(); - for class in trait_id.implemented_by(&self.state.db).clone() { - let method_impl = class + for typ in trait_id.implemented_by(&self.state.db).clone() { + let method_impl = typ .method(&self.state.db, method.name(&self.state.db)) .unwrap(); dynamic_calls.add( - class, + typ, method_impl, method_shapes.clone(), extra_shapes.clone(), @@ -791,8 +788,8 @@ impl<'a, 'b> Specialize<'a, 'b> { shapes.insert(target_par, *base_shapes.get(&src_par).unwrap()); } - if class.is_generic(&self.state.db) { - let params = class.type_parameters(&self.state.db); + if typ.is_generic(&self.state.db) { + let params = typ.type_parameters(&self.state.db); // We need/want to ensure that each specialization has its own // set of shapes. Even if this isn't technically required since @@ -801,16 +798,14 @@ impl<'a, 'b> Specialize<'a, 'b> { // unexpected bugs. let mut shapes = shapes.clone(); - for (key, class) in - class.specializations(&self.state.db).clone() - { + for (key, typ) in typ.specializations(&self.state.db).clone() { // A dynamic call won't include shapes/type arguments for - // type parameters of the specialized class, so we have to + // type parameters of the specialized type, so we have to // inject those here. // // We don't need to clone `shapes` here because the type // parameters are the same for every specialization of the - // base class, so we don't accidentally end up using the + // base type, so we don't accidentally end up using the // wrong shape on a future iteration of the surrounding // loop. for (¶m, shape) in params.iter().zip(key.shapes) { @@ -826,16 +821,16 @@ impl<'a, 'b> Specialize<'a, 'b> { } // We have to repeat these two calls for every specialized - // class, because the shapes referred to through bounds or + // type, because the shapes referred to through bounds or // type arguments may differ per specialization. self.add_implementation_shapes(method_impl, &mut shapes); self.add_method_bound_shapes(method_impl, &mut shapes); - self.specialize_method(class, method_impl, &shapes, None); + self.specialize_method(typ, method_impl, &shapes, None); } } else { self.add_implementation_shapes(method_impl, &mut shapes); self.add_method_bound_shapes(method_impl, &mut shapes); - self.specialize_method(class, method_impl, &shapes, None); + self.specialize_method(typ, method_impl, &shapes, None); } } @@ -867,13 +862,13 @@ impl<'a, 'b> Specialize<'a, 'b> { fn devirtualize_call_dynamic( &mut self, call: &CallDynamic, - receiver: ClassInstance, + receiver: TypeInstance, type_arguments: Option<&TypeArguments>, ) -> Instruction { - let class = receiver.instance_of(); - let method_impl = class + let typ = receiver.instance_of(); + let method_impl = typ .specialization_source(&self.state.db) - .unwrap_or(class) + .unwrap_or(typ) .method(&self.state.db, call.method.name(&self.state.db)) .unwrap(); @@ -881,10 +876,10 @@ impl<'a, 'b> Specialize<'a, 'b> { .map(|args| self.type_argument_shapes(call.method, args)) .unwrap_or_default(); - for (param, &shape) in class + for (param, &shape) in typ .type_parameters(&self.state.db) .into_iter() - .zip(class.shapes(&self.state.db)) + .zip(typ.shapes(&self.state.db)) { shapes.insert(param, shape); } @@ -901,7 +896,7 @@ impl<'a, 'b> Specialize<'a, 'b> { self.add_implementation_shapes(method_impl, &mut shapes); self.add_method_bound_shapes(method_impl, &mut shapes); - let new = self.specialize_method(class, method_impl, &shapes, None); + let new = self.specialize_method(typ, method_impl, &shapes, None); Instruction::CallInstance(Box::new(CallInstance { register: call.register, @@ -915,17 +910,17 @@ impl<'a, 'b> Specialize<'a, 'b> { fn specialize_method( &mut self, - class: ClassId, + type_id: TypeId, method: MethodId, shapes: &HashMap, - custom_self_type: Option, + custom_self_type: Option, ) -> MethodId { - let ins = ClassInstance::new(class); + let ins = TypeInstance::new(type_id); let stype = custom_self_type.unwrap_or(ins); // Regular methods on regular types don't need to be specialized. - if !class.is_generic(&self.state.db) - && !class.is_closure(&self.state.db) + if !type_id.is_generic(&self.state.db) + && !type_id.is_closure(&self.state.db) && !method.is_generic(&self.state.db) { if self.work.push(stype, method, shapes.clone()) { @@ -936,7 +931,7 @@ impl<'a, 'b> Specialize<'a, 'b> { return method; } - let mut key: Vec = class + let mut key: Vec = type_id .type_parameters(&self.state.db) .into_iter() .chain(method.type_parameters(&self.state.db)) @@ -949,7 +944,7 @@ impl<'a, 'b> Specialize<'a, 'b> { return new; } - let new_rec = method.receiver_for_class_instance(&self.state.db, ins); + let new_rec = method.receiver_for_type_instance(&self.state.db, ins); let new = self.specialize_method_type(new_rec, method, key, shapes); self.work.push(stype, new, shapes.clone()); @@ -957,18 +952,19 @@ impl<'a, 'b> Specialize<'a, 'b> { new } - fn schedule_regular_dropper(&mut self, original: ClassId, class: ClassId) { - if class.is_generic(&self.state.db) || class.is_closure(&self.state.db) + fn schedule_regular_dropper(&mut self, original: TypeId, type_id: TypeId) { + if type_id.is_generic(&self.state.db) + || type_id.is_closure(&self.state.db) { return; } - self.generate_dropper(original, class); + self.generate_dropper(original, type_id); } - fn schedule_regular_inline_type_methods(&mut self, class: ClassId) { - if class.is_generic(&self.state.db) - || !class.is_inline_type(&self.state.db) + fn schedule_regular_inline_type_methods(&mut self, type_id: TypeId) { + if type_id.is_generic(&self.state.db) + || !type_id.is_inline_type(&self.state.db) { return; } @@ -976,8 +972,8 @@ impl<'a, 'b> Specialize<'a, 'b> { let methods = [INCREMENT_METHOD, DECREMENT_METHOD]; for name in methods { - let method = class.method(&self.state.db, name).unwrap(); - let stype = ClassInstance::new(class); + let method = type_id.method(&self.state.db, name).unwrap(); + let stype = TypeInstance::new(type_id); if self.work.push(stype, method, HashMap::new()) { self.regular_methods.push(method); @@ -985,7 +981,7 @@ impl<'a, 'b> Specialize<'a, 'b> { } } - fn generate_dropper(&mut self, original: ClassId, class: ClassId) { + fn generate_dropper(&mut self, original: TypeId, type_id: TypeId) { let name = DROPPER_METHOD; // `copy` types won't have droppers, so there's nothing to do here. @@ -995,13 +991,13 @@ impl<'a, 'b> Specialize<'a, 'b> { // References to `self` in closures should point to the type of the // scope the closure is defined in, not the closure itself. - let stype = if class.is_closure(&self.state.db) { + let stype = if type_id.is_closure(&self.state.db) { self.self_type } else { - ClassInstance::new(class) + TypeInstance::new(type_id) }; - if original == class { + if original == type_id { if self.work.push(stype, method, HashMap::new()) { self.regular_methods.push(method); } @@ -1009,25 +1005,25 @@ impl<'a, 'b> Specialize<'a, 'b> { return; } - let shapes = if class.is_closure(&self.state.db) { + let shapes = if type_id.is_closure(&self.state.db) { self.shapes.clone() } else { - class + type_id .type_parameters(&self.state.db) .into_iter() - .zip(class.shapes(&self.state.db).clone()) + .zip(type_id.shapes(&self.state.db).clone()) .collect() }; - let new = self.specialize_method(class, method, &shapes, Some(stype)); + let new = self.specialize_method(type_id, method, &shapes, Some(stype)); - class.add_method(&mut self.state.db, name.to_string(), new); + type_id.add_method(&mut self.state.db, name.to_string(), new); } fn generate_inline_type_methods( &mut self, - original: ClassId, - class: ClassId, + original: TypeId, + type_id: TypeId, ) { if !original.is_inline_type(&self.state.db) { return; @@ -1038,8 +1034,8 @@ impl<'a, 'b> Specialize<'a, 'b> { for name in methods { let method = original.method(&self.state.db, name).unwrap(); - if original == class { - let stype = ClassInstance::new(class); + if original == type_id { + let stype = TypeInstance::new(type_id); if self.work.push(stype, method, HashMap::new()) { self.regular_methods.push(method); @@ -1048,20 +1044,20 @@ impl<'a, 'b> Specialize<'a, 'b> { continue; } - let shapes = class + let shapes = type_id .type_parameters(&self.state.db) .into_iter() - .zip(class.shapes(&self.state.db).clone()) + .zip(type_id.shapes(&self.state.db).clone()) .collect(); - let new = self.specialize_method(class, method, &shapes, None); + let new = self.specialize_method(type_id, method, &shapes, None); let name = method.name(&self.state.db).clone(); - class.add_method(&mut self.state.db, name, new); + type_id.add_method(&mut self.state.db, name, new); } } - fn generate_closure_methods(&mut self, original: ClassId, class: ClassId) { + fn generate_closure_methods(&mut self, original: TypeId, type_id: TypeId) { // Closures may capture generic types from the surrounding method, so we // have to expose the surrounding method's shapes to the closure. let shapes = self.shapes.clone(); @@ -1071,7 +1067,7 @@ impl<'a, 'b> Specialize<'a, 'b> { // of `self` should refer to the type of `self` as used by the method in // which the closure is defined, instead of pointing to the closure's // type. - self.specialize_method(class, method, &shapes, Some(self.self_type)); + self.specialize_method(type_id, method, &shapes, Some(self.self_type)); } /// Creates a new specialized method, using an existing method as its @@ -1086,13 +1082,13 @@ impl<'a, 'b> Specialize<'a, 'b> { mut key: Vec, shapes: &HashMap, ) -> MethodId { - // For static methods we include the class' type parameter shapes such + // For static methods we include the type's type parameter shapes such // that we can generate unique names using just the shapes for // non-generic static methods. If we didn't do this, then two different // instances of e.g. `Result.Ok` would produce the same symbol name let shape_params = if method.is_static(&self.state.db) { - let class = receiver.class_id(&self.state.db).unwrap(); - let mut params = class.type_parameters(&self.state.db); + let typ = receiver.type_id(&self.state.db).unwrap(); + let mut params = typ.type_parameters(&self.state.db); params.append(&mut method.type_parameters(&self.state.db)); params @@ -1113,7 +1109,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(arg.value_type); @@ -1124,7 +1120,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(raw_var_type); @@ -1142,7 +1138,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(old_ret); @@ -1178,7 +1174,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(arg.value_type); @@ -1188,7 +1184,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(raw_var_type); @@ -1206,7 +1202,7 @@ impl<'a, 'b> Specialize<'a, 'b> { &mut self.state.db, self.interned, shapes, - &mut self.classes, + &mut self.types, self.self_type, ) .specialize(old_ret); @@ -1330,20 +1326,20 @@ impl<'a, 'b> Specialize<'a, 'b> { /// lookups/hashing. /// /// This is necessary because in certain cases we may produce e.g. a - /// `Shape::Inline(ins)` shape where `ins` refers to an unspecialized class + /// `Shape::Inline(ins)` shape where `ins` refers to an unspecialized type /// ID. Rather than try and handle that case in a variety of places that /// produce shapes, we handle this in this single place just before we /// actually use the key for a lookup. /// /// This preparation in turn is necessary so two different references to the - /// same type, one using as specialized class ID and one using the raw one, + /// same type, one using as specialized type ID and one using the raw one, /// result in the same lookup result. fn prepare_key(&mut self, key: &mut Vec) { TypeSpecializer::specialize_shapes( &mut self.state.db, self.interned, &self.shapes, - &mut self.classes, + &mut self.types, self.self_type, key, ); @@ -1474,16 +1470,16 @@ impl<'a, 'b, 'c> ExpandDrop<'a, 'b, 'c> { if dropper { self.call_dropper(before_id, value, location); } else { - let class = self + let typ = self .method .registers .value_type(value) - .class_id(self.db) + .type_id(self.db) .unwrap(); - if class.is_heap_allocated(self.db) { + if typ.is_heap_allocated(self.db) { self.block_mut(before_id).check_refs(value, location); - self.block_mut(before_id).free(value, class, location); + self.block_mut(before_id).free(value, typ, location); } } @@ -1500,10 +1496,10 @@ impl<'a, 'b, 'c> ExpandDrop<'a, 'b, 'c> { let typ = self.method.registers.value_type(value); let reg = self.method.registers.alloc(TypeRef::nil()); - if let Some(class) = typ.class_id(self.db) { - // If the type of the receiver is statically known to be a class, we + if let Some(typ) = typ.type_id(self.db) { + // If the type of the receiver is statically known to be a type, we // can just call the dropper directly. - let method = class.method(self.db, types::DROPPER_METHOD).unwrap(); + let method = typ.method(self.db, types::DROPPER_METHOD).unwrap(); self.block_mut(block).call_instance( reg, @@ -1523,7 +1519,7 @@ impl<'a, 'b, 'c> ExpandDrop<'a, 'b, 'c> { before_id: BlockId, after_id: BlockId, value: RegisterId, - instance: ClassInstance, + instance: TypeInstance, location: InstructionLocation, ) { let reg = self.method.registers.alloc(TypeRef::nil()); @@ -1625,7 +1621,7 @@ impl<'a, 'b, 'c> ExpandBorrow<'a, 'b, 'c> { &mut self, block: BlockId, value: RegisterId, - instance: ClassInstance, + instance: TypeInstance, location: InstructionLocation, ) { let reg = self.method.registers.alloc(TypeRef::nil()); diff --git a/compiler/src/symbol_names.rs b/compiler/src/symbol_names.rs index a08dfb464..24cd49894 100644 --- a/compiler/src/symbol_names.rs +++ b/compiler/src/symbol_names.rs @@ -2,7 +2,7 @@ use crate::mir::Mir; use std::collections::HashMap; use std::fmt::Write as _; -use types::{ClassId, ConstantId, Database, MethodId, ModuleId, Shape, Sign}; +use types::{ConstantId, Database, MethodId, ModuleId, Shape, Sign, TypeId}; pub(crate) const SYMBOL_PREFIX: &str = "_I"; @@ -28,25 +28,25 @@ pub(crate) fn format_shape(db: &Database, shape: Shape, buf: &mut String) { Shape::Copy(ins) => { let _ = write!(buf, "C{}.", ins.instance_of().module(db).name(db)); - format_class_name(db, ins.instance_of(), buf); + format_type_name(db, ins.instance_of(), buf); Ok(()) } Shape::Inline(ins) => { let _ = write!(buf, "IO{}.", ins.instance_of().module(db).name(db)); - format_class_name(db, ins.instance_of(), buf); + format_type_name(db, ins.instance_of(), buf); Ok(()) } Shape::InlineRef(ins) => { let _ = write!(buf, "IR{}.", ins.instance_of().module(db).name(db)); - format_class_name(db, ins.instance_of(), buf); + format_type_name(db, ins.instance_of(), buf); Ok(()) } Shape::InlineMut(ins) => { let _ = write!(buf, "IM{}.", ins.instance_of().module(db).name(db)); - format_class_name(db, ins.instance_of(), buf); + format_type_name(db, ins.instance_of(), buf); Ok(()) } }; @@ -58,7 +58,7 @@ pub(crate) fn format_shapes(db: &Database, shapes: &[Shape], buf: &mut String) { } } -fn format_class_base_name(db: &Database, id: ClassId, name: &mut String) { +fn format_type_base_name(db: &Database, id: TypeId, name: &mut String) { name.push_str(id.name(db)); // For closures the process of generating a name is a little more tricky: a @@ -85,14 +85,14 @@ fn format_class_base_name(db: &Database, id: ClassId, name: &mut String) { // doesn't support demangling our format). name.push_str(&format!( "({},{},{})", - qualified_class_name(db, stype.module(db), stype), + qualified_type_name(db, stype.module(db), stype), loc.line_start, loc.column_start, )); } -pub(crate) fn format_class_name(db: &Database, id: ClassId, buf: &mut String) { - format_class_base_name(db, id, buf); +pub(crate) fn format_type_name(db: &Database, id: TypeId, buf: &mut String) { + format_type_base_name(db, id, buf); let shapes = id.shapes(db); @@ -102,26 +102,26 @@ pub(crate) fn format_class_name(db: &Database, id: ClassId, buf: &mut String) { } } -pub(crate) fn qualified_class_name( +pub(crate) fn qualified_type_name( db: &Database, module: ModuleId, - class: ClassId, + tid: TypeId, ) -> String { let mut name = format!("{}.", module.name(db)); - format_class_name(db, class, &mut name); + format_type_name(db, tid, &mut name); name } pub(crate) fn format_method_name( db: &Database, - class: ClassId, + tid: TypeId, id: MethodId, name: &mut String, ) { name.push_str(id.name(db)); - let cshapes = class.shapes(db); + let cshapes = tid.shapes(db); let mshapes = id.shapes(db); if !cshapes.is_empty() || !mshapes.is_empty() { @@ -132,7 +132,7 @@ pub(crate) fn format_method_name( } fn mangled_method_name(db: &Database, method: MethodId) -> String { - let class = method.receiver(db).class_id(db).unwrap(); + let tid = method.receiver(db).type_id(db).unwrap(); // We don't use MethodId::source_module() here as for default methods that // may point to the module that defined the trait, rather than the module @@ -146,48 +146,48 @@ fn mangled_method_name(db: &Database, method: MethodId) -> String { let mut name = format!( "{}{}_{}.", SYMBOL_PREFIX, - if class.is_closure(db) { "MC" } else { "M" }, + if tid.is_closure(db) { "MC" } else { "M" }, mod_name ); // This ensures that methods such as `std::process.sleep` aren't formatted // as `std::process::std::process.sleep`. This in turn makes stack traces // easier to read. - if !class.kind(db).is_module() { - format_class_base_name(db, class, &mut name); + if !tid.kind(db).is_module() { + format_type_base_name(db, tid, &mut name); name.push('.'); } - format_method_name(db, class, method, &mut name); + format_method_name(db, tid, method, &mut name); name } /// A cache of mangled symbol names. pub(crate) struct SymbolNames { - pub(crate) classes: HashMap, + pub(crate) types: HashMap, pub(crate) methods: HashMap, pub(crate) constants: HashMap, - pub(crate) setup_classes: HashMap, + pub(crate) setup_types: HashMap, pub(crate) setup_constants: HashMap, } impl SymbolNames { pub(crate) fn new(db: &Database, mir: &Mir) -> Self { - let mut classes = HashMap::new(); + let mut types = HashMap::new(); let mut methods = HashMap::new(); let mut constants = HashMap::new(); - let mut setup_classes = HashMap::new(); + let mut setup_types = HashMap::new(); let mut setup_constants = HashMap::new(); for module in mir.modules.values() { - for &class in &module.classes { - let class_name = format!( + for &typ in &module.types { + let tname = format!( "{}T_{}", SYMBOL_PREFIX, - qualified_class_name(db, module.id, class) + qualified_type_name(db, module.id, typ) ); - classes.insert(class, class_name); + types.insert(typ, tname); } } @@ -207,15 +207,15 @@ impl SymbolNames { for &id in mir.modules.keys() { let mod_name = id.name(db).as_str(); - let classes = format!("{}M_{}.$classes", SYMBOL_PREFIX, mod_name); + let types = format!("{}M_{}.$types", SYMBOL_PREFIX, mod_name); let constants = format!("{}M_{}.$constants", SYMBOL_PREFIX, mod_name); - setup_classes.insert(id, classes); + setup_types.insert(id, types); setup_constants.insert(id, constants); } - Self { classes, methods, constants, setup_classes, setup_constants } + Self { types, methods, constants, setup_types, setup_constants } } } @@ -225,7 +225,7 @@ mod tests { use location::Location; use types::module_name::ModuleName; use types::{ - Class, ClassInstance, ClassKind, Module, SpecializationKey, Visibility, + Module, SpecializationKey, Type, TypeInstance, TypeKind, Visibility, }; fn name(db: &Database, shape: Shape) -> String { @@ -240,19 +240,19 @@ mod tests { let mut db = Database::new(); let mid = Module::alloc(&mut db, ModuleName::new("a.b.c"), "c.inko".into()); - let kind = ClassKind::Regular; + let kind = TypeKind::Regular; let vis = Visibility::Public; let loc = Location::default(); - let cls1 = Class::alloc(&mut db, "A".to_string(), kind, vis, mid, loc); - let cls2 = Class::alloc(&mut db, "B".to_string(), kind, vis, mid, loc); - let cls3 = Class::alloc(&mut db, "C".to_string(), kind, vis, mid, loc); - let cls4 = Class::alloc(&mut db, "D".to_string(), kind, vis, mid, loc); + let cls1 = Type::alloc(&mut db, "A".to_string(), kind, vis, mid, loc); + let cls2 = Type::alloc(&mut db, "B".to_string(), kind, vis, mid, loc); + let cls3 = Type::alloc(&mut db, "C".to_string(), kind, vis, mid, loc); + let cls4 = Type::alloc(&mut db, "D".to_string(), kind, vis, mid, loc); cls1.set_specialization_key( &mut db, SpecializationKey::new(vec![ Shape::Int(64, Sign::Signed), - Shape::Inline(ClassInstance::new(cls2)), + Shape::Inline(TypeInstance::new(cls2)), ]), ); cls2.set_specialization_key( @@ -261,13 +261,13 @@ mod tests { ); cls3.set_specialization_key( &mut db, - SpecializationKey::new(vec![Shape::InlineRef(ClassInstance::new( + SpecializationKey::new(vec![Shape::InlineRef(TypeInstance::new( cls2, ))]), ); cls4.set_specialization_key( &mut db, - SpecializationKey::new(vec![Shape::InlineMut(ClassInstance::new( + SpecializationKey::new(vec![Shape::InlineMut(TypeInstance::new( cls2, ))]), ); @@ -284,15 +284,15 @@ mod tests { assert_eq!(name(&db, Shape::Nil), "n"); assert_eq!(name(&db, Shape::Pointer), "p"); assert_eq!( - name(&db, Shape::Inline(ClassInstance::new(cls1))), + name(&db, Shape::Inline(TypeInstance::new(cls1))), "IOa.b.c.A#i64IOa.b.c.B#s" ); assert_eq!( - name(&db, Shape::InlineMut(ClassInstance::new(cls3))), + name(&db, Shape::InlineMut(TypeInstance::new(cls3))), "IMa.b.c.C#IRa.b.c.B#s" ); assert_eq!( - name(&db, Shape::InlineRef(ClassInstance::new(cls4))), + name(&db, Shape::InlineRef(TypeInstance::new(cls4))), "IRa.b.c.D#IMa.b.c.B#s" ); } diff --git a/compiler/src/type_check/define_types.rs b/compiler/src/type_check/define_types.rs index 9eca71823..a944a4676 100644 --- a/compiler/src/type_check/define_types.rs +++ b/compiler/src/type_check/define_types.rs @@ -2,7 +2,7 @@ use crate::diagnostics::DiagnosticId; use crate::hir; use crate::state::State; -use crate::type_check::graph::RecursiveClassChecker; +use crate::type_check::graph::RecursiveTypeChecker; use crate::type_check::{ define_type_bounds, CheckTypeSignature, DefineAndCheckTypeSignature, DefineTypeSignature, Rules, TypeScope, @@ -12,13 +12,13 @@ use std::path::PathBuf; use types::check::TypeChecker; use types::format::format_type; use types::{ - Class, ClassId, ClassInstance, ClassKind, Constant, Database, ModuleId, - Symbol, Trait, TraitId, TraitImplementation, TypeId, TypeRef, Visibility, + Constant, Database, ModuleId, Symbol, Trait, TraitId, TraitImplementation, + Type, TypeEnum, TypeId, TypeInstance, TypeKind, TypeRef, Visibility, ARRAY_INTERNAL_NAME, CONSTRUCTORS_LIMIT, ENUM_TAG_FIELD, ENUM_TAG_INDEX, - MAIN_CLASS, OPTION_CLASS, OPTION_MODULE, RESULT_CLASS, RESULT_MODULE, + MAIN_TYPE, OPTION_MODULE, OPTION_TYPE, RESULT_MODULE, RESULT_TYPE, }; -/// A compiler pass that defines classes and traits. +/// A compiler pass that defines types and traits. /// /// This pass _only_ defines the types, it doesn't define their type parameters, /// trait requirements, etc. @@ -42,11 +42,11 @@ impl<'a> DefineTypes<'a> { fn run(mut self, module: &mut hir::Module) { for expression in module.expressions.iter_mut() { match expression { - hir::TopLevelExpression::Class(ref mut node) => { - self.define_class(node); + hir::TopLevelExpression::Type(ref mut node) => { + self.define_type(node); } - hir::TopLevelExpression::ExternClass(ref mut node) => { - self.define_extern_class(node); + hir::TopLevelExpression::ExternType(ref mut node) => { + self.define_extern_type(node); } hir::TopLevelExpression::Trait(ref mut node) => { self.define_trait(node); @@ -59,28 +59,28 @@ impl<'a> DefineTypes<'a> { } } - fn define_class(&mut self, node: &mut hir::DefineClass) { + fn define_type(&mut self, node: &mut hir::DefineType) { let name = node.name.name.clone(); let module = self.module; let vis = Visibility::public(node.public); let loc = node.location; - let id = if let hir::ClassKind::Builtin = node.kind { + let id = if let hir::TypeKind::Builtin = node.kind { if !self.module.is_std(self.db()) { self.state.diagnostics.error( DiagnosticId::InvalidType, - "builtin classes can only be defined in 'std' modules", + "builtin types can only be defined in 'std' modules", self.file(), node.location, ); } - if let Some(id) = self.db().builtin_class(&name) { + if let Some(id) = self.db().builtin_type(&name) { id.set_module(self.db_mut(), module); id } else { self.state.diagnostics.error( DiagnosticId::InvalidType, - format!("'{}' isn't a valid builtin class", name), + format!("'{}' isn't a valid builtin type", name), self.file(), node.location, ); @@ -89,13 +89,13 @@ impl<'a> DefineTypes<'a> { } } else { let kind = match node.kind { - hir::ClassKind::Regular => ClassKind::Regular, - hir::ClassKind::Async => ClassKind::Async, - hir::ClassKind::Enum => ClassKind::Enum, + hir::TypeKind::Regular => TypeKind::Regular, + hir::TypeKind::Async => TypeKind::Async, + hir::TypeKind::Enum => TypeKind::Enum, _ => unreachable!(), }; - let cls = Class::alloc( + let cls = Type::alloc( self.db_mut(), name.clone(), kind, @@ -105,11 +105,11 @@ impl<'a> DefineTypes<'a> { ); match node.semantics { - hir::ClassSemantics::Default => {} - hir::ClassSemantics::Inline => { + hir::TypeSemantics::Default => {} + hir::TypeSemantics::Inline => { cls.set_inline_storage(self.db_mut()); } - hir::ClassSemantics::Copy => { + hir::TypeSemantics::Copy => { cls.set_copy_storage(self.db_mut()); } } @@ -124,21 +124,21 @@ impl<'a> DefineTypes<'a> { node.name.location, ); } else { - self.module.new_symbol(self.db_mut(), name, Symbol::Class(id)); + self.module.new_symbol(self.db_mut(), name, Symbol::Type(id)); } - node.class_id = Some(id); + node.type_id = Some(id); } - fn define_extern_class(&mut self, node: &mut hir::DefineExternClass) { + fn define_extern_type(&mut self, node: &mut hir::DefineExternType) { let name = node.name.name.clone(); let module = self.module; let vis = Visibility::public(node.public); let loc = node.location; - let id = Class::alloc( + let id = Type::alloc( self.db_mut(), name.clone(), - ClassKind::Extern, + TypeKind::Extern, vis, module, loc, @@ -151,10 +151,10 @@ impl<'a> DefineTypes<'a> { node.name.location, ); } else { - self.module.new_symbol(self.db_mut(), name, Symbol::Class(id)); + self.module.new_symbol(self.db_mut(), name, Symbol::Type(id)); } - node.class_id = Some(id); + node.type_id = Some(id); } fn define_trait(&mut self, node: &mut hir::DefineTrait) { @@ -216,7 +216,7 @@ impl<'a> DefineTypes<'a> { } } -/// A compiler pass that adds all trait implementations to their classes. +/// A compiler pass that adds all trait implementations to their types. pub(crate) struct ImplementTraits<'a> { state: &'a mut State, module: ModuleId, @@ -247,30 +247,30 @@ impl<'a> ImplementTraits<'a> { } fn implement_trait(&mut self, node: &mut hir::ImplementTrait) { - let class_name = &node.class_name.name; - let class_id = match self.module.use_symbol(self.db_mut(), class_name) { - Some(Symbol::Class(id)) => id, + let type_name = &node.type_name.name; + let type_id = match self.module.use_symbol(self.db_mut(), type_name) { + Some(Symbol::Type(id)) => id, Some(_) => { - self.state.diagnostics.not_a_class( - class_name, + self.state.diagnostics.not_a_type( + type_name, self.file(), - node.class_name.location, + node.type_name.location, ); return; } None => { self.state.diagnostics.undefined_symbol( - class_name, + type_name, self.file(), - node.class_name.location, + node.type_name.location, ); return; } }; - if !class_id.allow_trait_implementations(self.db()) { + if !type_id.allow_trait_implementations(self.db()) { self.state.diagnostics.error( DiagnosticId::InvalidImplementation, "traits can't be implemented for this type", @@ -284,13 +284,13 @@ impl<'a> ImplementTraits<'a> { let bounds = define_type_bounds( self.state, self.module, - class_id, + type_id, &mut node.bounds, ); - let class_ins = ClassInstance::rigid(self.db_mut(), class_id, &bounds); + let type_ins = TypeInstance::rigid(self.db_mut(), type_id, &bounds); let scope = TypeScope::with_bounds( self.module, - TypeId::ClassInstance(class_ins), + TypeEnum::TypeInstance(type_ins), None, &bounds, ); @@ -303,21 +303,21 @@ impl<'a> ImplementTraits<'a> { { let name = &node.trait_name.name.name; - if class_id + if type_id .trait_implementation(self.db(), instance.instance_of()) .is_some() { self.state.diagnostics.error( DiagnosticId::InvalidImplementation, format!( - "the trait '{}' is already implemented for class '{}'", - name, class_name + "the trait '{}' is already implemented for type '{}'", + name, type_name ), self.file(), node.location, ); } else { - class_id.add_trait_implementation( + type_id.add_trait_implementation( self.db_mut(), TraitImplementation { instance, bounds }, ); @@ -334,7 +334,7 @@ impl<'a> ImplementTraits<'a> { ); } - if class_id.is_copy_type(self.db()) { + if type_id.is_copy_type(self.db()) { self.state.diagnostics.error( DiagnosticId::InvalidImplementation, "Drop can't be implemented for 'copy' types", @@ -343,13 +343,13 @@ impl<'a> ImplementTraits<'a> { ); } - class_id.mark_as_having_destructor(self.db_mut()); + type_id.mark_as_having_destructor(self.db_mut()); } node.trait_instance = Some(instance); } - node.class_instance = Some(class_ins); + node.type_instance = Some(type_ins); } fn file(&self) -> PathBuf { @@ -394,7 +394,8 @@ impl<'a> DefineTraitRequirements<'a> { fn define_trait(&mut self, node: &mut hir::DefineTrait) { let trait_id = node.trait_id.unwrap(); - let scope = TypeScope::new(self.module, TypeId::Trait(trait_id), None); + let scope = + TypeScope::new(self.module, TypeEnum::Trait(trait_id), None); let rules = Rules::default(); for req in &mut node.requirements { @@ -475,7 +476,7 @@ impl<'a> CheckTraitImplementations<'a> { } fn implement_trait(&mut self, node: &hir::ImplementTrait) { - let class_ins = node.class_instance.unwrap(); + let type_ins = node.type_instance.unwrap(); let trait_ins = node.trait_instance.unwrap(); let mut checker = CheckTypeSignature::new(self.state, self.module); @@ -490,13 +491,13 @@ impl<'a> CheckTraitImplementations<'a> { for req in trait_ins.instance_of().required_traits(self.db()) { let mut checker = TypeChecker::new(self.db()); - if !checker.class_implements_trait(class_ins, req) { + if !checker.type_implements_trait(type_ins, req) { self.state.diagnostics.error( DiagnosticId::MissingTrait, format!( - "the trait '{}' isn't implemented for class '{}'", + "the trait '{}' isn't implemented for type '{}'", format_type(self.db(), req), - class_ins.instance_of().name(self.db()) + type_ins.instance_of().name(self.db()) ), self.file(), node.location, @@ -514,7 +515,7 @@ impl<'a> CheckTraitImplementations<'a> { } } -/// A compiler pass that defines the fields in a class. +/// A compiler pass that defines the fields in a type. pub(crate) struct DefineFields<'a> { state: &'a mut State, main_module: bool, @@ -542,27 +543,27 @@ impl<'a> DefineFields<'a> { fn run(mut self, module: &mut hir::Module) { for expr in &mut module.expressions { match expr { - hir::TopLevelExpression::Class(ref mut node) => { - self.define_class(node); + hir::TopLevelExpression::Type(ref mut node) => { + self.define_type(node); } - hir::TopLevelExpression::ExternClass(ref mut node) => { - self.define_extern_class(node); + hir::TopLevelExpression::ExternType(ref mut node) => { + self.define_extern_type(node); } _ => (), } } } - fn define_class(&mut self, node: &mut hir::DefineClass) { - let class_id = node.class_id.unwrap(); + fn define_type(&mut self, node: &mut hir::DefineType) { + let type_id = node.type_id.unwrap(); let mut id: usize = 0; - let scope = TypeScope::new(self.module, TypeId::Class(class_id), None); - let is_enum = class_id.kind(self.db()).is_enum(); - let is_copy = class_id.is_copy_type(self.db()); - let is_main = self.main_module && node.name.name == MAIN_CLASS; + let scope = TypeScope::new(self.module, TypeEnum::Type(type_id), None); + let is_enum = type_id.kind(self.db()).is_enum(); + let is_copy = type_id.is_copy_type(self.db()); + let is_main = self.main_module && node.name.name == MAIN_TYPE; for expr in &mut node.body { - let fnode = if let hir::ClassExpression::Field(ref mut n) = expr { + let fnode = if let hir::TypeExpression::Field(ref mut n) = expr { n } else { continue; @@ -580,7 +581,7 @@ impl<'a> DefineFields<'a> { break; } - if class_id.field(self.db(), &name).is_some() { + if type_id.field(self.db(), &name).is_some() { self.state.diagnostics.duplicate_field( &name, self.file(), @@ -612,15 +613,15 @@ impl<'a> DefineFields<'a> { ); } - if !class_id.is_public(self.db()) && vis == Visibility::Public { + if !type_id.is_public(self.db()) && vis == Visibility::Public { self.state .diagnostics - .public_field_private_class(self.file(), fnode.location); + .public_field_private_type(self.file(), fnode.location); } let module = self.module; let loc = fnode.location; - let field = class_id.new_field( + let field = type_id.new_field( self.db_mut(), name, id, @@ -635,15 +636,15 @@ impl<'a> DefineFields<'a> { } } - fn define_extern_class(&mut self, node: &mut hir::DefineExternClass) { - let class_id = node.class_id.unwrap(); + fn define_extern_type(&mut self, node: &mut hir::DefineExternType) { + let type_id = node.type_id.unwrap(); let mut id: usize = 0; - let scope = TypeScope::new(self.module, TypeId::Class(class_id), None); + let scope = TypeScope::new(self.module, TypeEnum::Type(type_id), None); for node in &mut node.fields { let name = node.name.name.clone(); - if class_id.field(self.db(), &name).is_some() { + if type_id.field(self.db(), &name).is_some() { self.state.diagnostics.duplicate_field( &name, self.file(), @@ -668,8 +669,8 @@ impl<'a> DefineFields<'a> { ) .define_type(&mut node.value_type); - // We can't allow heap values in external classes, as that would - // allow violating their single ownership constraints. + // We can't allow heap values in external types, as that would allow + // violating their single ownership constraints. if !typ.is_copy_type(self.db()) { self.state.diagnostics.not_a_copy_type( &format_type(self.db(), typ), @@ -678,15 +679,15 @@ impl<'a> DefineFields<'a> { ); } - if !class_id.is_public(self.db()) && vis == Visibility::Public { + if !type_id.is_public(self.db()) && vis == Visibility::Public { self.state .diagnostics - .public_field_private_class(self.file(), node.location); + .public_field_private_type(self.file(), node.location); } let module = self.module; let loc = node.location; - let field = class_id.new_field( + let field = type_id.new_field( self.db_mut(), name, id, @@ -714,7 +715,7 @@ impl<'a> DefineFields<'a> { } } -/// A compiler pass that defines class and trait types parameters, except for +/// A compiler pass that defines type and trait types parameters, except for /// their requirements. pub(crate) struct DefineTypeParameters<'a> { state: &'a mut State, @@ -737,8 +738,8 @@ impl<'a> DefineTypeParameters<'a> { fn run(mut self, module: &mut hir::Module) { for expr in module.expressions.iter_mut() { match expr { - hir::TopLevelExpression::Class(ref mut node) => { - self.define_class(node); + hir::TopLevelExpression::Type(ref mut node) => { + self.define_type(node); } hir::TopLevelExpression::Trait(ref mut node) => { self.define_trait(node); @@ -748,8 +749,8 @@ impl<'a> DefineTypeParameters<'a> { } } - fn define_class(&mut self, node: &mut hir::DefineClass) { - let id = node.class_id.unwrap(); + fn define_type(&mut self, node: &mut hir::DefineType) { + let id = node.type_id.unwrap(); let is_copy = id.is_copy_type(self.db()); for param in &mut node.type_parameters { @@ -814,7 +815,7 @@ impl<'a> DefineTypeParameters<'a> { } } -/// A compiler pass that defines the required traits for class and trait type +/// A compiler pass that defines the required traits for type and trait type /// parameters. pub(crate) struct DefineTypeParameterRequirements<'a> { state: &'a mut State, @@ -837,8 +838,8 @@ impl<'a> DefineTypeParameterRequirements<'a> { fn run(mut self, module: &mut hir::Module) { for expr in module.expressions.iter_mut() { match expr { - hir::TopLevelExpression::Class(ref mut node) => { - self.define_class(node); + hir::TopLevelExpression::Type(ref mut node) => { + self.define_type(node); } hir::TopLevelExpression::Trait(ref mut node) => { self.define_trait(node); @@ -848,14 +849,14 @@ impl<'a> DefineTypeParameterRequirements<'a> { } } - fn define_class(&mut self, node: &mut hir::DefineClass) { - let self_type = TypeId::Class(node.class_id.unwrap()); + fn define_type(&mut self, node: &mut hir::DefineType) { + let self_type = TypeEnum::Type(node.type_id.unwrap()); self.define_requirements(&mut node.type_parameters, self_type); } fn define_trait(&mut self, node: &mut hir::DefineTrait) { - let self_type = TypeId::Trait(node.trait_id.unwrap()); + let self_type = TypeEnum::Trait(node.trait_id.unwrap()); self.define_requirements(&mut node.type_parameters, self_type); } @@ -863,7 +864,7 @@ impl<'a> DefineTypeParameterRequirements<'a> { fn define_requirements( &mut self, parameters: &mut Vec, - self_type: TypeId, + self_type: TypeEnum, ) { let scope = TypeScope::new(self.module, self_type, None); let rules = Rules::default(); @@ -894,7 +895,7 @@ impl<'a> DefineTypeParameterRequirements<'a> { } } -/// A compiler pass that verifies if type parameters on classes and traits are +/// A compiler pass that verifies if type parameters on types and traits are /// correct. pub(crate) struct CheckTypeParameters<'a> { state: &'a mut State, @@ -916,7 +917,7 @@ impl<'a> CheckTypeParameters<'a> { fn run(mut self, module: &mut hir::Module) { for expr in module.expressions.iter_mut() { match expr { - hir::TopLevelExpression::Class(ref node) => { + hir::TopLevelExpression::Type(ref node) => { self.check_type_parameters(&node.type_parameters); } hir::TopLevelExpression::Trait(ref node) => { @@ -956,41 +957,41 @@ impl<'a> InsertPrelude<'a> { } pub(crate) fn run(&mut self) { - self.add_class(ClassId::int()); - self.add_class(ClassId::float()); - self.add_class(ClassId::string()); - self.add_class(ClassId::array()); - self.add_class(ClassId::boolean()); - self.add_class(ClassId::nil()); - self.add_class(ClassId::byte_array()); - - self.import_class(OPTION_MODULE, OPTION_CLASS); - self.import_class(RESULT_MODULE, RESULT_CLASS); - self.import_class("std.map", "Map"); + self.add_type(TypeId::int()); + self.add_type(TypeId::float()); + self.add_type(TypeId::string()); + self.add_type(TypeId::array()); + self.add_type(TypeId::boolean()); + self.add_type(TypeId::nil()); + self.add_type(TypeId::byte_array()); + + self.import_type(OPTION_MODULE, OPTION_TYPE); + self.import_type(RESULT_MODULE, RESULT_TYPE); + self.import_type("std.map", "Map"); self.import_method("std.process", "panic"); // This name is used when desugaring array literals. self.module.new_symbol( self.db_mut(), ARRAY_INTERNAL_NAME.to_string(), - Symbol::Class(ClassId::array()), + Symbol::Type(TypeId::array()), ); } - fn add_class(&mut self, id: ClassId) { + fn add_type(&mut self, id: TypeId) { let name = id.name(self.db()).clone(); if self.module.symbol_exists(self.db(), &name) { return; } - self.module.new_symbol(self.db_mut(), name, Symbol::Class(id)); + self.module.new_symbol(self.db_mut(), name, Symbol::Type(id)); } - fn import_class(&mut self, module: &str, class: &str) { - let id = self.state.db.class_in_module(module, class); + fn import_type(&mut self, module: &str, name: &str) { + let id = self.state.db.type_in_module(module, name); - self.add_class(id); + self.add_type(id); } fn import_method(&mut self, module: &str, method: &str) { @@ -1021,7 +1022,7 @@ impl<'a> InsertPrelude<'a> { } } -/// A compiler pass that defines the constructors for an enum class. +/// A compiler pass that defines the constructors for an enum type. pub(crate) struct DefineConstructors<'a> { state: &'a mut State, module: ModuleId, @@ -1041,24 +1042,24 @@ impl<'a> DefineConstructors<'a> { fn run(mut self, module: &mut hir::Module) { for expr in module.expressions.iter_mut() { - if let hir::TopLevelExpression::Class(ref mut node) = expr { - self.define_class(node); + if let hir::TopLevelExpression::Type(ref mut node) = expr { + self.define_type(node); } } } - fn define_class(&mut self, node: &mut hir::DefineClass) { - let class_id = node.class_id.unwrap(); - let is_enum = class_id.kind(self.db()).is_enum(); - let is_copy = class_id.is_copy_type(self.db()); + fn define_type(&mut self, node: &mut hir::DefineType) { + let type_id = node.type_id.unwrap(); + let is_enum = type_id.kind(self.db()).is_enum(); + let is_copy = type_id.is_copy_type(self.db()); let rules = Rules::default(); - let scope = TypeScope::new(self.module, TypeId::Class(class_id), None); + let scope = TypeScope::new(self.module, TypeEnum::Type(type_id), None); let mut constructors_count = 0; let mut args_count = 0; for expr in &mut node.body { let node = - if let hir::ClassExpression::Constructor(ref mut node) = expr { + if let hir::TypeExpression::Constructor(ref mut node) = expr { node } else { continue; @@ -1077,7 +1078,7 @@ impl<'a> DefineConstructors<'a> { let name = &node.name.name; - if class_id.constructor(self.db(), name).is_some() { + if type_id.constructor(self.db(), name).is_some() { self.state.diagnostics.error( DiagnosticId::DuplicateSymbol, format!("the constructor '{}' is already defined", name), @@ -1131,7 +1132,7 @@ impl<'a> DefineConstructors<'a> { } constructors_count += 1; - class_id.new_constructor( + type_id.new_constructor( self.db_mut(), name.to_string(), args, @@ -1154,9 +1155,9 @@ impl<'a> DefineConstructors<'a> { let vis = Visibility::TypePrivate; let tag_typ = TypeRef::foreign_unsigned_int(16); let tag_name = ENUM_TAG_FIELD.to_string(); - let loc = class_id.location(db); + let loc = type_id.location(db); - class_id.new_field( + type_id.new_field( db, tag_name, ENUM_TAG_INDEX, @@ -1176,7 +1177,7 @@ impl<'a> DefineConstructors<'a> { // generating the LLVM layouts. let typ = TypeRef::Unknown; - class_id.new_field( + type_id.new_field( db, id.to_string(), id, @@ -1202,16 +1203,16 @@ impl<'a> DefineConstructors<'a> { } } -/// A compiler pass that adds errors for recursive stack allocated classes. +/// A compiler pass that adds errors for recursive stack allocated types. pub(crate) fn check_recursive_types( state: &mut State, modules: &[hir::Module], ) -> bool { for module in modules { for expr in &module.expressions { - let (class, loc) = match expr { - hir::TopLevelExpression::Class(ref n) => { - let id = n.class_id.unwrap(); + let (typ, loc) = match expr { + hir::TopLevelExpression::Type(ref n) => { + let id = n.type_id.unwrap(); // Heap types _are_ allowed to be recursive as they can't // recursive into themselves without indirection. @@ -1221,15 +1222,15 @@ pub(crate) fn check_recursive_types( (id, n.location) } - hir::TopLevelExpression::ExternClass(ref n) => { - (n.class_id.unwrap(), n.location) + hir::TopLevelExpression::ExternType(ref n) => { + (n.type_id.unwrap(), n.location) } _ => continue, }; // The recursion check is extracted into a separate type so we can // separate visiting the IR and performing the actual check. - if !RecursiveClassChecker::new(&state.db).is_recursive(class) { + if !RecursiveTypeChecker::new(&state.db).is_recursive(typ) { continue; } @@ -1255,8 +1256,8 @@ mod tests { use ast::parser::Parser; use types::module_name::ModuleName; use types::{ - ClassId, ConstantId, TraitId, TraitInstance, TypeBounds, - FIRST_USER_CLASS_ID, + ConstantId, TraitId, TraitInstance, TypeBounds, TypeId, + FIRST_USER_TYPE_ID, }; fn get_trait(db: &mut Database, module: ModuleId, name: &str) -> TraitId { @@ -1267,17 +1268,17 @@ mod tests { } } - fn get_class(db: &mut Database, module: ModuleId, name: &str) -> ClassId { - if let Some(Symbol::Class(id)) = module.use_symbol(db, name) { + fn get_type(db: &mut Database, module: ModuleId, name: &str) -> TypeId { + if let Some(Symbol::Type(id)) = module.use_symbol(db, name) { id } else { panic!("expected a Class"); } } - fn class_expr(module: &hir::Module) -> &hir::DefineClass { + fn type_expr(module: &hir::Module) -> &hir::DefineType { match &module.expressions[0] { - hir::TopLevelExpression::Class(ref node) => node, + hir::TopLevelExpression::Type(ref node) => node, _ => panic!("expected a DefineClass node"), } } @@ -1315,49 +1316,49 @@ mod tests { } #[test] - fn test_define_class() { + fn test_define_type() { let mut state = State::new(Config::new()); - let mut modules = parse(&mut state, "class A {}"); + let mut modules = parse(&mut state, "type A {}"); assert!(DefineTypes::run_all(&mut state, &mut modules)); - let id = ClassId(FIRST_USER_CLASS_ID + 1); + let id = TypeId(FIRST_USER_TYPE_ID + 1); assert_eq!(state.diagnostics.iter().count(), 0); - assert_eq!(class_expr(&modules[0]).class_id, Some(id)); + assert_eq!(type_expr(&modules[0]).type_id, Some(id)); assert_eq!(id.name(&state.db), &"A".to_string()); assert!(!id.kind(&state.db).is_async()); assert_eq!( modules[0].module_id.use_symbol(&mut state.db, "A"), - Some(Symbol::Class(id)) + Some(Symbol::Type(id)) ); } #[test] - fn test_define_async_class() { + fn test_define_async_type() { let mut state = State::new(Config::new()); - let mut modules = parse(&mut state, "class async A {}"); + let mut modules = parse(&mut state, "type async A {}"); assert!(DefineTypes::run_all(&mut state, &mut modules)); - let id = ClassId(FIRST_USER_CLASS_ID + 1); + let id = TypeId(FIRST_USER_TYPE_ID + 1); assert_eq!(state.diagnostics.iter().count(), 0); - assert_eq!(class_expr(&modules[0]).class_id, Some(id)); + assert_eq!(type_expr(&modules[0]).type_id, Some(id)); assert_eq!(id.name(&state.db), &"A".to_string()); assert!(id.kind(&state.db).is_async()); assert_eq!( modules[0].module_id.use_symbol(&mut state.db, "A"), - Some(Symbol::Class(id)) + Some(Symbol::Type(id)) ); } #[test] - fn test_define_empty_enum_class() { + fn test_define_empty_enum_type() { let mut state = State::new(Config::new()); - let mut modules = parse(&mut state, "class enum A {}"); + let mut modules = parse(&mut state, "type enum A {}"); assert!(DefineTypes::run_all(&mut state, &mut modules)); assert!(!DefineConstructors::run_all(&mut state, &mut modules)); @@ -1394,10 +1395,10 @@ mod tests { module, Location::default(), ); - let string = Class::alloc( + let string = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1411,7 +1412,7 @@ mod tests { module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string), + Symbol::Type(string), ); define_drop_trait(&mut state); @@ -1436,10 +1437,10 @@ mod tests { module, Location::default(), ); - let string = Class::alloc( + let string = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1455,7 +1456,7 @@ mod tests { module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string), + Symbol::Type(string), ); define_drop_trait(&mut state); @@ -1467,10 +1468,10 @@ mod tests { assert_eq!(imp.instance.instance_of(), to_string); - if let TypeRef::Owned(TypeId::ClassInstance(ins)) = arg { + if let TypeRef::Owned(TypeEnum::TypeInstance(ins)) = arg { assert_eq!(ins.instance_of(), string); } else { - panic!("Expected the type argument to be a class instance"); + panic!("Expected the type argument to be a type instance"); } } @@ -1487,10 +1488,10 @@ mod tests { module, Location::default(), ); - let array = Class::alloc( + let array = Type::alloc( &mut state.db, "Array".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1505,7 +1506,7 @@ mod tests { module.new_symbol( &mut state.db, "Array".to_string(), - Symbol::Class(array), + Symbol::Type(array), ); define_drop_trait(&mut state); @@ -1531,10 +1532,10 @@ mod tests { module, Location::default(), ); - let array = Class::alloc( + let array = Type::alloc( &mut state.db, "Array".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1548,7 +1549,7 @@ mod tests { module.new_symbol( &mut state.db, "Array".to_string(), - Symbol::Class(array), + Symbol::Type(array), ); define_drop_trait(&mut state); @@ -1561,7 +1562,7 @@ mod tests { } #[test] - fn test_implement_trait_with_undefined_class() { + fn test_implement_trait_with_undefined_type() { let mut state = State::new(Config::new()); let mut modules = parse(&mut state, "impl ToString for String {}"); let module = ModuleId(0); @@ -1589,7 +1590,7 @@ mod tests { } #[test] - fn test_implement_trait_with_invalid_class() { + fn test_implement_trait_with_invalid_type() { let mut state = State::new(Config::new()); let mut modules = parse(&mut state, "impl ToString for String {}"); let module = ModuleId(0); @@ -1671,10 +1672,10 @@ mod tests { module, Location::default(), ); - let string = Class::alloc( + let string = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1700,7 +1701,7 @@ mod tests { module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string), + Symbol::Type(string), ); define_drop_trait(&mut state); @@ -1729,10 +1730,10 @@ mod tests { module, Location::default(), ); - let string = Class::alloc( + let string = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1750,7 +1751,7 @@ mod tests { module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string), + Symbol::Type(string), ); define_drop_trait(&mut state); @@ -1769,82 +1770,82 @@ mod tests { #[test] fn test_define_field() { let mut state = State::new(Config::new()); - let string = Class::alloc( + let string = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, ModuleId(0), Location::default(), ); - let string_ins = ClassInstance::new(string); + let string_ins = TypeInstance::new(string); let mut modules = - parse(&mut state, "class Person { let @name: String }"); + parse(&mut state, "type Person { let @name: String }"); let module = ModuleId(0); module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string), + Symbol::Type(string), ); DefineTypes::run_all(&mut state, &mut modules); assert!(DefineFields::run_all(&mut state, &mut modules)); - let person = get_class(&mut state.db, module, "Person"); + let person = get_type(&mut state.db, module, "Person"); let field = person.field(&state.db, "name").unwrap(); assert_eq!( field.value_type(&state.db), - TypeRef::Owned(TypeId::ClassInstance(string_ins)) + TypeRef::Owned(TypeEnum::TypeInstance(string_ins)) ); } #[test] fn test_define_duplicate_field() { let mut state = State::new(Config::new()); - let string = Class::alloc( + let string = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, ModuleId(0), Location::default(), ); - let int = Class::alloc( + let int = Type::alloc( &mut state.db, "Int".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, ModuleId(0), Location::default(), ); let mut modules = parse( &mut state, - "class Person { let @name: String let @name: Int }", + "type Person { let @name: String let @name: Int }", ); let module = ModuleId(0); module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string), + Symbol::Type(string), ); - module.new_symbol(&mut state.db, "Int".to_string(), Symbol::Class(int)); + module.new_symbol(&mut state.db, "Int".to_string(), Symbol::Type(int)); DefineTypes::run_all(&mut state, &mut modules); assert!(!DefineFields::run_all(&mut state, &mut modules)); - let person = get_class(&mut state.db, module, "Person"); + let person = get_type(&mut state.db, module, "Person"); let field = person.field(&state.db, "name").unwrap(); - let string_ins = ClassInstance::new(string); + let string_ins = TypeInstance::new(string); assert_eq!( field.value_type(&state.db), - TypeRef::Owned(TypeId::ClassInstance(string_ins)) + TypeRef::Owned(TypeEnum::TypeInstance(string_ins)) ); let error = state.diagnostics.iter().next().unwrap(); @@ -1856,7 +1857,7 @@ mod tests { #[test] fn test_define_field_with_self_type() { let mut state = State::new(Config::new()); - let mut modules = parse(&mut state, "class Person { let @name: Self }"); + let mut modules = parse(&mut state, "type Person { let @name: Self }"); DefineTypes::run_all(&mut state, &mut modules); @@ -1910,17 +1911,17 @@ mod tests { } #[test] - fn test_define_class_type_parameter() { + fn test_define_type_type_parameter() { let mut state = State::new(Config::new()); - let mut modules = parse(&mut state, "class A[T] {}"); + let mut modules = parse(&mut state, "type A[T] {}"); let module = ModuleId(0); DefineTypes::run_all(&mut state, &mut modules); assert!(DefineTypeParameters::run_all(&mut state, &mut modules)); - let class_a = get_class(&mut state.db, module, "A"); - let params = class_a.type_parameters(&state.db); + let type_a = get_type(&mut state.db, module, "A"); + let params = type_a.type_parameters(&state.db); assert_eq!(params.len(), 1); @@ -1928,15 +1929,15 @@ mod tests { assert_eq!(param.name(&state.db), &"T"); assert_eq!( - class_expr(&modules[0]).type_parameters[0].type_parameter_id, + type_expr(&modules[0]).type_parameters[0].type_parameter_id, Some(param) ); } #[test] - fn test_define_duplicate_class_type_parameter() { + fn test_define_duplicate_type_type_parameter() { let mut state = State::new(Config::new()); - let mut modules = parse(&mut state, "class A[T, T] {}"); + let mut modules = parse(&mut state, "type A[T, T] {}"); DefineTypes::run_all(&mut state, &mut modules); @@ -1950,7 +1951,7 @@ mod tests { } #[test] - fn test_define_class_type_parameter_requirements() { + fn test_define_type_type_parameter_requirements() { let mut state = State::new(Config::new()); let module = ModuleId(0); let debug = Trait::alloc( @@ -1960,7 +1961,7 @@ mod tests { module, Location::default(), ); - let mut modules = parse(&mut state, "class Array[T: Debug] {}"); + let mut modules = parse(&mut state, "type Array[T: Debug] {}"); module.new_symbol( &mut state.db, @@ -1976,7 +1977,7 @@ mod tests { &mut modules )); - let array = get_class(&mut state.db, module, "Array"); + let array = get_type(&mut state.db, module, "Array"); let param = array.type_parameters(&state.db)[0]; assert_eq!(param.requirements(&state.db)[0].instance_of(), debug); @@ -2050,7 +2051,7 @@ mod tests { } #[test] - fn test_check_type_parameters_with_class() { + fn test_check_type_parameters_with_type() { let mut state = State::new(Config::new()); let module = ModuleId(0); let debug = Trait::alloc( @@ -2063,7 +2064,7 @@ mod tests { debug.new_type_parameter(&mut state.db, "T".to_string()); - let mut modules = parse(&mut state, "class Array[T: Debug] {}"); + let mut modules = parse(&mut state, "type Array[T: Debug] {}"); module.new_symbol( &mut state.db, diff --git a/compiler/src/type_check/expressions.rs b/compiler/src/type_check/expressions.rs index 3f3ae9bf7..008eae4e9 100644 --- a/compiler/src/type_check/expressions.rs +++ b/compiler/src/type_check/expressions.rs @@ -12,17 +12,17 @@ use types::check::{Environment, TypeChecker}; use types::format::{format_type, format_type_with_arguments}; use types::resolve::TypeResolver; use types::{ - Block, CallInfo, CallKind, ClassId, ClassInstance, Closure, - ClosureCallInfo, ClosureId, ConstantKind, ConstantPatternKind, Database, - FieldId, FieldInfo, IdentifierKind, IntrinsicCall, MethodId, MethodLookup, - ModuleId, Receiver, Sign, Symbol, ThrowKind, TraitId, TraitInstance, - TypeArguments, TypeBounds, TypeId, TypeRef, Variable, VariableId, - CALL_METHOD, DEREF_POINTER_FIELD, + Block, CallInfo, CallKind, Closure, ClosureCallInfo, ClosureId, + ConstantKind, ConstantPatternKind, Database, FieldId, FieldInfo, + IdentifierKind, IntrinsicCall, MethodId, MethodLookup, ModuleId, Receiver, + Sign, Symbol, ThrowKind, TraitId, TraitInstance, TypeArguments, TypeBounds, + TypeEnum, TypeId, TypeInstance, TypeRef, Variable, VariableId, CALL_METHOD, + DEREF_POINTER_FIELD, }; const IGNORE_VARIABLE: &str = "_"; -/// The maximum number of methods that a single class can define. +/// The maximum number of methods that a single type can define. /// /// We subtract 1 to account for the generated dropper methods, as these methods /// are generated later. @@ -269,9 +269,9 @@ impl MethodCall { fn new( state: &mut State, module: ModuleId, - caller: Option<(MethodId, &HashSet)>, + caller: Option<(MethodId, &HashSet)>, receiver: TypeRef, - receiver_id: TypeId, + receiver_id: TypeEnum, method: MethodId, ) -> Self { // When checking arguments we need access to the type arguments of the @@ -292,9 +292,9 @@ impl MethodCall { // Static methods may use/return type parameters of the surrounding // type, so we also need to create placeholders for those. if method.is_static(&state.db) { - if let TypeId::Class(class) = receiver_id { - if class.is_generic(&state.db) { - for param in class.type_parameters(&state.db) { + if let TypeEnum::Type(typ) = receiver_id { + if typ.is_generic(&state.db) { + for param in typ.type_parameters(&state.db) { type_arguments.assign( param, TypeRef::placeholder(&mut state.db, Some(param)), @@ -309,12 +309,12 @@ impl MethodCall { // make sure those type parameters are mapped to the correct final // values, so we have to expose them to the call's type arguments. match receiver_id { - TypeId::TraitInstance(ins) => copy_inherited_type_arguments( + TypeEnum::TraitInstance(ins) => copy_inherited_type_arguments( &state.db, ins, &mut type_arguments, ), - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id) => { + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id) => { for ins in id.requirements(&state.db) { copy_inherited_type_arguments( &state.db, @@ -349,8 +349,10 @@ impl MethodCall { // from some deeply nested type (e.g. a type parameter // requirement), we still remap it correctly. for (&k, &v) in caller.bounds(&state.db).iter() { - type_arguments - .assign(k, TypeRef::Any(TypeId::RigidTypeParameter(v))); + type_arguments.assign( + k, + TypeRef::Any(TypeEnum::RigidTypeParameter(v)), + ); } caller.bounds(&state.db).union(method.bounds(&state.db)) @@ -373,13 +375,13 @@ impl MethodCall { if rec_is_rigid { for val in type_arguments.values_mut() { *val = match val { - TypeRef::Any(TypeId::TypeParameter(id)) => { - TypeRef::Any(TypeId::RigidTypeParameter( + TypeRef::Any(TypeEnum::TypeParameter(id)) => { + TypeRef::Any(TypeEnum::RigidTypeParameter( bounds.get(*id).unwrap_or(*id), )) } - TypeRef::Owned(TypeId::TypeParameter(id)) => { - TypeRef::Owned(TypeId::RigidTypeParameter( + TypeRef::Owned(TypeEnum::TypeParameter(id)) => { + TypeRef::Owned(TypeEnum::RigidTypeParameter( bounds.get(*id).unwrap_or(*id), )) } @@ -675,14 +677,14 @@ impl<'a> Expressions<'a> { fn run(mut self, module: &mut hir::Module) { for expression in module.expressions.iter_mut() { match expression { - hir::TopLevelExpression::Class(ref mut n) => { - self.define_class(n); + hir::TopLevelExpression::Type(ref mut n) => { + self.define_type(n); } hir::TopLevelExpression::Trait(ref mut n) => { self.define_trait(n); } hir::TopLevelExpression::Reopen(ref mut n) => { - self.reopen_class(n); + self.reopen_type(n); } hir::TopLevelExpression::Implement(ref mut n) => { self.implement_trait(n); @@ -695,15 +697,15 @@ impl<'a> Expressions<'a> { } } - fn define_class(&mut self, node: &mut hir::DefineClass) { - let id = node.class_id.unwrap(); + fn define_type(&mut self, node: &mut hir::DefineType) { + let id = node.type_id.unwrap(); let num_methods = id.number_of_methods(self.db()); if num_methods > METHODS_IN_CLASS_LIMIT { self.state.diagnostics.error( DiagnosticId::InvalidType, format!( - "the number of methods defined in this class ({}) \ + "the number of methods defined in this type ({}) \ exceeds the maximum of {} methods", num_methods, METHODS_IN_CLASS_LIMIT ), @@ -716,13 +718,13 @@ impl<'a> Expressions<'a> { for node in &mut node.body { match node { - hir::ClassExpression::AsyncMethod(ref mut n) => { + hir::TypeExpression::AsyncMethod(ref mut n) => { self.define_async_method(n); } - hir::ClassExpression::InstanceMethod(ref mut n) => { + hir::TypeExpression::InstanceMethod(ref mut n) => { self.define_instance_method(n); } - hir::ClassExpression::StaticMethod(ref mut n) => { + hir::TypeExpression::StaticMethod(ref mut n) => { self.define_static_method(n); } _ => {} @@ -730,16 +732,16 @@ impl<'a> Expressions<'a> { } } - fn reopen_class(&mut self, node: &mut hir::ReopenClass) { + fn reopen_type(&mut self, node: &mut hir::ReopenType) { for node in &mut node.body { match node { - hir::ReopenClassExpression::InstanceMethod(ref mut n) => { + hir::ReopenTypeExpression::InstanceMethod(ref mut n) => { self.define_instance_method(n) } - hir::ReopenClassExpression::StaticMethod(ref mut n) => { + hir::ReopenTypeExpression::StaticMethod(ref mut n) => { self.define_static_method(n) } - hir::ReopenClassExpression::AsyncMethod(ref mut n) => { + hir::ReopenTypeExpression::AsyncMethod(ref mut n) => { self.define_async_method(n) } } @@ -1162,8 +1164,8 @@ impl<'a> CheckConstant<'a> { // Mutating constant arrays isn't safe, so they're typed as `ref // Array[T]` instead of `Array[T]`. - let ary = TypeRef::Ref(TypeId::ClassInstance( - ClassInstance::with_types(self.db_mut(), ClassId::array(), types), + let ary = TypeRef::Ref(TypeEnum::TypeInstance( + TypeInstance::with_types(self.db_mut(), TypeId::array(), types), )); node.resolved_type = ary; @@ -1175,8 +1177,8 @@ impl<'a> CheckConstant<'a> { receiver: TypeRef, name: &str, location: Location, - ) -> Option<(TypeId, MethodId)> { - let rec_id = match receiver.type_id(self.db()) { + ) -> Option<(TypeEnum, MethodId)> { + let rec_id = match receiver.as_type_enum(self.db()) { Ok(id) => id, Err(TypeRef::Error) => return None, Err(typ) => { @@ -1253,13 +1255,13 @@ struct CheckMethodBody<'a> { method: MethodId, /// The type ID of the receiver of the surrounding method. - self_type: TypeId, + self_type: TypeEnum, /// Any bounds to apply to type parameters. bounds: &'a TypeBounds, /// The type IDs that are or originate from `self`. - self_types: HashSet, + self_types: HashSet, } impl<'a> CheckMethodBody<'a> { @@ -1267,13 +1269,13 @@ impl<'a> CheckMethodBody<'a> { state: &'a mut State, module: ModuleId, method: MethodId, - self_type: TypeId, + self_type: TypeEnum, bounds: &'a TypeBounds, ) -> Self { - let mut self_types: HashSet = method + let mut self_types: HashSet = method .fields(&state.db) .into_iter() - .filter_map(|(_, typ)| typ.type_id(&state.db).ok()) + .filter_map(|(_, typ)| typ.as_type_enum(&state.db).ok()) .collect(); self_types.insert(self_type); @@ -1507,7 +1509,7 @@ impl<'a> CheckMethodBody<'a> { scope: &mut LexicalScope, ) -> TypeRef { let types = self.input_expressions(&mut node.values, scope); - let class = if let Some(id) = ClassId::tuple(types.len()) { + let typ = if let Some(id) = TypeId::tuple(types.len()) { id } else { self.state.diagnostics.tuple_size_error(self.file(), node.location); @@ -1515,11 +1517,11 @@ impl<'a> CheckMethodBody<'a> { return TypeRef::Error; }; - let tuple = TypeRef::Owned(TypeId::ClassInstance( - ClassInstance::with_types(self.db_mut(), class, types.clone()), + let tuple = TypeRef::Owned(TypeEnum::TypeInstance( + TypeInstance::with_types(self.db_mut(), typ, types.clone()), )); - node.class_id = Some(class); + node.type_id = Some(typ); node.resolved_type = tuple; node.value_types = types; node.resolved_type @@ -1642,8 +1644,8 @@ impl<'a> CheckMethodBody<'a> { hir::Pattern::Tuple(ref mut n) => { self.tuple_pattern(n, value_type, pattern); } - hir::Pattern::Class(ref mut n) => { - self.class_pattern(n, value_type, pattern); + hir::Pattern::Type(ref mut n) => { + self.type_pattern(n, value_type, pattern); } hir::Pattern::Int(ref mut n) => { self.int_pattern(n, value_type); @@ -1867,10 +1869,10 @@ impl<'a> CheckMethodBody<'a> { } let ins = match value_type { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) if ins.instance_of().kind(self.db()).is_tuple() => { ins @@ -1925,9 +1927,9 @@ impl<'a> CheckMethodBody<'a> { node.field_ids = fields; } - fn class_pattern( + fn type_pattern( &mut self, - node: &mut hir::ClassPattern, + node: &mut hir::TypePattern, value_type: TypeRef, pattern: &mut Pattern, ) { @@ -1937,7 +1939,7 @@ impl<'a> CheckMethodBody<'a> { } let Some(ins) = - value_type.as_class_instance_for_pattern_matching(self.db()) + value_type.as_type_instance_for_pattern_matching(self.db()) else { self.state.diagnostics.error( DiagnosticId::InvalidType, @@ -1953,9 +1955,9 @@ impl<'a> CheckMethodBody<'a> { return; }; - let class = ins.instance_of(); + let typ = ins.instance_of(); - if class.has_destructor(self.db()) { + if typ.has_destructor(self.db()) { self.state.diagnostics.error( DiagnosticId::InvalidType, format!( @@ -1968,21 +1970,21 @@ impl<'a> CheckMethodBody<'a> { ); } - if class.kind(self.db()).is_enum() { + if typ.kind(self.db()).is_enum() { self.state.diagnostics.error( DiagnosticId::InvalidType, - "enum classes don't support class patterns", + "enum types don't support type patterns", self.file(), node.location, ); } let immutable = value_type.is_ref(self.db()); - let args = TypeArguments::for_class(self.db(), ins); + let args = TypeArguments::for_type(self.db(), ins); for node in &mut node.values { let name = &node.field.name; - let field = if let Some(f) = class.field(self.db(), name) { + let field = if let Some(f) = typ.field(self.db(), name) { f } else { self.state.diagnostics.error( @@ -2012,7 +2014,7 @@ impl<'a> CheckMethodBody<'a> { self.pattern(&mut node.pattern, field_type, pattern); } - node.class_id = Some(class); + node.type_id = Some(typ); } fn int_pattern(&mut self, node: &mut hir::IntLiteral, input_type: TypeRef) { @@ -2087,7 +2089,7 @@ impl<'a> CheckMethodBody<'a> { self.state.diagnostics.error( DiagnosticId::InvalidType, format!( - "this pattern expects an enum class, \ + "this pattern expects an enum type, \ but the input type is '{}'", format_type(self.db(), value_type), ), @@ -2100,9 +2102,9 @@ impl<'a> CheckMethodBody<'a> { }; let name = &node.name.name; - let class = ins.instance_of(); + let typ = ins.instance_of(); - let constructor = if let Some(v) = class.constructor(self.db(), name) { + let constructor = if let Some(v) = typ.constructor(self.db(), name) { v } else { self.state.diagnostics.undefined_constructor( @@ -2131,7 +2133,7 @@ impl<'a> CheckMethodBody<'a> { } let immutable = value_type.is_ref(self.db()); - let args = TypeArguments::for_class(self.db(), ins); + let args = TypeArguments::for_type(self.db(), ins); let bounds = self.bounds; for (patt, member) in node.values.iter_mut().zip(members.into_iter()) { @@ -2403,9 +2405,9 @@ impl<'a> CheckMethodBody<'a> { if exp.is_uni(self.db()) && closure.can_infer_as_uni(self.db()) => { - TypeRef::Uni(TypeId::Closure(closure)) + TypeRef::Uni(TypeEnum::Closure(closure)) } - _ => TypeRef::Owned(TypeId::Closure(closure)), + _ => TypeRef::Owned(TypeEnum::Closure(closure)), }; node.closure_id = Some(closure); @@ -2427,7 +2429,7 @@ impl<'a> CheckMethodBody<'a> { let module = self.module; let (rec, rec_id, rec_kind, method) = { let rec = scope.surrounding_type; - let rec_id = rec.type_id(self.db()).unwrap(); + let rec_id = rec.as_type_enum(self.db()).unwrap(); match rec_id.lookup_method(self.db(), &node.name, module, false) { MethodLookup::Ok(method) => { @@ -2453,10 +2455,10 @@ impl<'a> CheckMethodBody<'a> { return node.resolved_type; } - Some(Symbol::Class(id)) if receiver => { - return TypeRef::Owned(TypeId::Class(id)); + Some(Symbol::Type(id)) if receiver => { + return TypeRef::Owned(TypeEnum::Type(id)); } - Some(Symbol::Class(_) | Symbol::Trait(_)) if !receiver => { + Some(Symbol::Type(_) | Symbol::Trait(_)) if !receiver => { self.state.diagnostics.symbol_not_a_value( &node.name, self.file(), @@ -2470,7 +2472,7 @@ impl<'a> CheckMethodBody<'a> { ( TypeRef::module(id), - TypeId::Module(id), + TypeEnum::Module(id), Receiver::with_module(self.db(), method), method, ) @@ -2537,7 +2539,7 @@ impl<'a> CheckMethodBody<'a> { let (rec, rec_id, rec_kind, method) = { let rec = scope.surrounding_type; - let rec_id = rec.type_id(self.db()).unwrap(); + let rec_id = rec.as_type_enum(self.db()).unwrap(); match rec_id.lookup_method(self.db(), name, module, true) { MethodLookup::Ok(method) if method.is_extern(self.db()) => { @@ -2594,7 +2596,7 @@ impl<'a> CheckMethodBody<'a> { ( TypeRef::module(id), - TypeId::Module(id), + TypeEnum::Module(id), Receiver::with_module(self.db(), method), method, ) @@ -2669,7 +2671,7 @@ impl<'a> CheckMethodBody<'a> { } node.info = Some(FieldInfo { - class: scope.surrounding_type.class_id(self.db()).unwrap(), + type_id: scope.surrounding_type.type_id(self.db()).unwrap(), id: field, variable_type: ret, as_pointer, @@ -3050,7 +3052,7 @@ impl<'a> CheckMethodBody<'a> { if let Some(m) = self.module.method(self.db(), &n.name) { if m.uses_c_calling_convention(self.db()) { node.pointer_to_method = Some(m); - node.resolved_type = TypeRef::pointer(TypeId::Foreign( + node.resolved_type = TypeRef::pointer(TypeEnum::Foreign( types::ForeignType::Int(8, Sign::Unsigned), )); @@ -3268,7 +3270,7 @@ impl<'a> CheckMethodBody<'a> { } let value = self.expression(&mut node.value, scope); - let targs = TypeArguments::for_class(self.db(), ins); + let targs = TypeArguments::for_type(self.db(), ins); let raw_type = field.value_type(self.db()); let bounds = self.bounds; let var_type = @@ -3316,7 +3318,7 @@ impl<'a> CheckMethodBody<'a> { &mut self, node: &mut hir::AssignSetter, receiver: TypeRef, - receiver_id: TypeId, + receiver_id: TypeEnum, value: TypeRef, scope: &mut LexicalScope, ) -> bool { @@ -3337,7 +3339,7 @@ impl<'a> CheckMethodBody<'a> { scope, ) { node.kind = CallKind::SetField(FieldInfo { - class: receiver.class_id(self.db()).unwrap(), + type_id: receiver.type_id(self.db()).unwrap(), id: field, variable_type: typ, as_pointer: false, @@ -3357,7 +3359,7 @@ impl<'a> CheckMethodBody<'a> { ); } - let targs = TypeArguments::for_class(self.db(), ins); + let targs = TypeArguments::for_type(self.db(), ins); let raw_type = field.value_type(self.db()); let bounds = self.bounds; let var_type = @@ -3386,7 +3388,7 @@ impl<'a> CheckMethodBody<'a> { } node.kind = CallKind::SetField(FieldInfo { - class: ins.instance_of(), + type_id: ins.instance_of(), id: field, variable_type: var_type, as_pointer: false, @@ -3563,17 +3565,17 @@ impl<'a> CheckMethodBody<'a> { return typ; } - if let TypeId::Module(id) = rec_id { + if let TypeEnum::Module(id) = rec_id { match id.use_symbol(self.db_mut(), &node.name.name) { Some(Symbol::Constant(id)) => { node.kind = CallKind::GetConstant(id); return id.value_type(self.db()); } - Some(Symbol::Class(id)) if as_receiver => { - return TypeRef::Owned(TypeId::Class(id)); + Some(Symbol::Type(id)) if as_receiver => { + return TypeRef::Owned(TypeEnum::Type(id)); } - Some(Symbol::Class(_) | Symbol::Trait(_)) + Some(Symbol::Type(_) | Symbol::Trait(_)) if !as_receiver => { self.state.diagnostics.symbol_not_a_value( @@ -3610,11 +3612,11 @@ impl<'a> CheckMethodBody<'a> { }; } MethodLookup::None => { - if let TypeId::Module(mod_id) = rec_id { - if let Some(Symbol::Class(id)) = + if let TypeEnum::Module(mod_id) = rec_id { + if let Some(Symbol::Type(id)) = mod_id.use_symbol(self.db_mut(), &node.name.name) { - return self.new_class_instance(node, scope, id); + return self.new_type_instance(node, scope, id); } } @@ -3668,7 +3670,7 @@ impl<'a> CheckMethodBody<'a> { let name = &node.name.name; let module = self.module; let rec = scope.surrounding_type; - let rec_id = rec.type_id(self.db()).unwrap(); + let rec_id = rec.as_type_enum(self.db()).unwrap(); let (rec_info, rec, rec_id, method) = match rec_id.lookup_method(self.db(), name, module, true) { MethodLookup::Ok(method) => { @@ -3707,7 +3709,7 @@ impl<'a> CheckMethodBody<'a> { // Private module methods can't be imported, so we // don't need to check the visibility here. let mod_id = method.module(self.db()); - let id = TypeId::Module(mod_id); + let id = TypeEnum::Module(mod_id); let mod_typ = TypeRef::Owned(id); ( @@ -3717,8 +3719,8 @@ impl<'a> CheckMethodBody<'a> { method, ) } - Some(Symbol::Class(id)) => { - return self.new_class_instance(node, scope, id); + Some(Symbol::Type(id)) => { + return self.new_type_instance(node, scope, id); } _ => { self.state.diagnostics.undefined_symbol( @@ -3763,70 +3765,72 @@ impl<'a> CheckMethodBody<'a> { returns } - fn new_class_instance( + fn new_type_instance( &mut self, node: &mut hir::Call, scope: &mut LexicalScope, - class: ClassId, + type_id: TypeId, ) -> TypeRef { - if class.is_builtin() && !self.module.is_std(self.db()) { + if type_id.is_builtin() && !self.module.is_std(self.db()) { self.state.diagnostics.error( DiagnosticId::InvalidType, - "instances of builtin classes can't be created using the \ - class literal syntax", + "instances of builtin types can't be created using the \ + type literal syntax", self.file(), node.location, ); } - let kind = class.kind(self.db()); + let kind = type_id.kind(self.db()); let require_send = kind.is_async(); - let ins = ClassInstance::empty(self.db_mut(), class); + let ins = TypeInstance::empty(self.db_mut(), type_id); let mut assigned = HashSet::new(); let mut fields = Vec::new(); for (idx, arg) in node.arguments.iter_mut().enumerate() { let (field, val_expr) = match arg { hir::Argument::Positional(n) => { - let field = - if let Some(v) = class.field_by_index(self.db(), idx) { - v - } else { - let num = class.number_of_fields(self.db()); - - self.state.diagnostics.error( - DiagnosticId::InvalidSymbol, - format!( - "the field index {} is out of bounds \ + let field = if let Some(v) = + type_id.field_by_index(self.db(), idx) + { + v + } else { + let num = type_id.number_of_fields(self.db()); + + self.state.diagnostics.error( + DiagnosticId::InvalidSymbol, + format!( + "the field index {} is out of bounds \ (total number of fields: {})", - idx, num, - ), - self.file(), - n.value.location(), - ); + idx, num, + ), + self.file(), + n.value.location(), + ); - continue; - }; + continue; + }; (field, &mut n.value) } hir::Argument::Named(n) => { - let field = - if let Some(v) = class.field(self.db(), &n.name.name) { - v - } else { - self.state.diagnostics.error( - DiagnosticId::InvalidSymbol, - format!( - "the field '{}' is undefined", - &n.name.name - ), - self.file(), - n.location, - ); + let field = if let Some(v) = + type_id.field(self.db(), &n.name.name) + { + v + } else { + self.state.diagnostics.error( + DiagnosticId::InvalidSymbol, + format!( + "the field '{}' is undefined", + &n.name.name + ), + self.file(), + n.location, + ); - continue; - }; + continue; + }; (field, &mut n.value) } @@ -3848,7 +3852,7 @@ impl<'a> CheckMethodBody<'a> { // account what we have inferred thus far. Consider the following // code: // - // class Foo[T] { + // type Foo[T] { // let @a: Option[Option[T]] // } // @@ -3915,16 +3919,16 @@ impl<'a> CheckMethodBody<'a> { fields.push((field, expected)); } - // For extern classes we allow either all fields to be specified, or all + // For extern types we allow either all fields to be specified, or all // fields to be left out. The latter is useful when dealing with C // structures that start on the stack as uninitialized data and are // initialized using a dedicated function. // - // If an extern class has one or more fields specifid, then we require + // If an extern type has one or more fields specifid, then we require // _all_ fields to be specified, as leaving out fields in this case is // likely the result of a mistake. if !kind.is_extern() || !assigned.is_empty() { - for field in class.field_names(self.db()) { + for field in type_id.field_names(self.db()) { if assigned.contains(&field) { continue; } @@ -3938,10 +3942,10 @@ impl<'a> CheckMethodBody<'a> { } } - let resolved_type = TypeRef::Owned(TypeId::ClassInstance(ins)); + let resolved_type = TypeRef::Owned(TypeEnum::TypeInstance(ins)); - node.kind = CallKind::ClassInstance(types::ClassInstanceInfo { - class_id: class, + node.kind = CallKind::TypeInstance(types::TypeInstanceInfo { + type_id, resolved_type, fields, }); @@ -3953,7 +3957,7 @@ impl<'a> CheckMethodBody<'a> { &mut self, node: &mut hir::Call, receiver: TypeRef, - receiver_id: TypeId, + receiver_id: TypeEnum, ) -> Option { let (ins, field) = self.lookup_field_with_receiver(receiver_id, &node.name)?; @@ -3974,7 +3978,7 @@ impl<'a> CheckMethodBody<'a> { node.kind = CallKind::GetField(FieldInfo { id: field, - class: ins.instance_of(), + type_id: ins.instance_of(), variable_type: returns, as_pointer, }); @@ -4151,8 +4155,8 @@ impl<'a> CheckMethodBody<'a> { &mut self, receiver: TypeRef, location: Location, - ) -> Option { - match receiver.type_id(self.db()) { + ) -> Option { + match receiver.as_type_enum(self.db()) { Ok(id) => Some(id), Err(TypeRef::Error) => None, Err(TypeRef::Placeholder(_)) => { @@ -4367,7 +4371,7 @@ impl<'a> CheckMethodBody<'a> { fn type_signature( &mut self, node: &mut hir::Type, - self_type: TypeId, + self_type: TypeEnum, ) -> TypeRef { let rules = Rules { type_parameters_as_rigid: true, ..Default::default() }; @@ -4564,10 +4568,10 @@ impl<'a> CheckMethodBody<'a> { fn lookup_field_with_receiver( &mut self, - receiver_id: TypeId, + receiver_id: TypeEnum, name: &hir::Identifier, - ) -> Option<(ClassInstance, FieldId)> { - let (ins, field) = if let TypeId::ClassInstance(ins) = receiver_id { + ) -> Option<(TypeInstance, FieldId)> { + let (ins, field) = if let TypeEnum::TypeInstance(ins) = receiver_id { ins.instance_of() .field(self.db(), &name.name) .map(|field| (ins, field)) @@ -4577,7 +4581,7 @@ impl<'a> CheckMethodBody<'a> { // We disallow `receiver.field` even when `receiver` is `self`, because // we can't tell the difference between two different instances of the - // same non-generic process (e.g. every instance `class async Foo {}` + // same non-generic process (e.g. every instance `type async Foo {}` // has the same TypeId). if ins.instance_of().kind(self.db()).is_async() { self.state.diagnostics.unavailable_process_field( diff --git a/compiler/src/type_check/graph.rs b/compiler/src/type_check/graph.rs index d55767d0d..3348329ba 100644 --- a/compiler/src/type_check/graph.rs +++ b/compiler/src/type_check/graph.rs @@ -1,6 +1,6 @@ //! Helpers for performing graph-like operations on types, such as checking if a -//! class is recursive. -use types::{ClassId, ClassInstance, Database, TypeRef}; +//! type is recursive. +use types::{Database, TypeId, TypeInstance, TypeRef}; #[derive(Copy, Clone)] enum Visit { @@ -20,35 +20,35 @@ enum Visit { Visited, } -/// A type used for checking if a stack class is a recursive class. -pub(crate) struct RecursiveClassChecker<'a> { +/// A type used for checking if a stack type is a recursive type. +pub(crate) struct RecursiveTypeChecker<'a> { db: &'a Database, states: Vec, - work: Vec, + work: Vec, } -impl<'a> RecursiveClassChecker<'a> { - pub(crate) fn new(db: &'a Database) -> RecursiveClassChecker<'a> { - RecursiveClassChecker { +impl<'a> RecursiveTypeChecker<'a> { + pub(crate) fn new(db: &'a Database) -> RecursiveTypeChecker<'a> { + RecursiveTypeChecker { db, - states: vec![Visit::Unvisited; db.number_of_classes()], + states: vec![Visit::Unvisited; db.number_of_types()], work: Vec::new(), } } - pub(crate) fn is_recursive(&mut self, class: ClassId) -> bool { - self.add(class); + pub(crate) fn is_recursive(&mut self, type_id: TypeId) -> bool { + self.add(type_id); - while let Some(&class) = self.work.last() { - if let Visit::Visiting = self.state(class) { - self.set_state(class, Visit::Visited); + while let Some(&typ) = self.work.last() { + if let Visit::Visiting = self.state(typ) { + self.set_state(typ, Visit::Visited); self.work.pop(); continue; } - self.set_state(class, Visit::Visiting); + self.set_state(typ, Visit::Visiting); - for field in class.fields(self.db) { + for field in typ.fields(self.db) { let typ = field.value_type(self.db); let Some(ins) = self.edge(typ) else { continue }; @@ -77,26 +77,26 @@ impl<'a> RecursiveClassChecker<'a> { false } - fn edge(&self, typ: TypeRef) -> Option { + fn edge(&self, typ: TypeRef) -> Option { // Pointers _are_ stack allocated, but they introduce indirection that // breaks recursion so we don't need to process them. if typ.is_pointer(self.db) { return None; } - typ.as_class_instance(self.db) + typ.as_type_instance(self.db) .filter(|v| v.instance_of().is_stack_allocated(self.db)) } - fn set_state(&mut self, id: ClassId, state: Visit) { + fn set_state(&mut self, id: TypeId, state: Visit) { self.states[id.0 as usize] = state; } - fn state(&self, id: ClassId) -> Visit { + fn state(&self, id: TypeId) -> Visit { self.states[id.0 as usize] } - fn add(&mut self, id: ClassId) { + fn add(&mut self, id: TypeId) { self.set_state(id, Visit::Scheduled); self.work.push(id); } diff --git a/compiler/src/type_check/imports.rs b/compiler/src/type_check/imports.rs index 708ae6527..8c9fa13d9 100644 --- a/compiler/src/type_check/imports.rs +++ b/compiler/src/type_check/imports.rs @@ -9,7 +9,7 @@ use types::{Database, ModuleId, Symbol, IMPORT_MODULE_ITSELF_NAME}; /// A compiler pass that defines any imported types. /// -/// This pass only defines imported classes, traits and modules. +/// This pass only defines imported types, traits and modules. /// /// Method imports are handled in a separate pass, as we can't process these /// until other passes have run first. diff --git a/compiler/src/type_check/methods.rs b/compiler/src/type_check/methods.rs index efb7bfbcc..a0248a6d2 100644 --- a/compiler/src/type_check/methods.rs +++ b/compiler/src/type_check/methods.rs @@ -10,10 +10,10 @@ use std::path::PathBuf; use types::check::{Environment, TypeChecker}; use types::format::{format_type, format_type_with_arguments}; use types::{ - Block, ClassId, ClassInstance, Database, Method, MethodId, MethodKind, - MethodSource, ModuleId, Symbol, TraitId, TraitInstance, TypeArguments, - TypeBounds, TypeId, TypeRef, Visibility, DROP_METHOD, MAIN_CLASS, - MAIN_METHOD, + Block, Database, Method, MethodId, MethodKind, MethodSource, ModuleId, + Symbol, TraitId, TraitInstance, TypeArguments, TypeBounds, TypeEnum, + TypeId, TypeInstance, TypeRef, Visibility, DROP_METHOD, MAIN_METHOD, + MAIN_TYPE, }; fn method_kind(kind: hir::MethodKind) -> MethodKind { @@ -24,9 +24,13 @@ fn method_kind(kind: hir::MethodKind) -> MethodKind { } } -fn receiver_type(db: &Database, id: TypeId, kind: hir::MethodKind) -> TypeRef { +fn receiver_type( + db: &Database, + id: TypeEnum, + kind: hir::MethodKind, +) -> TypeRef { match id { - TypeId::ClassInstance(ins) + TypeEnum::TypeInstance(ins) if ins.instance_of().is_value_type(db) && !ins.instance_of().kind(db).is_async() => { @@ -62,7 +66,7 @@ trait MethodDefiner { &mut self, nodes: &mut Vec, method: MethodId, - receiver_id: TypeId, + receiver_id: TypeEnum, ) { for param_node in nodes { let name = ¶m_node.name.name; @@ -231,38 +235,38 @@ trait MethodDefiner { method.set_return_type(self.db_mut(), typ); } - fn add_method_to_class( + fn add_method_to_type( &mut self, method: MethodId, - class_id: ClassId, + type_id: TypeId, name: &str, location: Location, ) { - if class_id.method_exists(self.db(), name) { - let class_name = format_type(self.db(), class_id); + if type_id.method_exists(self.db(), name) { + let tname = format_type(self.db(), type_id); let file = self.file(); self.state_mut() .diagnostics - .duplicate_method(name, class_name, file, location); + .duplicate_method(name, tname, file, location); } else { - class_id.add_method(self.db_mut(), name.to_string(), method); + type_id.add_method(self.db_mut(), name.to_string(), method); } } fn check_if_mutating_method_is_allowed( &mut self, kind: hir::MethodKind, - class: ClassId, + type_id: TypeId, location: Location, ) { if !matches!(kind, hir::MethodKind::Mutable) - || class.allow_mutating(self.db()) + || type_id.allow_mutating(self.db()) { return; } - let name = class.name(self.db()).clone(); + let name = type_id.name(self.db()).clone(); let file = self.file(); self.state_mut().diagnostics.error( @@ -424,8 +428,8 @@ impl<'a> DefineMethods<'a> { fn run(mut self, module: &mut hir::Module) { for expression in module.expressions.iter_mut() { match expression { - hir::TopLevelExpression::Class(ref mut node) => { - self.define_class(node); + hir::TopLevelExpression::Type(ref mut node) => { + self.define_type(node); } hir::TopLevelExpression::Trait(ref mut node) => { self.define_trait(node); @@ -437,33 +441,33 @@ impl<'a> DefineMethods<'a> { self.define_extern_function(node); } hir::TopLevelExpression::Reopen(ref mut node) => { - self.reopen_class(node); + self.reopen_type(node); } _ => {} } } } - fn define_class(&mut self, node: &mut hir::DefineClass) { - let class_id = node.class_id.unwrap(); + fn define_type(&mut self, node: &mut hir::DefineType) { + let type_id = node.type_id.unwrap(); for expr in &mut node.body { match expr { - hir::ClassExpression::AsyncMethod(ref mut node) => { - self.define_async_method(class_id, node, TypeBounds::new()); + hir::TypeExpression::AsyncMethod(ref mut node) => { + self.define_async_method(type_id, node, TypeBounds::new()); } - hir::ClassExpression::StaticMethod(ref mut node) => { - self.define_static_method(class_id, node) + hir::TypeExpression::StaticMethod(ref mut node) => { + self.define_static_method(type_id, node) } - hir::ClassExpression::InstanceMethod(ref mut node) => { + hir::TypeExpression::InstanceMethod(ref mut node) => { self.define_instance_method( - class_id, + type_id, node, TypeBounds::new(), ); } - hir::ClassExpression::Constructor(ref mut node) => { - self.define_constructor_method(class_id, node); + hir::TypeExpression::Constructor(ref mut node) => { + self.define_constructor_method(type_id, node); } _ => {} } @@ -516,34 +520,34 @@ impl<'a> DefineMethods<'a> { } } - fn reopen_class(&mut self, node: &mut hir::ReopenClass) { - let class_name = &node.class_name.name; - let class_id = match self.module.use_symbol(self.db_mut(), class_name) { - Some(Symbol::Class(id)) => id, + fn reopen_type(&mut self, node: &mut hir::ReopenType) { + let tname = &node.type_name.name; + let type_id = match self.module.use_symbol(self.db_mut(), tname) { + Some(Symbol::Type(id)) => id, Some(_) => { - self.state.diagnostics.not_a_class( - class_name, + self.state.diagnostics.not_a_type( + tname, self.file(), - node.class_name.location, + node.type_name.location, ); return; } None => { self.state.diagnostics.undefined_symbol( - class_name, + tname, self.file(), - node.class_name.location, + node.type_name.location, ); return; } }; - if class_id.kind(self.db()).is_extern() { + if type_id.kind(self.db()).is_extern() { self.state.diagnostics.error( DiagnosticId::InvalidImplementation, - "methods can't be defined for extern classes", + "methods can't be defined for extern types", self.file(), node.location, ); @@ -552,29 +556,29 @@ impl<'a> DefineMethods<'a> { let bounds = define_type_bounds( self.state, self.module, - class_id, + type_id, &mut node.bounds, ); for expr in &mut node.body { match expr { - hir::ReopenClassExpression::InstanceMethod(ref mut n) => { - self.define_instance_method(class_id, n, bounds.clone()); + hir::ReopenTypeExpression::InstanceMethod(ref mut n) => { + self.define_instance_method(type_id, n, bounds.clone()); } - hir::ReopenClassExpression::StaticMethod(ref mut n) => { - self.define_static_method(class_id, n); + hir::ReopenTypeExpression::StaticMethod(ref mut n) => { + self.define_static_method(type_id, n); } - hir::ReopenClassExpression::AsyncMethod(ref mut n) => { - self.define_async_method(class_id, n, bounds.clone()); + hir::ReopenTypeExpression::AsyncMethod(ref mut n) => { + self.define_async_method(type_id, n, bounds.clone()); } } } - node.class_id = Some(class_id); + node.type_id = Some(type_id); } fn define_module_method(&mut self, node: &mut hir::DefineModuleMethod) { - let self_type = TypeId::Module(self.module); + let self_type = TypeEnum::Module(self.module); let receiver = TypeRef::Owned(self_type); let method = node.method_id.unwrap(); @@ -606,7 +610,7 @@ impl<'a> DefineMethods<'a> { } fn define_extern_function(&mut self, node: &mut hir::DefineExternFunction) { - let self_type = TypeId::Module(self.module); + let self_type = TypeEnum::Module(self.module); let func = node.method_id.unwrap(); let scope = TypeScope::new(self.module, self_type, None); let rules = Rules { @@ -632,14 +636,14 @@ impl<'a> DefineMethods<'a> { fn define_static_method( &mut self, - class_id: ClassId, + type_id: TypeId, node: &mut hir::DefineStaticMethod, ) { - let receiver = TypeRef::Owned(TypeId::Class(class_id)); + let receiver = TypeRef::Owned(TypeEnum::Type(type_id)); let bounds = TypeBounds::new(); - let self_type = TypeId::ClassInstance(ClassInstance::rigid( + let self_type = TypeEnum::TypeInstance(TypeInstance::rigid( self.db_mut(), - class_id, + type_id, &bounds, )); let module = self.module; @@ -660,7 +664,7 @@ impl<'a> DefineMethods<'a> { let scope = TypeScope::new(self.module, self_type, Some(method)); let rules = Rules { - allow_private_types: class_id.is_private(self.db()) + allow_private_types: type_id.is_private(self.db()) || method.is_private(self.db()), ..Default::default() }; @@ -668,7 +672,7 @@ impl<'a> DefineMethods<'a> { self.define_type_parameters( &mut node.type_parameters, method, - TypeId::Class(class_id), + TypeEnum::Type(type_id), ); self.define_type_parameter_requirements( &mut node.type_parameters, @@ -682,9 +686,9 @@ impl<'a> DefineMethods<'a> { rules, &scope, ); - self.add_method_to_class( + self.add_method_to_type( method, - class_id, + type_id, &node.name.name, node.location, ); @@ -694,13 +698,13 @@ impl<'a> DefineMethods<'a> { fn define_instance_method( &mut self, - class_id: ClassId, + type_id: TypeId, node: &mut hir::DefineInstanceMethod, mut bounds: TypeBounds, ) { - let async_class = class_id.kind(self.db()).is_async(); + let async_type = type_id.kind(self.db()).is_async(); - if matches!(node.kind, hir::MethodKind::Moving) && async_class { + if matches!(node.kind, hir::MethodKind::Moving) && async_type { self.state.diagnostics.error( DiagnosticId::InvalidMethod, "moving methods can't be defined for 'async' types", @@ -711,13 +715,13 @@ impl<'a> DefineMethods<'a> { self.check_if_mutating_method_is_allowed( node.kind, - class_id, + type_id, node.location, ); - let self_id = TypeId::Class(class_id); + let self_id = TypeEnum::Type(type_id); let module = self.module; - let vis = if async_class { + let vis = if async_type { if node.public { Visibility::Public } else { @@ -744,9 +748,9 @@ impl<'a> DefineMethods<'a> { bounds.make_immutable(self.db_mut()); } - // Regular instance methods on an `async class` must be private to the - // class itself. - if async_class && method.is_public(self.db()) { + // Regular instance methods on an `async` type must be private to the + // type itself. + if async_type && method.is_public(self.db()) { self.state.diagnostics.error( DiagnosticId::InvalidMethod, "instance methods defined on 'async' types must be private", @@ -758,13 +762,13 @@ impl<'a> DefineMethods<'a> { self.define_type_parameters(&mut node.type_parameters, method, self_id); let rules = Rules { - allow_private_types: class_id.is_private(self.db()) + allow_private_types: type_id.is_private(self.db()) || method.is_private(self.db()), ..Default::default() }; - let self_type = TypeId::ClassInstance(ClassInstance::rigid( + let self_type = TypeEnum::TypeInstance(TypeInstance::rigid( self.db_mut(), - class_id, + type_id, &bounds, )); let receiver = receiver_type(self.db(), self_type, node.kind); @@ -790,9 +794,9 @@ impl<'a> DefineMethods<'a> { rules, &scope, ); - self.add_method_to_class( + self.add_method_to_type( method, - class_id, + type_id, &node.name.name, node.location, ); @@ -803,11 +807,11 @@ impl<'a> DefineMethods<'a> { fn define_async_method( &mut self, - class_id: ClassId, + type_id: TypeId, node: &mut hir::DefineAsyncMethod, mut bounds: TypeBounds, ) { - let self_id = TypeId::Class(class_id); + let self_id = TypeEnum::Type(type_id); let module = self.module; let kind = if node.mutable { MethodKind::AsyncMutable @@ -827,12 +831,13 @@ impl<'a> DefineMethods<'a> { bounds.make_immutable(self.db_mut()); } - if !class_id.kind(self.db()).is_async() { + if !type_id.kind(self.db()).is_async() { let file = self.file(); self.state_mut().diagnostics.error( DiagnosticId::InvalidMethod, - "async methods can only be used in async classes".to_string(), + "'async' methods can only be defined for 'async' types" + .to_string(), file, node.location, ); @@ -841,14 +846,14 @@ impl<'a> DefineMethods<'a> { self.define_type_parameters(&mut node.type_parameters, method, self_id); let rules = Rules { - allow_private_types: class_id.is_private(self.db()) + allow_private_types: type_id.is_private(self.db()) || method.is_private(self.db()), ..Default::default() }; let bounds = TypeBounds::new(); - let self_type = TypeId::ClassInstance(ClassInstance::rigid( + let self_type = TypeEnum::TypeInstance(TypeInstance::rigid( self.db_mut(), - class_id, + type_id, &bounds, )); let receiver = if node.mutable { @@ -883,9 +888,9 @@ impl<'a> DefineMethods<'a> { ); } - self.add_method_to_class( + self.add_method_to_type( method, - class_id, + type_id, &node.name.name, node.location, ); @@ -900,7 +905,7 @@ impl<'a> DefineMethods<'a> { node: &mut hir::DefineRequiredMethod, ) { let name = &node.name.name; - let self_id = TypeId::Trait(trait_id); + let self_id = TypeEnum::Trait(trait_id); let module = self.module; let kind = method_kind(node.kind); let method = Method::alloc( @@ -919,7 +924,7 @@ impl<'a> DefineMethods<'a> { ..Default::default() }; let bounds = TypeBounds::new(); - let self_type = TypeId::TraitInstance(TraitInstance::rigid( + let self_type = TypeEnum::TraitInstance(TraitInstance::rigid( self.db_mut(), trait_id, &bounds, @@ -968,7 +973,7 @@ impl<'a> DefineMethods<'a> { node: &mut hir::DefineInstanceMethod, ) { let name = &node.name.name; - let self_id = TypeId::Trait(trait_id); + let self_id = TypeEnum::Trait(trait_id); let module = self.module; let kind = method_kind(node.kind); let method = Method::alloc( @@ -1000,7 +1005,7 @@ impl<'a> DefineMethods<'a> { // or an unrelated value that happens to have the same type. ins.self_type = true; - let self_type = TypeId::TraitInstance(ins); + let self_type = TypeEnum::TraitInstance(ins); let receiver = receiver_type(self.db(), self_type, node.kind); method.set_receiver(self.db_mut(), receiver); @@ -1042,7 +1047,7 @@ impl<'a> DefineMethods<'a> { #[allow(clippy::unnecessary_to_owned)] fn define_constructor_method( &mut self, - class_id: ClassId, + type_id: TypeId, node: &mut hir::DefineConstructor, ) { // Enums are desugared when lowering to MIR. We define the static method @@ -1065,7 +1070,7 @@ impl<'a> DefineMethods<'a> { method.always_inline(self.db_mut()); let constructor = - class_id.constructor(self.db(), &node.name.name).unwrap(); + type_id.constructor(self.db(), &node.name.name).unwrap(); for (index, typ) in constructor.arguments(self.db()).to_vec().into_iter().enumerate() @@ -1081,26 +1086,26 @@ impl<'a> DefineMethods<'a> { ); } - let stype = TypeId::Class(class_id); + let stype = TypeEnum::Type(type_id); let rec = TypeRef::Owned(stype); - let ret = if class_id.is_generic(self.db()) { - let args = class_id + let ret = if type_id.is_generic(self.db()) { + let args = type_id .type_parameters(self.db()) .into_iter() - .map(|param| TypeRef::Any(TypeId::TypeParameter(param))) + .map(|param| TypeRef::Any(TypeEnum::TypeParameter(param))) .collect(); - ClassInstance::with_types(self.db_mut(), class_id, args) + TypeInstance::with_types(self.db_mut(), type_id, args) } else { - ClassInstance::new(class_id) + TypeInstance::new(type_id) }; method.set_receiver(self.db_mut(), rec); method.set_return_type( self.db_mut(), - TypeRef::Owned(TypeId::ClassInstance(ret)), + TypeRef::Owned(TypeEnum::TypeInstance(ret)), ); - class_id.add_method(self.db_mut(), name, method); + type_id.add_method(self.db_mut(), name, method); node.method_id = Some(method); node.constructor_id = Some(constructor); @@ -1144,18 +1149,18 @@ impl<'a> CheckMainMethod<'a> { let mod_id = self.db().module(main_mod); - if let Some((class, method)) = self.main_method(mod_id) { + if let Some((typ, method)) = self.main_method(mod_id) { method.set_main(self.db_mut()); self.db_mut().set_main_method(method); - self.db_mut().set_main_class(class); + self.db_mut().set_main_type(typ); true } else { self.state.diagnostics.error( DiagnosticId::MissingMain, format!( - "this module must define the async class '{}', \ - which must define the async method '{}'", - MAIN_CLASS, MAIN_METHOD + "this module must define the 'async' type '{}', \ + which must define the 'async' method '{}'", + MAIN_TYPE, MAIN_METHOD ), mod_id.file(self.db()), Location::default(), @@ -1165,26 +1170,26 @@ impl<'a> CheckMainMethod<'a> { } } - fn main_method(&mut self, mod_id: ModuleId) -> Option<(ClassId, MethodId)> { - let class = if let Some(Symbol::Class(class_id)) = - mod_id.use_symbol(self.db_mut(), MAIN_CLASS) + fn main_method(&mut self, mod_id: ModuleId) -> Option<(TypeId, MethodId)> { + let typ = if let Some(Symbol::Type(type_id)) = + mod_id.use_symbol(self.db_mut(), MAIN_TYPE) { - class_id + type_id } else { return None; }; - if !class.kind(self.db()).is_async() { + if !typ.kind(self.db()).is_async() { return None; } - let method = class.method(self.db(), MAIN_METHOD)?; + let method = typ.method(self.db(), MAIN_METHOD)?; if method.kind(self.db()) == MethodKind::Async && method.number_of_arguments(self.db()) == 0 && method.return_type(self.db()).is_nil(self.db()) { - Some((class, method)) + Some((typ, method)) } else { None } @@ -1236,10 +1241,10 @@ impl<'a> ImplementTraitMethods<'a> { fn implement_trait(&mut self, node: &mut hir::ImplementTrait) { let trait_ins = node.trait_instance.unwrap(); let trait_id = trait_ins.instance_of(); - let class_ins = node.class_instance.unwrap(); - let class_id = class_ins.instance_of(); + let type_ins = node.type_instance.unwrap(); + let type_id = type_ins.instance_of(); let mut mut_error = false; - let allow_mut = class_id.allow_mutating(self.db()); + let allow_mut = type_id.allow_mutating(self.db()); for method in trait_id.default_methods(self.db()) { if method.is_mutable(self.db()) && !allow_mut && !mut_error { @@ -1255,11 +1260,11 @@ impl<'a> ImplementTraitMethods<'a> { mut_error = true; } - if !class_id.method_exists(self.db(), method.name(self.db())) { + if !type_id.method_exists(self.db(), method.name(self.db())) { continue; } - let class_name = format_type(self.db(), class_id); + let type_name = format_type(self.db(), type_id); let trait_name = format_type(self.db(), trait_ins); let method_name = format_type(self.db(), method); let file = self.file(); @@ -1269,24 +1274,24 @@ impl<'a> ImplementTraitMethods<'a> { format!( "the trait '{}' can't be implemented for '{}', as its \ default method '{}' is already defined for '{}'", - trait_name, class_name, method_name, class_name + trait_name, type_name, method_name, type_name ), file, node.location, ); } - let bounds = class_id + let bounds = type_id .trait_implementation(self.db(), trait_id) .map(|i| i.bounds.clone()) .unwrap(); for expr in &mut node.body { - self.implement_method(expr, class_ins, trait_ins, bounds.clone()); + self.implement_method(expr, type_ins, trait_ins, bounds.clone()); } for req in trait_id.required_methods(self.db()) { - if class_ins + if type_ins .instance_of() .method_exists(self.db(), req.name(self.db())) { @@ -1295,13 +1300,13 @@ impl<'a> ImplementTraitMethods<'a> { let file = self.file(); let method_name = format_type(self.db(), req); - let class_name = format_type(self.db(), class_ins.instance_of()); + let type_name = format_type(self.db(), type_ins.instance_of()); self.state_mut().diagnostics.error( DiagnosticId::InvalidImplementation, format!( "the method '{}' must be implemented for '{}'", - method_name, class_name + method_name, type_name ), file, node.location, @@ -1309,24 +1314,24 @@ impl<'a> ImplementTraitMethods<'a> { } for method in trait_id.default_methods(self.db()) { - if class_id.method_exists(self.db(), method.name(self.db())) { + if type_id.method_exists(self.db(), method.name(self.db())) { continue; } let source = MethodSource::Inherited(trait_ins, method); let name = method.name(self.db()).clone(); - let module_id = class_id.module(self.db()); + let module_id = type_id.module(self.db()); let copy = method.copy_method(self.db_mut(), module_id); // This is needed to ensure that the receiver of the default method - // is typed as the class that implements the trait, not as the trait + // is typed as the type that implements the trait, not as the trait // itself. let new_rec = - method.receiver_for_class_instance(self.db(), class_ins); + method.receiver_for_type_instance(self.db(), type_ins); copy.set_source(self.db_mut(), source); copy.set_receiver(self.db_mut(), new_rec); - class_id.add_method(self.db_mut(), name, copy); + type_id.add_method(self.db_mut(), name, copy); copy.set_bounds(self.db_mut(), bounds.clone()); } } @@ -1334,7 +1339,7 @@ impl<'a> ImplementTraitMethods<'a> { fn implement_method( &mut self, node: &mut hir::DefineInstanceMethod, - class_instance: ClassInstance, + type_instance: TypeInstance, trait_instance: TraitInstance, mut bounds: TypeBounds, ) { @@ -1370,12 +1375,12 @@ impl<'a> ImplementTraitMethods<'a> { if !is_drop { self.check_if_mutating_method_is_allowed( node.kind, - class_instance.instance_of(), + type_instance.instance_of(), node.location, ); } - let self_type = TypeId::ClassInstance(class_instance); + let self_type = TypeEnum::TypeInstance(type_instance); let module = self.module; let method = Method::alloc( self.db_mut(), @@ -1401,7 +1406,7 @@ impl<'a> ImplementTraitMethods<'a> { ); let rules = Rules { - allow_private_types: class_instance + allow_private_types: type_instance .instance_of() .is_private(self.db()) || method.is_private(self.db()), @@ -1462,9 +1467,9 @@ impl<'a> ImplementTraitMethods<'a> { method.set_bounds(self.db_mut(), bounds); - self.add_method_to_class( + self.add_method_to_type( method, - class_instance.instance_of(), + type_instance.instance_of(), &node.name.name, node.location, ); diff --git a/compiler/src/type_check/mod.rs b/compiler/src/type_check/mod.rs index 86a81f9d2..3574d2fc3 100644 --- a/compiler/src/type_check/mod.rs +++ b/compiler/src/type_check/mod.rs @@ -7,8 +7,8 @@ use std::path::PathBuf; use types::check::{Environment, TypeChecker}; use types::format::format_type; use types::{ - Block, ClassId, ClassInstance, Closure, Database, MethodId, ModuleId, - Symbol, TraitId, TraitInstance, TypeArguments, TypeBounds, TypeId, + Block, Closure, Database, MethodId, ModuleId, Symbol, TraitId, + TraitInstance, TypeArguments, TypeBounds, TypeEnum, TypeId, TypeInstance, TypeParameterId, TypeRef, }; @@ -28,12 +28,11 @@ enum RefKind { } impl RefKind { - fn into_type_ref(self, id: TypeId) -> TypeRef { + fn into_type_ref(self, id: TypeEnum) -> TypeRef { match self { Self::Default => match id { - TypeId::TypeParameter(_) | TypeId::RigidTypeParameter(_) => { - TypeRef::Any(id) - } + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) => TypeRef::Any(id), _ => TypeRef::Owned(id), }, Self::Owned => TypeRef::Owned(id), @@ -49,8 +48,8 @@ pub(crate) struct TypeScope<'a> { /// The surrounding module. module: ModuleId, - /// The surrounding class or trait. - self_type: TypeId, + /// The surrounding type or trait. + self_type: TypeEnum, /// The surrounding method, if any. method: Option, @@ -62,7 +61,7 @@ pub(crate) struct TypeScope<'a> { impl<'a> TypeScope<'a> { pub(crate) fn new( module: ModuleId, - self_type: TypeId, + self_type: TypeEnum, method: Option, ) -> Self { Self { module, self_type, method, bounds: None } @@ -70,7 +69,7 @@ impl<'a> TypeScope<'a> { pub(crate) fn with_bounds( module: ModuleId, - self_type: TypeId, + self_type: TypeEnum, method: Option, bounds: &'a TypeBounds, ) -> Self { @@ -169,7 +168,7 @@ impl<'a> DefineTypeSignature<'a> { node: &mut hir::TypeName, ) -> Option { match self.define_type_name(node, RefKind::Owned) { - TypeRef::Owned(TypeId::TraitInstance(instance)) => Some(instance), + TypeRef::Owned(TypeEnum::TraitInstance(instance)) => Some(instance), TypeRef::Error => None, _ => { self.state.diagnostics.error( @@ -277,12 +276,12 @@ impl<'a> DefineTypeSignature<'a> { } match symbol { - Symbol::Class(id) if id.kind(&self.state.db).is_extern() => { - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new( + Symbol::Type(id) if id.kind(&self.state.db).is_extern() => { + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new( id, ))) } - Symbol::Class(id) if id.is_copy_type(&self.state.db) => { + Symbol::Type(id) if id.is_copy_type(&self.state.db) => { if matches!(kind, RefKind::Mut) { let name = &id.name(self.db()).clone(); @@ -293,10 +292,10 @@ impl<'a> DefineTypeSignature<'a> { ); } - TypeRef::Owned(self.define_class_instance(id, node)) + TypeRef::Owned(self.define_type_instance(id, node)) } - Symbol::Class(id) => { - kind.into_type_ref(self.define_class_instance(id, node)) + Symbol::Type(id) => { + kind.into_type_ref(self.define_type_instance(id, node)) } Symbol::Trait(id) => { kind.into_type_ref(self.define_trait_instance(id, node)) @@ -367,7 +366,7 @@ impl<'a> DefineTypeSignature<'a> { node: &mut hir::TupleType, kind: RefKind, ) -> TypeRef { - let class = if let Some(id) = ClassId::tuple(node.values.len()) { + let typ = if let Some(id) = TypeId::tuple(node.values.len()) { id } else { self.state.diagnostics.tuple_size_error(self.file(), node.location); @@ -377,30 +376,30 @@ impl<'a> DefineTypeSignature<'a> { let types = node.values.iter_mut().map(|n| self.define_type(n)).collect(); - let ins = TypeId::ClassInstance(ClassInstance::with_types( + let ins = TypeEnum::TypeInstance(TypeInstance::with_types( self.db_mut(), - class, + typ, types, )); kind.into_type_ref(ins) } - fn define_class_instance( + fn define_type_instance( &mut self, - id: ClassId, + id: TypeId, node: &mut hir::TypeName, - ) -> TypeId { + ) -> TypeEnum { let params = id.type_parameters(self.db()); if let Some(args) = self.type_arguments(params, &mut node.arguments) { - TypeId::ClassInstance(ClassInstance::generic( + TypeEnum::TypeInstance(TypeInstance::generic( self.db_mut(), id, args, )) } else { - TypeId::ClassInstance(ClassInstance::new(id)) + TypeEnum::TypeInstance(TypeInstance::new(id)) } } @@ -408,17 +407,17 @@ impl<'a> DefineTypeSignature<'a> { &mut self, id: TraitId, node: &mut hir::TypeName, - ) -> TypeId { + ) -> TypeEnum { let params = id.type_parameters(self.db()); if let Some(args) = self.type_arguments(params, &mut node.arguments) { - TypeId::TraitInstance(TraitInstance::generic( + TypeEnum::TraitInstance(TraitInstance::generic( self.db_mut(), id, args, )) } else { - TypeId::TraitInstance(TraitInstance::new(id)) + TypeEnum::TraitInstance(TraitInstance::new(id)) } } @@ -441,9 +440,9 @@ impl<'a> DefineTypeSignature<'a> { self.scope.bounds.as_ref().and_then(|b| b.get(id)).unwrap_or(id); let type_id = if self.rules.type_parameters_as_rigid { - TypeId::RigidTypeParameter(param_id) + TypeEnum::RigidTypeParameter(param_id) } else { - TypeId::TypeParameter(param_id) + TypeEnum::TypeParameter(param_id) }; if let RefKind::Mut = kind { @@ -482,7 +481,7 @@ impl<'a> DefineTypeSignature<'a> { block.set_return_type(self.db_mut(), return_type); - let typ = kind.into_type_ref(TypeId::Closure(block)); + let typ = kind.into_type_ref(TypeEnum::Closure(block)); node.resolved_type = typ; typ @@ -586,14 +585,14 @@ impl<'a> DefineTypeSignature<'a> { }; match sym { - Some(Symbol::Class(id)) => Some(TypeRef::Owned( - TypeId::ClassInstance(ClassInstance::new(id)), + Some(Symbol::Type(id)) => Some(TypeRef::Owned( + TypeEnum::TypeInstance(TypeInstance::new(id)), )), Some(Symbol::TypeParameter(id)) => { let tid = if self.rules.type_parameters_as_rigid { - TypeId::RigidTypeParameter(id) + TypeEnum::RigidTypeParameter(id) } else { - TypeId::TypeParameter(id) + TypeEnum::TypeParameter(id) }; Some(TypeRef::Owned(tid)) @@ -653,7 +652,7 @@ impl<'a> DefineTypeSignature<'a> { /// In addition, if defining and checking took place in the same pass, we /// wouldn't be able to support code like this: /// -/// class Int {} +/// type Int {} /// /// trait A[T: ToString] /// trait B[T: A[Int]] @@ -691,10 +690,10 @@ impl<'a> CheckTypeSignature<'a> { | TypeRef::Ref(id) | TypeRef::Mut(id) | TypeRef::Uni(id) => match id { - TypeId::ClassInstance(ins) => { - self.check_class_instance(node, ins); + TypeEnum::TypeInstance(ins) => { + self.check_type_instance(node, ins); } - TypeId::TraitInstance(ins) => { + TypeEnum::TraitInstance(ins) => { self.check_trait_instance(node, ins); } _ => {} @@ -711,10 +710,10 @@ impl<'a> CheckTypeSignature<'a> { } } - fn check_class_instance( + fn check_type_instance( &mut self, node: &hir::TypeName, - instance: ClassInstance, + instance: TypeInstance, ) { let required = instance.instance_of().number_of_type_parameters(self.db()); @@ -722,7 +721,7 @@ impl<'a> CheckTypeSignature<'a> { if self.check_type_argument_count(node, required) { // Classes can't allow Any types as type arguments, as this results // in a loss of type information at runtime. This means that if a - // class stores a type parameter T in a field, and it's assigned to + // type stores a type parameter T in a field, and it's assigned to // Any, we have no idea how to drop that value, and the value might // not even be managed by Inko (e.g. when using the FFI). self.check_argument_types( @@ -744,7 +743,7 @@ impl<'a> CheckTypeSignature<'a> { if self.check_type_argument_count(node, required) { // Traits do allow Any types as type arguments, as traits don't // dictate how a value is stored. If we end up dropping a trait we - // do so by calling the dropper of the underlying class, which in + // do so by calling the dropper of the underlying type, which in // turn already disallows storing Any in generic contexts. self.check_argument_types( node, @@ -793,7 +792,7 @@ impl<'a> CheckTypeSignature<'a> { for (param, node) in parameters.into_iter().zip(node.arguments.iter()) { let arg = arguments.get(param).unwrap(); - let exp = TypeRef::Any(TypeId::TypeParameter(param)); + let exp = TypeRef::Any(TypeEnum::TypeParameter(param)); let mut env = Environment::new( arg.type_arguments(self.db()), exp_args.clone(), @@ -902,14 +901,14 @@ impl<'a> DefineAndCheckTypeSignature<'a> { pub(crate) fn define_type_bounds( state: &mut State, module: ModuleId, - class: ClassId, + type_id: TypeId, nodes: &mut [hir::TypeBound], ) -> TypeBounds { let mut bounds = TypeBounds::new(); for bound in nodes { let name = &bound.name.name; - let param = if let Some(id) = class.type_parameter(&state.db, name) { + let param = if let Some(id) = type_id.type_parameter(&state.db, name) { id } else { state.diagnostics.undefined_symbol( @@ -940,7 +939,7 @@ pub(crate) fn define_type_bounds( for req in &mut bound.requirements { let rules = Rules::default(); - let scope = TypeScope::new(module, TypeId::Class(class), None); + let scope = TypeScope::new(module, TypeEnum::Type(type_id), None); let mut definer = DefineTypeSignature::new(state, module, &scope, rules); @@ -974,7 +973,7 @@ mod tests { use crate::type_check::{DefineTypeSignature, TypeScope}; use location::Location; use types::{ - Class, ClassKind, ClosureId, Method, MethodKind, Trait, TypeId, + ClosureId, Method, MethodKind, Trait, Type, TypeEnum, TypeKind, TypeRef, Visibility, }; @@ -991,15 +990,15 @@ mod tests { #[test] fn test_type_scope_new() { let mut state = State::new(Config::new()); - let int = Class::alloc( + let int = Type::alloc( &mut state.db, "Int".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let self_type = TypeId::ClassInstance(ClassInstance::new(int)); + let self_type = TypeEnum::TypeInstance(TypeInstance::new(int)); let module = module_type(&mut state, "foo"); let scope = TypeScope::new(module, self_type, None); @@ -1020,10 +1019,10 @@ mod tests { Visibility::Private, MethodKind::Instance, ); - let array = Class::alloc( + let array = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1037,10 +1036,10 @@ mod tests { module.new_symbol( &mut state.db, "Array".to_string(), - Symbol::Class(array), + Symbol::Type(array), ); - let array_ins = TypeId::ClassInstance(ClassInstance::new(array)); + let array_ins = TypeEnum::TypeInstance(TypeInstance::new(array)); let scope = TypeScope::new(module, array_ins, Some(method)); assert_eq!( @@ -1053,7 +1052,7 @@ mod tests { ); assert_eq!( scope.symbol(&mut state.db, "Array"), - Some(Symbol::Class(array)) + Some(Symbol::Type(array)) ); assert!(scope.symbol(&mut state.db, "Foo").is_none()); } @@ -1061,15 +1060,15 @@ mod tests { #[test] fn test_define_type_signature_as_trait_instance_with_trait() { let mut state = State::new(Config::new()); - let int = Class::alloc( + let int = Type::alloc( &mut state.db, "Int".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let self_type = TypeId::ClassInstance(ClassInstance::new(int)); + let self_type = TypeEnum::TypeInstance(TypeInstance::new(int)); let module = module_type(&mut state, "foo"); let to_string = Trait::alloc( &mut state.db, @@ -1099,20 +1098,20 @@ mod tests { #[test] fn test_define_type_signature_as_trait_instance_with_invalid_type() { let mut state = State::new(Config::new()); - let int = Class::alloc( + let int = Type::alloc( &mut state.db, "Int".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let self_type = TypeId::ClassInstance(ClassInstance::new(int)); + let self_type = TypeEnum::TypeInstance(TypeInstance::new(int)); let module = module_type(&mut state, "foo"); - let string = Class::alloc( + let string = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1121,7 +1120,7 @@ mod tests { module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string), + Symbol::Type(string), ); let scope = TypeScope::new(module, self_type, None); @@ -1138,21 +1137,20 @@ mod tests { fn test_define_type_signature_with_owned_type() { let mut state = State::new(Config::new()); let module = module_type(&mut state, "foo"); - let class_id = Class::alloc( + let type_id = Type::alloc( &mut state.db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_instance = - TypeId::ClassInstance(ClassInstance::new(class_id)); + let type_ins = TypeEnum::TypeInstance(TypeInstance::new(type_id)); module.new_symbol( &mut state.db, "A".to_string(), - Symbol::Class(class_id), + Symbol::Type(type_id), ); let mut node = hir::Type::Named(Box::new(hir_type_name( @@ -1160,14 +1158,14 @@ mod tests { Vec::new(), cols(1, 1), ))); - let scope = TypeScope::new(module, class_instance, None); + let scope = TypeScope::new(module, type_ins, None); let rules = Rules::default(); let type_ref = DefineTypeSignature::new(&mut state, module, &scope, rules) .define_type(&mut node); assert!(!state.diagnostics.has_errors()); - assert_eq!(type_ref, TypeRef::Owned(class_instance)); + assert_eq!(type_ref, TypeRef::Owned(type_ins)); assert_eq!( constructor!(node, hir::Type::Named).resolved_type, type_ref @@ -1179,21 +1177,20 @@ mod tests { let mut state = State::new(Config::new()); let foo_mod = module_type(&mut state, "foo"); let bar_mod = module_type(&mut state, "bar"); - let class_id = Class::alloc( + let type_id = Type::alloc( &mut state.db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_instance = - TypeId::ClassInstance(ClassInstance::new(class_id)); + let type_ins = TypeEnum::TypeInstance(TypeInstance::new(type_id)); foo_mod.new_symbol( &mut state.db, "A".to_string(), - Symbol::Class(class_id), + Symbol::Type(type_id), ); bar_mod.new_symbol( @@ -1213,14 +1210,14 @@ mod tests { location: cols(1, 1), })); - let scope = TypeScope::new(bar_mod, class_instance, None); + let scope = TypeScope::new(bar_mod, type_ins, None); let rules = Rules::default(); let type_ref = DefineTypeSignature::new(&mut state, bar_mod, &scope, rules) .define_type(&mut node); assert!(!state.diagnostics.has_errors()); - assert_eq!(type_ref, TypeRef::Owned(class_instance)); + assert_eq!(type_ref, TypeRef::Owned(type_ins)); assert_eq!( constructor!(node, hir::Type::Named).resolved_type, type_ref @@ -1231,21 +1228,20 @@ mod tests { fn test_define_type_signature_with_private_type() { let mut state = State::new(Config::new()); let module = module_type(&mut state, "foo"); - let class_id = Class::alloc( + let type_id = Type::alloc( &mut state.db, "_A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_instance = - TypeId::ClassInstance(ClassInstance::new(class_id)); + let type_ins = TypeEnum::TypeInstance(TypeInstance::new(type_id)); module.new_symbol( &mut state.db, "_A".to_string(), - Symbol::Class(class_id), + Symbol::Type(type_id), ); let mut node = hir::Type::Named(Box::new(hir_type_name( @@ -1253,7 +1249,7 @@ mod tests { Vec::new(), cols(1, 1), ))); - let scope = TypeScope::new(module, class_instance, None); + let scope = TypeScope::new(module, type_ins, None); let rules = Rules { allow_private_types: false, ..Default::default() }; DefineTypeSignature::new(&mut state, module, &scope, rules) @@ -1270,21 +1266,20 @@ mod tests { fn test_define_type_signature_with_ref_type() { let mut state = State::new(Config::new()); let module = module_type(&mut state, "foo"); - let class_id = Class::alloc( + let type_id = Type::alloc( &mut state.db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_instance = - TypeId::ClassInstance(ClassInstance::new(class_id)); + let type_ins = TypeEnum::TypeInstance(TypeInstance::new(type_id)); module.new_symbol( &mut state.db, "A".to_string(), - Symbol::Class(class_id), + Symbol::Type(type_id), ); let mut node = hir::Type::Ref(Box::new(hir::ReferenceType { @@ -1293,14 +1288,14 @@ mod tests { )), location: cols(1, 1), })); - let scope = TypeScope::new(module, class_instance, None); + let scope = TypeScope::new(module, type_ins, None); let rules = Rules::default(); let type_ref = DefineTypeSignature::new(&mut state, module, &scope, rules) .define_type(&mut node); assert!(!state.diagnostics.has_errors()); - assert_eq!(type_ref, TypeRef::Ref(class_instance)); + assert_eq!(type_ref, TypeRef::Ref(type_ins)); assert_eq!( constructor!( @@ -1315,15 +1310,15 @@ mod tests { #[test] fn test_define_type_signature_with_closure_type() { let mut state = State::new(Config::new()); - let int = Class::alloc( + let int = Type::alloc( &mut state.db, "Int".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let self_type = TypeId::ClassInstance(ClassInstance::new(int)); + let self_type = TypeEnum::TypeInstance(TypeInstance::new(int)); let module = module_type(&mut state, "foo"); let mut node = hir::Type::Closure(Box::new(hir::ClosureType { arguments: Vec::new(), @@ -1337,7 +1332,7 @@ mod tests { DefineTypeSignature::new(&mut state, module, &scope, rules) .define_type(&mut node); - assert_eq!(type_ref, TypeRef::Owned(TypeId::Closure(ClosureId(0)))); + assert_eq!(type_ref, TypeRef::Owned(TypeEnum::Closure(ClosureId(0)))); assert!(!state.diagnostics.has_errors()); assert_eq!( constructor!(node, hir::Type::Closure).resolved_type, @@ -1349,35 +1344,27 @@ mod tests { fn test_check_type_signature_with_incorrect_number_of_arguments() { let mut state = State::new(Config::new()); let module = module_type(&mut state, "foo"); - let class_a = Class::alloc( + let type_a = Type::alloc( &mut state.db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_b = Class::alloc( + let type_b = Type::alloc( &mut state.db, "B".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let instance_a = TypeId::ClassInstance(ClassInstance::new(class_a)); + let instance_a = TypeEnum::TypeInstance(TypeInstance::new(type_a)); - module.new_symbol( - &mut state.db, - "A".to_string(), - Symbol::Class(class_a), - ); + module.new_symbol(&mut state.db, "A".to_string(), Symbol::Type(type_a)); - module.new_symbol( - &mut state.db, - "B".to_string(), - Symbol::Class(class_b), - ); + module.new_symbol(&mut state.db, "B".to_string(), Symbol::Type(type_b)); let mut node = hir::Type::Named(Box::new(hir_type_name( "A", @@ -1416,44 +1403,44 @@ mod tests { module, Location::default(), ); - let list_class = Class::alloc( + let list_type = Type::alloc( &mut state.db, "List".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); let list_param = - list_class.new_type_parameter(&mut state.db, "T".to_string()); + list_type.new_type_parameter(&mut state.db, "T".to_string()); let requirement = TraitInstance::new(to_string); list_param.add_requirements(&mut state.db, vec![requirement]); - let string_class = Class::alloc( + let string_type = Type::alloc( &mut state.db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let instance_a = TypeId::ClassInstance(ClassInstance::rigid( + let instance_a = TypeEnum::TypeInstance(TypeInstance::rigid( &mut state.db, - list_class, + list_type, &TypeBounds::new(), )); module.new_symbol( &mut state.db, "List".to_string(), - Symbol::Class(list_class), + Symbol::Type(list_type), ); module.new_symbol( &mut state.db, "String".to_string(), - Symbol::Class(string_class), + Symbol::Type(string_type), ); module.new_symbol( diff --git a/docs/inko.pkg b/docs/inko.pkg index e3fc49a2e..cadb3f337 100644 --- a/docs/inko.pkg +++ b/docs/inko.pkg @@ -1,4 +1,4 @@ require https://github.com/yorickpeterse/inko-wobsite 0.19.0 fa5e47733423aa6a902028e69de5a374a1757377 require https://github.com/yorickpeterse/inko-builder 0.13.0 7a38803e1fcd80e19ad2ea8fd90b9babf70e93a6 require https://github.com/yorickpeterse/inko-markdown 0.21.0 3726c10b499242cb3febc931a82e35217e2f987a -require https://github.com/yorickpeterse/inko-syntax 0.14.0 ef03ca1958a17560082495ec6367bd50b02d3fde +require https://github.com/yorickpeterse/inko-syntax 0.16.0 21cd93afb84c093c28bb3629e0b8b9441f6b1822 diff --git a/docs/menu.json b/docs/menu.json index 580ef2a60..8234d916f 100644 --- a/docs/menu.json +++ b/docs/menu.json @@ -18,7 +18,7 @@ "getting-started/control-flow.md", "getting-started/variables.md", "getting-started/methods.md", - "getting-started/classes.md", + "getting-started/types.md", "getting-started/traits.md", "getting-started/visibility.md", "getting-started/modules.md", diff --git a/docs/source/design/compiler.md b/docs/source/design/compiler.md index 2f09b50bf..a7bfbdcb9 100644 --- a/docs/source/design/compiler.md +++ b/docs/source/design/compiler.md @@ -29,7 +29,7 @@ The compilation process consists of the following steps: Parsing is a topic extensively covered in computer science, so we won't go over it in much detail. Inko uses a handwritten LL(1) recursive descend parser, and a -separate lexer/tokeniser. Each type of thing to parse (e.g. a class or an array +separate lexer/tokeniser. Each type of thing to parse (e.g. a type or an array literal) typically has a corresponding function in the parser. AST nodes are just plain structures. @@ -325,8 +325,8 @@ refreshed automatically. Incremental compilation can be disabled using ### Methods -As part of code generation, methods are stored in a class such that we can -efficiently perform dynamic dispatch. Each class has a table for its method, +As part of code generation, methods are stored in a type such that we can +efficiently perform dynamic dispatch. Each type has a table for its method, with the size being a power of two. Each method is given a globally unique hash code based on its name. This means different methods with the same name share the same hash code, but this is OK because a type can only define a method with diff --git a/docs/source/getting-started/arrays.md b/docs/source/getting-started/arrays.md index aa7ca4673..723287c87 100644 --- a/docs/source/getting-started/arrays.md +++ b/docs/source/getting-started/arrays.md @@ -30,7 +30,7 @@ The `get` method returns an immutable borrow to a value, while `get_mut` returns a mutable borrow: ```inko -class Person { +type Person { let @name: String } @@ -43,7 +43,7 @@ people.get_mut(0) # => mut Person(name: 'Alice') If the index is out of bounds, `get` and `get_mut` panic: ```inko -class Person { +type Person { let @name: String } @@ -56,7 +56,7 @@ The `opt` and `opt_mut` methods are similar to `get` and `get_mut`, except they wrap the return values in an `Option` value: ```inko -class Person { +type Person { let @name: String } diff --git a/docs/source/getting-started/concurrency.md b/docs/source/getting-started/concurrency.md index 81dc6376d..87f94f9f1 100644 --- a/docs/source/getting-started/concurrency.md +++ b/docs/source/getting-started/concurrency.md @@ -15,10 +15,10 @@ as these guides explain the basics of what we'll build upon in this guide. To recap, Inko uses lightweight processes for concurrency. These processes don't share memory, instead values are _moved_ between processes. Processes are -defined using `class async`: +defined using `type async`: ```inko -class async Counter { +type async Counter { let @number: Int } ``` @@ -27,7 +27,7 @@ Interacting with processes is done using `async` methods. Such methods are defined like so: ```inko -class async Counter { +type async Counter { let @number: Int fn async mut increment(amount: Int) { @@ -157,7 +157,7 @@ Here's a more complicated example: import std.net.ip (IpAddress) import std.net.socket (TcpServer) -class async Main { +type async Main { fn async main { let server = recover TcpServer .new(IpAddress.v4(127, 0, 0, 1), port: 40_000) @@ -190,11 +190,11 @@ isn't available. When spawning a process, the values assigned to its fields must be sendable: ```inko -class async Example { +type async Example { let @numbers: Array[Int] } -class async Main { +type async Main { fn async main { Example(numbers: recover [10, 20]) } @@ -217,7 +217,7 @@ methods: ```inko import std.sync (Future, Promise) -class async Counter { +type async Counter { let @value: Int fn async mut increment { @@ -229,7 +229,7 @@ class async Counter { } } -class async Main { +type async Main { fn async main { let counter = Counter(value: 0) diff --git a/docs/source/getting-started/control-flow.md b/docs/source/getting-started/control-flow.md index a29dd2620..447eb7c9a 100644 --- a/docs/source/getting-started/control-flow.md +++ b/docs/source/getting-started/control-flow.md @@ -14,7 +14,7 @@ For conditionals we use `if`: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let num = 42 @@ -32,7 +32,7 @@ Inko also supports `else if` like so: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let num = 50 @@ -56,7 +56,7 @@ keywords: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let num = 50 @@ -85,7 +85,7 @@ Here we use a conditional loop to print a number 10 times: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let mut num = 0 @@ -121,7 +121,7 @@ import std.process (sleep) import std.stdio (Stdout) import std.time (Duration) -class async Main { +type async Main { fn async main { let out = Stdout.new let mut num = 0 @@ -142,7 +142,7 @@ the inner-most loop: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new diff --git a/docs/source/getting-started/destructors.md b/docs/source/getting-started/destructors.md index 2a3d5c810..1268d90de 100644 --- a/docs/source/getting-started/destructors.md +++ b/docs/source/getting-started/destructors.md @@ -12,7 +12,7 @@ Types can define a method to run when before they are dropped, known as a import std.drop (Drop) import std.stdio (Stdout) -class Person { +type Person { let @name: String } @@ -22,7 +22,7 @@ impl Drop for Person { } } -class async Main { +type async Main { fn async main { Person(name: 'Alice') } @@ -44,7 +44,7 @@ dropped escaping the `drop` call: import std.drop (Drop) import std.stdio (Stdout) -class Person { +type Person { let @name: String let @people: mut Array[ref Person] } @@ -56,7 +56,7 @@ impl Drop for Person { } } -class async Main { +type async Main { fn async main { let people = [] let person = Person(name: 'Alice', people: people) diff --git a/docs/source/getting-started/ffi.md b/docs/source/getting-started/ffi.md index 91885800a..796e65348 100644 --- a/docs/source/getting-started/ffi.md +++ b/docs/source/getting-started/ffi.md @@ -131,7 +131,7 @@ it as `test.inko`: ```inko import extern "m" -class async Main { +type async Main { fn async main {} } ``` @@ -181,7 +181,7 @@ instead: ```inko import extern "z" -class async Main { +type async Main { fn async main {} } ``` @@ -233,7 +233,7 @@ import extern "m" fn extern ceil(value: Float64) -> Float64 -class async Main { +type async Main { fn async main { let out = Stdout.new @@ -267,7 +267,7 @@ Variadic functions are also supported, and are defined as follows: ```inko fn extern printf(format: Pointer[UInt8], ...) -> Int32 -class async Main { +type async Main { fn async main { printf("Hello %s\n".to_pointer, "Inko".to_pointer) } @@ -283,26 +283,26 @@ additional arguments, because it doesn't know what the expected types are. ## Structures -Inko supports defining signatures for C structures, similar to classes. This is -done using the `class extern` syntax. For example, to define the `timespec` +Inko supports defining signatures for C structures, similar to types. This is +done using the `type extern` syntax. For example, to define the `timespec` structure from the libc `time.h` header, we'd write the following: ```inko -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } ``` -Like classes, we can create instances of these structs: +Like types, we can create instances of these structs: ```inko -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class async Main { +type async Main { fn async main { Timespec(tv_sec: 123 as Int64, tv_nsec: 456 as Int64) } @@ -314,12 +314,12 @@ reserves the necessary stack space but doesn't initialize it. This is useful when dealing with large structs that are initialized by a C function: ```inko -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class async Main { +type async Main { fn async main { let spec = Timespec() @@ -330,15 +330,15 @@ class async Main { Structures are allocated on the stack and are value types, meaning a move results in a copy (unless this is optimised away). Reading and writing of -structure fields uses the same syntax as regular Inko classes: +structure fields uses the same syntax as regular Inko types: ```inko -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class async Main { +type async Main { fn async main { let spec = Timespec(tv_sec: 123 as Int64, tv_nsec: 456 as Int64) @@ -354,21 +354,21 @@ may lead to memory leaks if you don't manually run these where necessary. If a structure is stored in a field, referring to the field doesn't incur a copy, instead you get a pointer to the structure. This makes it easier to work -with structures stored in Inko classes: +with structures stored in Inko types: ```inko import std.stdio (Stdout) -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class Box { +type Box { let @time: Timespec } -class async Main { +type async Main { fn async main { let out = Stdout.new let spec = Timespec(tv_sec: 123 as Int64, tv_nsec: 456 as Int64) @@ -399,14 +399,14 @@ import std.stdio (Stdout) let CLOCK_REALTIME = 0 -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } fn extern clock_gettime(id: Int32, time: Pointer[Timespec]) -> Int32 -class async Main { +type async Main { fn async main { let out = Stdout.new let spec = Timespec(tv_sec: 0 as Int64, tv_nsec: 0 as Int64) @@ -438,7 +438,7 @@ fn extern example(value: Int) -> Int { value } -class async Main { +type async Main { fn async main { let pointer_to_method = mut example } @@ -459,12 +459,12 @@ Dereferencing a pointer is done by reading from and writing to the pseudo field ```inko import std.stdio (Stdout) -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class async Main { +type async Main { fn async main { let out = Stdout.new let spec = Timespec(tv_sec: 0 as Int64, tv_nsec: 0 as Int64) @@ -487,12 +487,12 @@ mutate data pointed to in-place: ```inko import std.stdio (Stdout) -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class async Main { +type async Main { fn async main { let out = Stdout.new let spec = Timespec(tv_sec: 0 as Int64, tv_nsec: 0 as Int64) @@ -524,12 +524,12 @@ pointer. For example, here we mutate `tv_nsec` using such an approach: ```inko import std.stdio (Stdout) -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class async Main { +type async Main { fn async main { let out = Stdout.new let spec = Timespec(tv_sec: 0 as Int64, tv_nsec: 0 as Int64) @@ -559,14 +559,14 @@ import std.io (Error) let CLOCK_REALTIME = 0 -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } fn extern clock_gettime(id: Int32, time: Pointer[Timespec]) -> Int32 -class async Main { +type async Main { fn async main { let out = Stdout.new let spec = Timespec(tv_sec: 0 as Int64, tv_nsec: 0 as Int64) diff --git a/docs/source/getting-started/files.md b/docs/source/getting-started/files.md index a475070f0..8cfe04b45 100644 --- a/docs/source/getting-started/files.md +++ b/docs/source/getting-started/files.md @@ -13,7 +13,7 @@ To start, create the file `files.inko` with the following contents: import std.fs.file (ReadWriteFile) import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let file = ReadWriteFile.new('hello.txt'.to_path).get @@ -59,7 +59,7 @@ If we just want to read a file, we'd do so as follows: import std.fs.file (ReadOnlyFile) import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let file = ReadOnlyFile.new('hello.txt'.to_path).get @@ -90,7 +90,7 @@ If you just want to write to a file, you'd use the `WriteOnlyFile` type: ```inko import std.fs.file (WriteOnlyFile) -class async Main { +type async Main { fn async main { let file = WriteOnlyFile.new('hello.txt'.to_path).get diff --git a/docs/source/getting-started/generics.md b/docs/source/getting-started/generics.md index 1b77caa60..39dc76239 100644 --- a/docs/source/getting-started/generics.md +++ b/docs/source/getting-started/generics.md @@ -6,10 +6,10 @@ Types and methods can be generic, meaning that instead of supporting a single fixed type (e.g. `String`), they can operate on many different types. Take the -following class for example: +following type for example: ```inko -class Box { +type Box { let @value: String } ``` @@ -20,10 +20,10 @@ solve this problem, without having to copy-paste large amounts of code. ## Generic types -Generic classes are defined as follows: +Generic types are defined as follows: ```inko -class Box[T] { +type Box[T] { let @value: T } ``` @@ -44,7 +44,7 @@ Box(value: 1.123) We can of course define more than just one type parameter: ```inko -class Pair[A, B] { +type Pair[A, B] { let @a: A let @b: B } @@ -114,7 +114,7 @@ trait ToString { fn to_string -> String } -class Box[T: ToString] { +type Box[T: ToString] { let @value: T } ``` @@ -129,7 +129,7 @@ Type parameters can define multiple required traits as follows: trait A {} trait B {} -class Box[T: A + B] { +type Box[T: A + B] { let @value: T } ``` @@ -142,7 +142,7 @@ The required traits can also be made generic: ```inko trait Equal[A] {} -class Example[B: Equal[B]] { +type Example[B: Equal[B]] { ... } ``` @@ -169,7 +169,7 @@ trait Update { fn mut update } -class Example[T: Update] { +type Example[T: Update] { let @value: T fn mut update { @@ -197,7 +197,7 @@ trait Update { fn mut update } -class Example[T: mut + Update] { +type Example[T: mut + Update] { let @value: T fn mut update { @@ -207,14 +207,14 @@ class Example[T: mut + Update] { ``` Type parameter requirements can also be specified when reopening a generic -class: +type: ```inko trait Update { fn mut update } -class Example[T] { +type Example[T] { let @value: T } diff --git a/docs/source/getting-started/hello-concurrency.md b/docs/source/getting-started/hello-concurrency.md index 29b9c8a23..56ed5153a 100644 --- a/docs/source/getting-started/hello-concurrency.md +++ b/docs/source/getting-started/hello-concurrency.md @@ -13,13 +13,13 @@ import std.process (sleep) import std.stdio (Stdout) import std.time (Duration) -class async Printer { +type async Printer { fn async print(message: String) { let _ = Stdout.new.print(message) } } -class async Main { +type async Main { fn async main { Printer().print('Hello') Printer().print('world') @@ -44,7 +44,7 @@ or "world" and "Hello" on separate lines. ## Explanation Inko uses "lightweight processes" for concurrency. Such processes are defined -using the syntax `class async`, such as `class async Printer { ... }` in our +using the syntax `type async`, such as `type async Printer { ... }` in our program. We create instances of these processes using the syntax `Printer()`. For such a @@ -54,7 +54,7 @@ syntax. The details of how this works, what to keep in mind, etc, are covered separately. The `sleep(...)` line is needed such that the main process (defined using -`class async Main`) doesn't stop before the `Printer` processes print the +`type async Main`) doesn't stop before the `Printer` processes print the messages to the terminal. ## Futures and Promises @@ -67,7 +67,7 @@ program to the following: import std.stdio (Stdout) import std.sync (Future, Promise) -class async Printer { +type async Printer { fn async print(message: String, output: uni Promise[Nil]) { let _ = Stdout.new.print(message) @@ -75,7 +75,7 @@ class async Printer { } } -class async Main { +type async Main { fn async main { let future1 = match Future.new { case (future, promise) -> { @@ -130,7 +130,7 @@ We can rewrite the example from earlier using `Channel` as follows: import std.stdio (Stdout) import std.sync (Channel) -class async Printer { +type async Printer { fn async print(message: String, output: uni Channel[Nil]) { let _ = Stdout.new.print(message) @@ -138,7 +138,7 @@ class async Printer { } } -class async Main { +type async Main { fn async main { let chan = Channel.new diff --git a/docs/source/getting-started/hello-error-handling.md b/docs/source/getting-started/hello-error-handling.md index 8097ad985..6c8f3ef9d 100644 --- a/docs/source/getting-started/hello-error-handling.md +++ b/docs/source/getting-started/hello-error-handling.md @@ -14,7 +14,7 @@ from the previous tutorial and change it to the following: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { Stdout.new.print('Hello, world!').get } @@ -62,7 +62,7 @@ We'll start with the first option: ignoring the error. To do so, change ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let _ = Stdout.new.print('Hello, world!') } @@ -108,7 +108,7 @@ fn log(message: String) { # This is just an example, so the method doesn't actually do anything. } -class async Main { +type async Main { fn async main { match Stdout.new.print('Hello, world!') { case Ok(_) -> {} diff --git a/docs/source/getting-started/hello-world.md b/docs/source/getting-started/hello-world.md index 4883ebb9b..b0df69fa7 100644 --- a/docs/source/getting-started/hello-world.md +++ b/docs/source/getting-started/hello-world.md @@ -10,7 +10,7 @@ terminal. Create a file called `hello.inko` with the following contents: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { Stdout.new.print('Hello, world!') } @@ -37,7 +37,7 @@ This imports the `Stdout` type, used for writing text to the terminal's standard output stream. After the import we encounter the following: ```inko -class async Main { +type async Main { fn async main { } @@ -45,7 +45,7 @@ class async Main { ``` Inko uses lightweight processes (which we'll cover separately), which are -defined using the syntax `class async NAME { ... }`. The main process is always +defined using the syntax `type async NAME { ... }`. The main process is always called "Main", and is required to define an "async" instance method called "main". diff --git a/docs/source/getting-started/maps.md b/docs/source/getting-started/maps.md index ee2ff41e3..6a35b3b70 100644 --- a/docs/source/getting-started/maps.md +++ b/docs/source/getting-started/maps.md @@ -39,7 +39,7 @@ The `get` method returns an immutable borrow to the value of a key, while `get_mut` returns a mutable borrow: ```inko -class Person { +type Person { let @name: String } @@ -54,7 +54,7 @@ people.get_mut('alice') # => mut Person(name: 'Alice') If the key doesn't exist, `get` and `get_mut` panic: ```inko -class Person { +type Person { let @name: String } @@ -69,7 +69,7 @@ The `opt` and `opt_mut` methods are similar to `get` and `get_mut`, except they wrap the return values in an `Option` value: ```inko -class Person { +type Person { let @name: String } diff --git a/docs/source/getting-started/memory-management.md b/docs/source/getting-started/memory-management.md index ef04e1fb9..7027aa82e 100644 --- a/docs/source/getting-started/memory-management.md +++ b/docs/source/getting-started/memory-management.md @@ -14,9 +14,9 @@ we'll take a look at the basics of working with these different references. We'll start with a simple list of cats: ```inko -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] } @@ -36,9 +36,9 @@ Let's adjust the program to print the number of cats to the terminal: ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] @@ -54,9 +54,9 @@ Now we'll change the program to the following: ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] let more_cats = cats @@ -94,9 +94,9 @@ Immutable borrows are created using the `ref` keyword: ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] let more_cats = ref cats @@ -111,9 +111,9 @@ Mutable borrows are created using the `mut` keyword: ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] let more_cats = mut cats @@ -134,9 +134,9 @@ allow mutating of the borrowed data, while immutable borrows don't. For example: ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] let cats_ref = ref cats @@ -158,9 +158,9 @@ To fix this, we need to use a mutable borrow: ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] let cats_mut = mut cats @@ -176,13 +176,13 @@ When passing a value to something that expects a borrow, Inko automatically borrows the value according to the expected borrow: ```inko -class Person { +type Person { let @name: String } fn example(person: ref Person) {} -class async Main { +type async Main { fn async main { let person = Person(name: 'Alice') @@ -229,9 +229,9 @@ error known as a "panic" is produced, terminating the program: ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = [Cat(), Cat()] let borrow = ref cats @@ -307,9 +307,9 @@ exist when the unique reference is moved around. To illustrate this, change the ```inko import std.stdio (Stdout) -class Cat {} +type Cat {} -class async Main { +type async Main { fn async main { let cats = recover [Cat(), Cat()] let borrow = ref cats @@ -347,7 +347,7 @@ contents: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let a = 42 diff --git a/docs/source/getting-started/methods.md b/docs/source/getting-started/methods.md index 1e6a7faf3..7d6fa53bf 100644 --- a/docs/source/getting-started/methods.md +++ b/docs/source/getting-started/methods.md @@ -14,21 +14,21 @@ Methods are defined using the `fn` keyword. An example of this which we've seen so far is the `main` method defined like so: ```inko -class async Main { +type async Main { fn async main { } } ``` -We can also define methods outside of classes like so: +We can also define methods outside of types like so: ```inko fn example { } -class async Main { +type async Main { fn async main { example } @@ -39,13 +39,13 @@ Here we define the method `example`, then call it in the `main` method. The `example` method known as a "module method" because it's defined at the top-level scope, which is a module (more on this later). -## Methods and classes +## Methods and types -Within a class, we can define two types of methods: static methods, and instance +Within a type, we can define two types of methods: static methods, and instance methods. Instance methods are defined as follows: ```inko -class Person { +type Person { fn name { } @@ -55,22 +55,22 @@ class Person { Meanwhile, static methods are defined using `fn static` as follows: ```inko -class Person { +type Person { fn static new { } } ``` -The difference is that static methods don't require an instance of the class +The difference is that static methods don't require an instance of the type they are defined in, while instance methods do. This means that to call `new` in the above example, you'd write `Person.new`, while calling `name` would require -you to create an instance of the class, then use `person.name` where `person` is -a variable storing the instance of the class. +you to create an instance of the type, then use `person.name` where `person` is +a variable storing the instance of the type. -When a class is defined using `class async`, you can also define methods using +When a type is defined using `type async`, you can also define methods using `fn async`. These methods are the messages you can send to a process. It's a -compile-time error to define an `fn async` method on a regular class. +compile-time error to define an `fn async` method on a regular type. ## Arguments @@ -171,7 +171,7 @@ fn person(name: String, age: Int) -> String { age } -class async Main { +type async Main { fn async main { } @@ -187,11 +187,11 @@ test.inko:2:3 error(invalid-type): expected a value of type 'String', found 'Int ## Mutability -Trait and class instance methods are immutable by default, preventing them from +Trait and type instance methods are immutable by default, preventing them from mutating the data stored in their receivers. For example: ```inko -class Person { +type Person { let @name: String fn change_name(name: String) { @@ -205,7 +205,7 @@ and `change_name` is immutable. To allow mutations, use the `mut` keyword like so: ```inko -class Person { +type Person { let @name: String fn mut change_name(name: String) { @@ -224,7 +224,7 @@ Regular instance methods can take ownership of their receivers by defining them using `fn move`: ```inko -class Person { +type Person { let @name: String fn move into_name -> String { @@ -247,7 +247,7 @@ values. Closures are defined using the `fn` keyword while leaving out a name: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new @@ -263,7 +263,7 @@ argument types and the return type are inferred: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new @@ -278,7 +278,7 @@ explicit type signatures are necessary: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new @@ -299,7 +299,7 @@ from causing bugs, the compiler produces a compile-time error when you try to assign captured variables a new value: ```inko -class async Main { +type async Main { fn async main { let mut a = 10 @@ -319,7 +319,7 @@ is done by using the `fn move` keyword. When using `fn move`, you _can_ assign the captured variable a new value: ```inko -class async Main { +type async Main { fn async main { let mut nums = [10] diff --git a/docs/source/getting-started/modules.md b/docs/source/getting-started/modules.md index 9c30a6ed2..64edc07ae 100644 --- a/docs/source/getting-started/modules.md +++ b/docs/source/getting-started/modules.md @@ -5,7 +5,7 @@ --- Inko programs are divided into many modules. A module is an Inko source file -defining methods, classes, traits, constants, and more. +defining methods, types, traits, constants, and more. Modules and their symbols can be imported into other modules using the `import` keyword. For example, in the tutorials covered so far we've seen instances of @@ -14,20 +14,20 @@ this such as: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { Stdout.new.print('hello') } } ``` -Here we import the `Stdout` class from the module `std.stdio`. We can also +Here we import the `Stdout` type from the module `std.stdio`. We can also import modules as a whole: ```inko import std.stdio -class async Main { +type async Main { fn async main { stdio.Stdout.new.print('hello') } @@ -39,7 +39,7 @@ Importing multiple symbols at once is also possible: ```inko import std.stdio (Stderr, Stdout) -class async Main { +type async Main { fn async main { Stdout.new.print('hello') Stderr.new.print('world') @@ -53,7 +53,7 @@ conflicts by using a custom alias: ```inko import std.stdio (Stderr as ERR, Stdout as OUT) -class async Main { +type async Main { fn async main { OUT.new.print('hello') ERR.new.print('world') diff --git a/docs/source/getting-started/pattern-matching.md b/docs/source/getting-started/pattern-matching.md index 80d4ff072..2d9b27fe3 100644 --- a/docs/source/getting-started/pattern-matching.md +++ b/docs/source/getting-started/pattern-matching.md @@ -13,7 +13,7 @@ contents: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let val = Option.Some((42, 'hello')) @@ -91,8 +91,7 @@ only have two possible values (`true` and `false`). ### Enum patterns -If the value matched against is an enum class, we can match against its -constructors: +If the value matched against is an enum, we can match against its constructors: ```inko match Option.Some(42) { @@ -108,13 +107,13 @@ When specifying the constructor pattern only its name is needed, the name of the type it belongs to isn't needed. This means `case Option.Some(42)` is invalid. -### Class patterns +### Type patterns -Pattern matching can also be performed against regular classes using class -literal patterns: +Pattern matching can also be performed against regular types using type literal +patterns: ```inko -class Person { +type Person { let @name: String let @age: Int } @@ -140,7 +139,7 @@ match person { } ``` -Class literal patterns are only available for regular classes. +Type literal patterns are only available for regular types. ### Tuple patterns @@ -218,7 +217,7 @@ match: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let val = Option.Some((42, 'hello')) @@ -357,7 +356,7 @@ possible cases must be covered: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let val = Option.Some((42, 'hello')) @@ -383,7 +382,7 @@ the match exhaustive in a variety of ways, such as the following: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let val = Option.Some((42, 'hello')) @@ -405,7 +404,7 @@ of redundant patterns: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let val = Option.Some((42, 'hello')) @@ -431,7 +430,7 @@ course the compiler is also able to detect more complicated redundant patterns: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let out = Stdout.new let val = Option.Some((42, 'hello')) @@ -452,7 +451,7 @@ detect that the second `case` is redundant. - Range patterns aren't supported, instead you can use pattern guards. - Types defining custom destructors can't be matched against. -- `async` classes can't be matched against. +- `async` types can't be matched against. - Matching against `Float` isn't supported, as you'll likely run into precision/rounding errors. - The value matched against can't be a trait. diff --git a/docs/source/getting-started/sockets.md b/docs/source/getting-started/sockets.md index c161f5711..e9576ebfb 100644 --- a/docs/source/getting-started/sockets.md +++ b/docs/source/getting-started/sockets.md @@ -15,7 +15,7 @@ import std.net.ip (IpAddress) import std.net.socket (UdpSocket) import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let stdout = Stdout.new let server = UdpSocket.new(IpAddress.v4(0, 0, 0, 0), port: 0).get @@ -99,7 +99,7 @@ import std.net.ip (IpAddress) import std.net.socket (TcpServer) import std.stdio (Stdout) -class async Main { +type async Main { fn async main { let stdout = Stdout.new let server = TcpServer.new(IpAddress.v4(0, 0, 0, 0), port: 9999).get @@ -122,7 +122,7 @@ contents: import std.net.ip (IpAddress) import std.net.socket (TcpClient) -class async Main { +type async Main { fn async main { let client = TcpClient.new(IpAddress.v4(0, 0, 0, 0), port: 9999).get diff --git a/docs/source/getting-started/strings.md b/docs/source/getting-started/strings.md index 715dd340c..95c8226e0 100644 --- a/docs/source/getting-started/strings.md +++ b/docs/source/getting-started/strings.md @@ -46,7 +46,7 @@ produce many intermediate `String` instances. To work around this, the type ```inko import std.string (StringBuffer) -class async Main { +type async Main { fn async main { let buf = StringBuffer.new diff --git a/docs/source/getting-started/traits.md b/docs/source/getting-started/traits.md index ada2edb81..efff64561 100644 --- a/docs/source/getting-started/traits.md +++ b/docs/source/getting-started/traits.md @@ -4,13 +4,12 @@ } --- -Unlike many other languages with classes, Inko doesn't support class -inheritance. Instead, code is shared between classes using "traits". Traits are -essentially blueprints for classes, specifying what methods must be implemented -and/or providing default implementations of methods a class may wish to -override. +Inko types doesn't support type inheritance. Instead, code is shared between +types using "traits". Traits are essentially blueprints for types, specifying +what methods must be implemented and/or providing default implementations of +methods a type may wish to override. -Let's say we want to convert different class instances into strings. We can do +Let's say we want to convert different type instances into strings. We can do so using traits: ```inko @@ -20,7 +19,7 @@ trait ToString { fn to_string -> String } -class Cat { +type Cat { let @name: String } @@ -30,7 +29,7 @@ impl ToString for Cat { } } -class async Main { +type async Main { fn async main { let garfield = Cat(name: 'Garfield') @@ -44,7 +43,7 @@ Running this program produces the output "Garfield". ## Default methods In this example, the `to_string` method in the `ToString` trait is a required -method. This means that any class that implements `ToString` _must_ provide an +method. This means that any type that implements `ToString` _must_ provide an implementation of the `to_string` method. Default trait methods are defined as follows: @@ -58,7 +57,7 @@ trait ToString { } } -class Cat { +type Cat { let @name: String } @@ -68,7 +67,7 @@ impl ToString for Cat { } } -class async Main { +type async Main { fn async main { let garfield = Cat(name: 'Garfield') @@ -91,7 +90,7 @@ trait ToString { } } -class Cat { +type Cat { let @name: String } @@ -99,7 +98,7 @@ impl ToString for Cat { } -class async Main { +type async Main { fn async main { let garfield = Cat(name: 'Garfield') diff --git a/docs/source/getting-started/classes.md b/docs/source/getting-started/types.md similarity index 75% rename from docs/source/getting-started/classes.md rename to docs/source/getting-started/types.md index b6b90c5df..7d4ecd366 100644 --- a/docs/source/getting-started/classes.md +++ b/docs/source/getting-started/types.md @@ -1,30 +1,30 @@ --- { - "title": "Classes" + "title": "Types" } --- -Classes are data structures that can store state and define methods. One such -class we've seen many times so far is the `Main` class, which defines the main -process to run. +Types are data structures that can store state and define methods. One such type +we've seen many times so far is the `Main` type, which defines the main process +to run. -Classes are defined using the `class` keyword like so: +Types are defined using the `type` keyword like so: ```inko -class Person { +type Person { } ``` -Here `Person` is the name of the class. Inside the curly braces the fields and -methods of a class are defined. +Here `Person` is the name of the type. Inside the curly braces the fields and +methods of a type are defined. ## Fields Fields are defined using the `let` keyword: ```inko -class Person { +type Person { let @name: String let @age: Int } @@ -35,7 +35,7 @@ The `@` symbol isn't part of the name, it's just used to disambiguate the syntax when referring to fields. Referring to fields uses the same syntax: ```inko -class Person { +type Person { let @name: String let @age: Int @@ -54,7 +54,7 @@ mutable, the type of a field is instead `mut T`, unless it's defined as a is exposed as-is: ```inko -class Person { +type Person { let @name: String let @age: Int let @grades: ref Array[Int] @@ -97,7 +97,7 @@ Similar to local variables, `:=` can be used to assign a field a new value and return its old value, instead of dropping the old value: ```inko -class Person { +type Person { let @name: String fn mut replace_name(new_name: String) -> String { @@ -106,12 +106,12 @@ class Person { } ``` -## Initialising classes +## Initialising types -An instance of a class is created as follows: +An instance of a type is created as follows: ```inko -class Person { +type Person { let @name: String let @age: Int } @@ -128,9 +128,9 @@ Person('Alice', 42) ``` ::: tip -It's recommended to avoid the use of positional arguments when a class defines +It's recommended to avoid the use of positional arguments when a type defines more than one field. This ensures that if the order of fields changes, you don't -need to update every line of code that creates an instance of the class. +need to update every line of code that creates an instance of the type. ::: The fields of an instance can be read from and written to directly, meaning we @@ -144,12 +144,12 @@ alice.name = 'Bob' alice.name # => 'Bob' ``` -Sometimes creating an instance of a class involves complex logic to assign +Sometimes creating an instance of a type involves complex logic to assign values to certain fields. In this case it's best to create a static method to create the instance for you. For example: ```inko -class Person { +type Person { let @name: String let @age: Int @@ -162,12 +162,12 @@ class Person { Of course nothing complex is happening here, instead we're just trying to illustrate what using a static method for this might look like. -## Reopening classes +## Reopening types -A class can be reopened using the `impl` keyword like so: +A type can be reopened using the `impl` keyword like so: ```inko -class Person { +type Person { let @name: String let @age: Int } @@ -179,16 +179,15 @@ impl Person { } ``` -When reopening a class, only new methods can be added to the class. It's a +When reopening a type, only new methods can be added to the type. It's a compile-time error to try to add a field or overwrite an existing method. ## Enums -Inko also has "enum classes", created using `class enum`. Enum classes are used -to create sum types, also known as enums: +Inko supports algebraic data types or "enums", defined using `type enum`: ```inko -class enum Letter { +type enum Letter { case A case B case C @@ -206,10 +205,10 @@ Letter.C ``` The constructors in an enum support arguments, allowing you to store data in -them similar to using regular classes with fields: +them similar to using regular types with fields: ```inko -class enum OptionalString { +type enum OptionalString { case None case Some(String) } @@ -221,19 +220,19 @@ We can then create an instance of the `OptionalString.Some` as follows: OptionalString.Some('hello') ``` -Unlike other types of classes, you can't use the syntax `OptionalString(...)` -to create an instance of an enum class. +Unlike other types, you can't use the syntax `OptionalString(...)` to create an +instance of an enum. ## Inline types -When defining a class using the `class` keyword, instances of such a class are +When defining a type using the `type` keyword, instances of such a type are allocated on the heap and accessed through a pointer. While this gives you the greatest amount of flexibility, heap allocations can be expensive if done frequently. To work around this, you can define a stack allocated type using the `inline` keyword: ```inko -class inline Person { +type inline Person { let @name: String let @age: Int } @@ -242,27 +241,27 @@ class inline Person { The `inline` keyword can also be combined with the `enum` keyword: ```inko -class inline enum Letter { +type inline enum Letter { case A case B case C } ``` -Similar to regular classes, you can borrow instances of `inline` classes and -still move the instance you are borrowing from around, without the need for +Similar to regular types, you can borrow instances of `inline` types and still +move the instance you are borrowing from around, without the need for compile-time borrow checking as is necessary in [Rust](https://www.rust-lang.org/). This is made possible (and safe) by _copying_ the stack allocated data upon borrowing it, and then increasing the borrow count for any interior heap values. -This approach does mean that `inline` classes come with some restrictions and +This approach does mean that `inline` types come with some restrictions and caveats: - Fields can't be assigned new values, as copying the stack data means the assignment would only be visible to the copy used by the assignment. -- Borrowing interior heap data means that if an `inline` class stores 8 heap - allocated values, borrowing the `inline` class results in 8 borrow count +- Borrowing interior heap data means that if an `inline` type stores 8 heap + allocated values, borrowing the `inline` type results in 8 borrow count increments. - Recursive `inline` types aren't supported, and the compiler will emit a compile-time error when encountering such types. This restriction exists @@ -276,10 +275,10 @@ caveats: Besides supporting regular stack allocated types, Inko also supports stack allocated immutable value types. Such types are defined using the `copy` keyword -when defining a class: +when defining a type: ```inko -class copy Number { +type copy Number { let @value: Int } ``` @@ -287,13 +286,13 @@ class copy Number { The `copy` modifier is also available for enums: ```inko -class copy enum Example { +type copy enum Example { case A(Int) case B(Float) } ``` -When using this modifier, instances of the class are allocated on the stack and +When using this modifier, instances of the type are allocated on the stack and become _immutable_ value types that are copied upon a move. For the above `Number` example that means the memory representation is the same as that of the `Int` type. @@ -304,7 +303,7 @@ to return a new copy of the instance containing the appropriate changes. For example: ```inko -class copy Number { +type copy Number { let @value: Int fn increment(amount: Int) -> Number { @@ -313,7 +312,7 @@ class copy Number { } ``` -Classes defined using the `copy` modifier can only store instances of the +Types defined using the `copy` modifier can only store instances of the following types: - `Int`, `Float`, `Bool`, `Nil` @@ -323,7 +322,7 @@ Most notably, `String` values can't be stored in a `copy` type as `String` uses atomic reference counting. This means the following definition is invalid: ```inko -class copy InvalidType { +type copy InvalidType { let @value: Array[Int] # Array[Int] isn't an `inline` type } ``` @@ -331,14 +330,14 @@ class copy InvalidType { The same restriction applies to generic type parameters: ```inko -class copy Box[T] { +type copy Box[T] { let @value: T } Box([10]) # T requires a `copy` type, but `Array[Int]` isn't such a type ``` -Classes defined using the `copy` keyword can't implement the `std.drop.Drop` +Types defined using the `copy` keyword can't implement the `std.drop.Drop` trait and thus can't define custom destructors. If you need to implement this trait, you'll have to use the `inline` keyword instead. @@ -347,7 +346,7 @@ Similar to `inline` types, `copy` types can't be cast to traits. ## Inline vs heap types With Inko supporting both heap and stack allocated types, one might wonder: -when should I use the `inline` or `copy` modifier when defining a class? To +when should I use the `inline` or `copy` modifier when defining a type To answer this question, ask yourself the following questions: - Do you need to assign a field a new value? @@ -357,33 +356,32 @@ answer this question, ask yourself the following questions: - Do you want to be able to cast the type to a trait? If the answer to any of these questions is "Yes", you'll want to use a regular -heap allocated `class`. If the answer to each question is "No", then you need to +heap allocated `type`. If the answer to each question is "No", then you need to decide between using the `inline` and `copy` modifier. The decision between these two modifiers is a bit easier: if you only intend to store `copy` types (`Int`, `Float`, etc) and don't intend to mutate the type, it's best to use -`class copy`, while for all other cases it's best to use `class inline`. +`type copy`, while for all other cases it's best to use `type inline`. ## Processes -Processes are defined using `class async`, and creating instances of such -classes spawns a new process: +Processes are defined using `type async`, and creating instances of such +types spawns a new process: ```inko -class async Cat { +type async Cat { } ``` -Just like regular classes, async classes can define fields using the `let` -keyword: +Just like regular types, async types can define fields using the `let` keyword: ```inko -class async Cat { +type async Cat { let @name: String } ``` -Creating instances of such classes is done the same way as with regular classes: +Creating instances of such types is done the same way as with regular types: ```inko Cat(name: 'Garfield') @@ -392,7 +390,7 @@ Cat(name: 'Garfield') Processes can define `async` methods that can be called by other processes: ```inko -class async Cat { +type async Cat { let @name: String fn async give_food { @@ -403,23 +401,23 @@ class async Cat { ## Drop order -When dropping an instance of a class with fields, the fields are dropped in +When dropping an instance of a type with fields, the fields are dropped in reverse-definition order: ```inko -class Person { +type Person { let @name: String let @age: Int } ``` -When dropping an instance of this class, `@age` is dropped before `@name`. +When dropping an instance of this type, `@age` is dropped before `@name`. When dropping an `enum` with one or more cases that store data, the data stored in each case is dropped in reverse-definition order: ```inko -class enum Example { +type enum Example { case Foo(Int, String) case Bar } diff --git a/docs/source/getting-started/variables.md b/docs/source/getting-started/variables.md index 6ae90eacf..703a37563 100644 --- a/docs/source/getting-started/variables.md +++ b/docs/source/getting-started/variables.md @@ -79,12 +79,12 @@ the following is a compile-time error: let mut NUMBER = 42 ``` -Constants can only be defined outside of methods and classes, i.e. like so: +Constants can only be defined outside of methods and types, i.e. like so: ```inko let NUMBER = 42 -class Cat {} +type Cat {} ``` Constants are permanent values and as such are never dropped. diff --git a/docs/source/getting-started/visibility.md b/docs/source/getting-started/visibility.md index 5aa25628a..1a2f0d7ca 100644 --- a/docs/source/getting-started/visibility.md +++ b/docs/source/getting-started/visibility.md @@ -26,9 +26,9 @@ For types and constants, making them public is done as follows: | `let @name: Type` | `let pub @name: Type` |- -| Classes -| `class Example {}` -| `class pub Example {}` +| Types +| `type Example {}` +| `type pub Example {}` |- | Traits | `trait Example {}` @@ -71,13 +71,13 @@ The fields and regular (non-async) instance methods of a process are private to the type, meaning only the process itself can access them: ```inko -class async Cat { +type async Cat { let @name: String fn give_food {} } -class async Main { +type async Main { fn async main { let garfield = Cat(name: 'Garfield') diff --git a/docs/source/guides/cross-compilation.md b/docs/source/guides/cross-compilation.md index 1df7f0f46..920c2dc72 100644 --- a/docs/source/guides/cross-compilation.md +++ b/docs/source/guides/cross-compilation.md @@ -207,7 +207,7 @@ file `test.inko`: ```inko import std.stdio (Stdout) -class async Main { +type async Main { fn async main { Stdout.new.print('hello') } diff --git a/docs/source/guides/documentation.md b/docs/source/guides/documentation.md index daa278edb..00bc1e95a 100644 --- a/docs/source/guides/documentation.md +++ b/docs/source/guides/documentation.md @@ -8,7 +8,7 @@ Documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown), specifically using the [inko-markdown](https://github.com/yorickpeterse/inko-markdown) dialect. -Symbols (methods, classes, etc) are documented by placing one or more comments +Symbols (methods, types, etc) are documented by placing one or more comments before them, without empty lines between the comments or between the last comment and the start of the symbol: @@ -27,14 +27,14 @@ import std.string (StringBuffer) fn example {} ``` -If the module documentation is followed by a symbol (e.g. a class), ensure +If the module documentation is followed by a symbol (e.g. a type), ensure there's an empty line after the comment, otherwise it's treated as the documentation for the symbol: ```inko -# This documents the _module_ and not the class. +# This documents the _module_ and not the type. -class Example {} +type Example {} ``` The following can be documented: @@ -44,7 +44,7 @@ The following can be documented: - Module methods - Classes - Traits -- Methods defined on a class +- Methods defined on a type - Methods defined in an `impl` block - Methods defined in a trait diff --git a/docs/source/guides/operators.md b/docs/source/guides/operators.md index be592957f..7b16d8a54 100644 --- a/docs/source/guides/operators.md +++ b/docs/source/guides/operators.md @@ -16,7 +16,7 @@ implement this operator for a custom type: ```inko import std.ops (Add) -class Rational { +type Rational { let @numerator: Int let @denominator: Int } diff --git a/docs/source/references/compile-time-variables.md b/docs/source/references/compile-time-variables.md index 5636c553e..8ab32b07c 100644 --- a/docs/source/references/compile-time-variables.md +++ b/docs/source/references/compile-time-variables.md @@ -14,7 +14,7 @@ fn load_assets_from(path: String) { # ... } -class async Main { +type async Main { fn async main { load_assets_from(PATH) } @@ -44,7 +44,7 @@ fn load_assets_from(path: String) { # ... } -class async Main { +type async Main { fn async main { load_assets_from(PATH) } diff --git a/docs/source/references/core-types.md b/docs/source/references/core-types.md index 1faf0f6c4..cfe98c85f 100644 --- a/docs/source/references/core-types.md +++ b/docs/source/references/core-types.md @@ -29,13 +29,13 @@ values in the range of 0 up to (and including) 255. ## Float -The `Float` class is used for IEEE 754 double-precision floating point numbers. +The `Float` type is used for IEEE 754 double-precision floating point numbers. `Float` is a value type. ## Int -The `Int` class is used for integers. Integers are 64 bits signed integers. +The `Int` type is used for integers. Integers are 64 bits signed integers. `Int` is a value type. @@ -56,19 +56,19 @@ pattern matching bodies). ## Option -`Option` is an algebraic data type/enum class used to represent an optional -value. It has two constructor: `Some(T)` and `None`, with `None` signalling the -lack of a value. +`Option` is an algebraic data type/enum used to represent an optional value. It +has two constructor: `Some(T)` and `None`, with `None` signalling the lack of a +value. ## Result -`Result` is an algebraic data type/enum class used for error handling. It has -two constructors: `Ok(T)` and `Error(E)`. The `Ok` constructor signals the -success of an operation, while `Error` signals an error occurred. +`Result` is an algebraic data type/enum used for error handling. It has two +constructors: `Ok(T)` and `Error(E)`. The `Ok` constructor signals the success +of an operation, while `Error` signals an error occurred. ## String -The `String` class is used for strings. Strings are UTF-8 encoded immutable +The `String` type is used for strings. Strings are UTF-8 encoded immutable strings. Internally strings are represented such that they can be efficiently passed to C code, at the cost of one extra byte of overhead per string. diff --git a/docs/source/references/style.md b/docs/source/references/style.md index f7ff37f77..2459e5c99 100644 --- a/docs/source/references/style.md +++ b/docs/source/references/style.md @@ -65,7 +65,7 @@ always looks consistent. Types use PascalCase, such as `ByteArray` and `String`: ```inko -class AddressFormatter {} +type AddressFormatter {} ``` Methods, local variables, instance attributes, and arguments all use snake\_case @@ -179,7 +179,7 @@ describe the purpose of the item. For example: ```inko # A Person can be used for storing details of a single person, such as their # name and address. -class Person { +type Person { } ``` diff --git a/docs/source/references/syntax.md b/docs/source/references/syntax.md index 7b9781fb5..3580f1c42 100644 --- a/docs/source/references/syntax.md +++ b/docs/source/references/syntax.md @@ -13,10 +13,10 @@ Each Inko source file is a module and may contain the following: - Imports - Constants -- Classes +- Types - Methods - Trait implementations -- Classes that are reopened +- Types that are reopened - Comments Unlike languages such as Ruby and Python, it's not valid to include expressions @@ -27,7 +27,7 @@ import std.stdio (Stdout) Stdout.new.print('hello') -class async Main { +type async Main { fn async main {} } ``` @@ -122,7 +122,7 @@ fn move method_name {} # A public mutable instance method: fn pub mut method_name {} -# A public mutable async instance method (only available in async classes): +# A public mutable async instance method (only available in async types): fn pub async mut method_name {} # Method names may end with a ?, this is used for predicate methods: @@ -156,7 +156,7 @@ Type parameters are specified before regular arguments: fn method_name[A, B](arg1, A, arg2: B) {} ``` -Like classes, you can specify a list of required traits: +Like with types, you can specify a list of required traits: ```inko fn method_name[A: ToFoo + ToBar, B](arg1, A, arg2: B) {} @@ -174,7 +174,7 @@ fn method_name { Signatures for C functions are defined using the `fn extern` syntax. These functions can't define any generic type parameters, can only be defined at the -top-level of a module (i.e. not in a class), and can't specify the `mut` +top-level of a module (i.e. not in a type), and can't specify the `mut` keyword. For example: ```inko @@ -200,33 +200,33 @@ fn extern example -> Int { In this case, variadic arguments are _not_ supported. -## Classes +## Types -Classes are defined using the `class` keyword: +Types are defined using the `type` keyword: ```inko -class Person {} +type Person {} ``` -A class can define one or more fields using `let`: +A type can define one or more fields using `let`: ```inko -class Person { +type Person { let @name: String # `@name` is the field name, and `String` its type let @age: Int } ``` -To make a class public, use `class pub` like so: +To make a type public, use `type pub` like so: ```inko -class pub Person { +type pub Person { let @name: String # `@name` is the field name, and `String` its type let @age: Int } ``` -Instances of classes are created using the same syntax as method calls: +Instances of types are created using the same syntax as method calls: ```inko Person(name: 'Alice', age: 42) @@ -241,7 +241,7 @@ Person('Alice', 42) If no fields are given, the parentheses are required: ```inko -class Example {} +type Example {} Example() ``` @@ -251,49 +251,49 @@ Example() Enums are defined as follows: ```inko -class pub enum Result {} +type pub enum Result {} ``` -Enum classes allow defining of constructors using the `case` keyword: +Enum types allow defining of constructors using the `case` keyword: ```inko -class enum Result { +type enum Result { case Ok case Error } ``` -Enum classes can't define regular fields. +Enum types can't define regular fields. -### Stack allocated classes +### Stack allocated types -Stack allocated classes are defined using the `inline` and `copy` keywords: +Stack allocated types are defined using the `inline` and `copy` keywords: ```inko -class pub copy Example {} -class pub inline Example {} +type pub copy Example {} +type pub inline Example {} ``` These keywords can be combined with the `enum` keyword: ```inko -class copy enum Example { +type copy enum Example { case A case B } -class inline enum Example { +type inline enum Example { case A case B } ``` -### Generic classes +### Generic types -Generic classes are defined like so: +Generic types are defined like so: ```inko -class enum Result[T, E] { +type enum Result[T, E] { case Ok(T) case Error(E) } @@ -303,7 +303,7 @@ Here `T` and `E` are type parameters. Type parameters can also list one or more traits that must be implemented before a type can be assigned to the parameter: ```inko -class enum Result[T, E: ToString + ToFoo + ToBar] { +type enum Result[T, E: ToString + ToFoo + ToBar] { case Ok(T) case Error(E) } @@ -313,30 +313,30 @@ Type parameters can also specify the `mut` requirement, restricting the types to those that allow mutations: ```inko -class MyBox[T: mut] {} +type MyBox[T: mut] {} ``` ### Processes -Processes are defined as async classes like so: +Processes are defined as async types like so: ```inko -class async Counter { +type async Counter { } -class pub async Counter { +type pub async Counter { } ``` ### C structures -C structures are defined using `class extern`. When used, the class can't define +C structures are defined using `type extern`. When used, the type can't define any methods or use generic type parameters: ```inko -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } @@ -344,11 +344,11 @@ class extern Timespec { ### Methods -Classes can define static methods, instance methods, and async methods (in case -the class is an async class): +Types can define static methods, instance methods, and async methods (in case +the type is an async type): ```inko -class Person { +type Person { let @name: String # This is a static method, available as `Person.new`. @@ -363,27 +363,27 @@ class Person { } } -class async Counter { +type async Counter { fn async increment { # ... } } ``` -### Reopening classes +### Reopening types -A class can be reopened using the `impl` keyword like so: +A type can be reopened using the `impl` keyword like so: ```inko impl String {} ``` Within the body, only methods are allowed; fields can only be defined when the -class is defined for the first time. +type is defined for the first time. ## Traits -Traits are defined using the `trait` keyword, and like classes default to being +Traits are defined using the `trait` keyword, and like types default to being private. Traits are defined like so: @@ -427,7 +427,7 @@ Traits can also define type parameters: trait ToArray[T] {} ``` -And like classes and methods, these can define required traits: +And like types and methods, these can define required traits: ```inko trait ToArray[T: ToFoo + ToBar] {} @@ -448,7 +448,7 @@ Traits are implemented using the `impl` keyword: impl ToString for String {} ``` -The syntax is `impl TraitName for ClassName { body }`. Within the body only +The syntax is `impl TraitName for TypeName { body }`. Within the body only instance methods are allowed. ## Comments @@ -702,7 +702,7 @@ The following patterns are supported: - Bindings: `case v -> BODY`, `case mut v -> BODY` (allows reassigning of `v`) - Wildcards: `case _ -> BODY` - Enum constructors: `case Some(v) -> BODY` -- Classes: `case { @name = name } -> BODY` +- Types: `case { @name = name } -> BODY` - Tuples: `case (a, b, c) -> BODY` - OR patterns: `case 10 or 20 -> BODY` diff --git a/inko/src/command/test.rs b/inko/src/command/test.rs index 7298dce80..5c6ee4230 100644 --- a/inko/src/command/test.rs +++ b/inko/src/command/test.rs @@ -169,7 +169,7 @@ fn generate_main_test_module(tests: Vec) -> String { source.push_str(&line); } - source.push_str("\nclass async Main {\n"); + source.push_str("\ntype async Main {\n"); source.push_str(" fn async main {\n"); source.push_str(" let tests = Tests.new\n\n"); diff --git a/rt/src/macros/mod.rs b/rt/src/macros/mod.rs index 349d8f008..c2ce9275d 100644 --- a/rt/src/macros/mod.rs +++ b/rt/src/macros/mod.rs @@ -12,7 +12,7 @@ /// /// # Examples /// -/// init!(some_object.header.class => some_class); +/// init!(some_object.header.instance_of => type); macro_rules! init { ($field: expr => $value: expr) => { #[allow(unused_unsafe)] diff --git a/rt/src/mem.rs b/rt/src/mem.rs index a191507ca..f7d80be7c 100644 --- a/rt/src/mem.rs +++ b/rt/src/mem.rs @@ -32,8 +32,8 @@ pub(crate) unsafe fn header_of<'a, T>(ptr: *const T) -> &'a mut Header { /// we're dealing with. #[repr(C)] pub struct Header { - /// The class of the object. - pub class: ClassPointer, + /// The type of the object. + pub instance_of: TypePointer, /// The number of references to the object of this header. /// @@ -53,13 +53,13 @@ pub struct Header { } impl Header { - pub(crate) fn init(&mut self, class: ClassPointer) { - self.class = class; + pub(crate) fn init(&mut self, instance_of: TypePointer) { + self.instance_of = instance_of; self.references = 0; } - pub(crate) fn init_atomic(&mut self, class: ClassPointer) { - self.class = class; + pub(crate) fn init_atomic(&mut self, instance_of: TypePointer) { + self.instance_of = instance_of; self.references = 1; } } @@ -77,26 +77,26 @@ pub struct Method { pub code: extern "system" fn(), } -/// An Inko class. +/// An Inko type. #[repr(C)] -pub struct Class { - /// The name of the class. +pub struct Type { + /// The name of the type. pub(crate) name: RustString, - /// The size (in bytes) of instances of this class. + /// The size (in bytes) of instances of this type. /// /// This is only used for allocating and deallocating processes, as the /// deallocation happens asynchronously _after_ a process finishes running. - /// For regular classes the allocation and free logic is generated by the + /// For regular types the allocation and free logic is generated by the /// compiler. pub(crate) instance_size: u32, - /// The number of method slots this class has. + /// The number of method slots this type has. /// /// The actual number of methods may be less than this value. pub(crate) method_slots: u16, - /// The methods of this class, as pointers to native functions. + /// The methods of this type, as pointers to native functions. /// /// Methods are accessed frequently, and we want to do so with as little /// indirection and as cache-friendly as possible. For this reason we use a @@ -106,8 +106,8 @@ pub struct Class { pub methods: [Method; 0], } -impl Class { - pub(crate) unsafe fn drop(ptr: ClassPointer) { +impl Type { + pub(crate) unsafe fn drop(ptr: TypePointer) { let layout = Self::layout(ptr.method_slots); let raw_ptr = ptr.0; @@ -119,13 +119,13 @@ impl Class { name: RustString, methods: u16, size: u32, - ) -> ClassPointer { + ) -> TypePointer { let ptr = unsafe { let layout = Self::layout(methods); - // For classes we zero memory out, so unused method slots are set to + // For types we zero memory out, so unused method slots are set to // zeroed memory, instead of random garbage. - let ptr = alloc_zeroed(layout) as *mut Class; + let ptr = alloc_zeroed(layout) as *mut Type; if ptr.is_null() { handle_alloc_error(layout); @@ -139,33 +139,32 @@ impl Class { init!(obj.instance_size => size); init!(obj.method_slots => methods); - ClassPointer(ptr) + TypePointer(ptr) } - /// Returns a new class for a regular object. + /// Returns a new type for a regular object. pub(crate) fn object( name: RustString, size: u32, methods: u16, - ) -> ClassPointer { + ) -> TypePointer { Self::alloc(name, methods, size) } - /// Returns a new class for a process. + /// Returns a new type for a process. pub(crate) fn process( name: RustString, size: u32, methods: u16, - ) -> ClassPointer { + ) -> TypePointer { Self::alloc(name, methods, size) } - /// Returns the `Layout` for a class itself. + /// Returns the `Layout` for a type itself. unsafe fn layout(methods: u16) -> Layout { - let size = - size_of::() + (methods as usize * size_of::()); + let size = size_of::() + (methods as usize * size_of::()); - Layout::from_size_align_unchecked(size, align_of::()) + Layout::from_size_align_unchecked(size, align_of::()) } pub(crate) unsafe fn instance_layout(&self) -> Layout { @@ -176,16 +175,16 @@ impl Class { } } -/// A pointer to a class. +/// A pointer to a type. #[repr(transparent)] #[derive(Eq, PartialEq, Copy, Clone, Debug)] -pub struct ClassPointer(*mut Class); +pub struct TypePointer(*mut Type); -impl Deref for ClassPointer { - type Target = Class; +impl Deref for TypePointer { + type Target = Type; - fn deref(&self) -> &Class { - unsafe { &*(self.0 as *const Class) } + fn deref(&self) -> &Type { + unsafe { &*(self.0 as *const Type) } } } @@ -201,11 +200,11 @@ impl ByteArray { drop_in_place(ptr); } - pub(crate) fn alloc(class: ClassPointer, value: Vec) -> *mut Self { + pub(crate) fn alloc(instance_of: TypePointer, value: Vec) -> *mut Self { let ptr = allocate(Layout::new::()) as *mut Self; let obj = unsafe { &mut *ptr }; - obj.header.init(class); + obj.header.init(instance_of); init!(obj.value => value); ptr } @@ -240,14 +239,14 @@ impl String { } pub(crate) fn alloc( - class: ClassPointer, + instance_of: TypePointer, value: RustString, ) -> *const String { - Self::new(class, value.into_bytes()) + Self::new(instance_of, value.into_bytes()) } pub(crate) fn from_bytes( - class: ClassPointer, + instance_of: TypePointer, bytes: Vec, ) -> *const String { let string = match RustString::from_utf8(bytes) { @@ -257,10 +256,10 @@ impl String { } }; - String::new(class, string.into_bytes()) + String::new(instance_of, string.into_bytes()) } - fn new(class: ClassPointer, mut bytes: Vec) -> *const String { + fn new(instance_of: TypePointer, mut bytes: Vec) -> *const String { let len = bytes.len(); bytes.reserve_exact(1); @@ -277,7 +276,7 @@ impl String { let ptr = allocate(Layout::new::()) as *mut Self; let obj = unsafe { &mut *ptr }; - obj.header.init_atomic(class); + obj.header.init_atomic(instance_of); init!(obj.size => len as u64); init!(obj.bytes => buffer); ptr as _ @@ -317,25 +316,26 @@ mod tests { #[test] fn test_header_field_offsets() { - let header = Header { class: ClassPointer(0x7 as _), references: 42 }; + let header = + Header { instance_of: TypePointer(0x7 as _), references: 42 }; let base = addr_of!(header) as usize; - assert_eq!(addr_of!(header.class) as usize - base, 0); + assert_eq!(addr_of!(header.instance_of) as usize - base, 0); assert_eq!(addr_of!(header.references) as usize - base, 8); } #[test] - fn test_class_field_offsets() { - let class = Class::alloc("A".to_string(), 4, 8); - let base = class.0 as usize; + fn test_type_field_offsets() { + let typ = Type::alloc("A".to_string(), 4, 8); + let base = typ.0 as usize; - assert_eq!(addr_of!(class.name) as usize - base, 0); - assert_eq!(addr_of!(class.instance_size) as usize - base, 24); - assert_eq!(addr_of!(class.method_slots) as usize - base, 28); - assert_eq!(addr_of!(class.methods) as usize - base, 32); + assert_eq!(addr_of!(typ.name) as usize - base, 0); + assert_eq!(addr_of!(typ.instance_size) as usize - base, 24); + assert_eq!(addr_of!(typ.method_slots) as usize - base, 28); + assert_eq!(addr_of!(typ.methods) as usize - base, 32); unsafe { - Class::drop(class); + Type::drop(typ); } } @@ -355,7 +355,7 @@ mod tests { assert_eq!(size_of::(), 32); assert_eq!(size_of::(), 40); assert_eq!(size_of::(), 16); - assert_eq!(size_of::(), 32); + assert_eq!(size_of::(), 32); } #[test] @@ -364,56 +364,56 @@ mod tests { assert_eq!(align_of::(), ALIGNMENT); assert_eq!(align_of::(), ALIGNMENT); assert_eq!(align_of::(), ALIGNMENT); - assert_eq!(align_of::(), ALIGNMENT); + assert_eq!(align_of::(), ALIGNMENT); } #[test] - fn test_class_new() { - let class = Class::alloc("A".to_string(), 0, 24); + fn test_type_alloc() { + let typ = Type::alloc("A".to_string(), 0, 24); - assert_eq!(class.method_slots, 0); - assert_eq!(class.instance_size, 24); + assert_eq!(typ.method_slots, 0); + assert_eq!(typ.instance_size, 24); - unsafe { Class::drop(class) }; + unsafe { Type::drop(typ) }; } #[test] - fn test_class_new_object() { - let class = Class::object("A".to_string(), 24, 0); + fn test_type_object() { + let typ = Type::object("A".to_string(), 24, 0); - assert_eq!(class.method_slots, 0); - assert_eq!(class.instance_size, 24); + assert_eq!(typ.method_slots, 0); + assert_eq!(typ.instance_size, 24); - unsafe { Class::drop(class) }; + unsafe { Type::drop(typ) }; } #[test] - fn test_class_new_process() { - let class = Class::process("A".to_string(), 24, 0); + fn test_type_process() { + let typ = Type::process("A".to_string(), 24, 0); - assert_eq!(class.method_slots, 0); - assert_eq!(class.instance_size, 24); + assert_eq!(typ.method_slots, 0); + assert_eq!(typ.instance_size, 24); - unsafe { Class::drop(class) }; + unsafe { Type::drop(typ) }; } #[test] fn test_string_new() { - let class = Class::object("A".to_string(), 24, 0); - let string = String::new(class, vec![105, 110, 107, 111]); + let typ = Type::object("A".to_string(), 24, 0); + let string = String::new(typ, vec![105, 110, 107, 111]); unsafe { assert_eq!((*string).as_bytes(), &[105, 110, 107, 111]); assert_eq!(String::read(string), "inko"); - Class::drop(class); + Type::drop(typ); } } #[test] fn test_string_from_bytes() { - let class = Class::object("A".to_string(), 24, 0); + let typ = Type::object("A".to_string(), 24, 0); let string = String::from_bytes( - class, + typ, vec![ 72, 101, 108, 108, 111, 32, 240, 144, 128, 87, 111, 114, 108, 100, @@ -422,7 +422,7 @@ mod tests { unsafe { assert_eq!(String::read(string), "Hello �World"); - Class::drop(class); + Type::drop(typ); } } } diff --git a/rt/src/network_poller.rs b/rt/src/network_poller.rs index 68c61aa7e..769032180 100644 --- a/rt/src/network_poller.rs +++ b/rt/src/network_poller.rs @@ -75,13 +75,13 @@ impl Worker { #[cfg(test)] mod tests { use super::*; - use crate::test::{empty_process_class, new_process}; + use crate::test::{empty_process_type, new_process}; use std::net::UdpSocket; #[test] fn test_add() { - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let output = UdpSocket::bind("0.0.0.0:0").unwrap(); let poller = NetworkPoller::new(); @@ -92,8 +92,8 @@ mod tests { fn test_modify() { let output = UdpSocket::bind("0.0.0.0:0").unwrap(); let poller = NetworkPoller::new(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); poller.add(*process, &output, Interest::Read); poller.modify(*process, &output, Interest::Write); @@ -103,8 +103,8 @@ mod tests { fn test_delete() { let output = UdpSocket::bind("0.0.0.0:0").unwrap(); let poller = NetworkPoller::new(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); poller.add(*process, &output, Interest::Write); poller.delete(&output); @@ -114,8 +114,8 @@ mod tests { fn test_poll() { let output = UdpSocket::bind("0.0.0.0:0").unwrap(); let poller = NetworkPoller::new(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let mut events = sys::Events::with_capacity(1); poller.add(*process, &output, Interest::Write); @@ -130,9 +130,9 @@ mod tests { let sock1 = UdpSocket::bind("0.0.0.0:0").unwrap(); let sock2 = UdpSocket::bind("0.0.0.0:0").unwrap(); let poller = NetworkPoller::new(); - let class = empty_process_class("A"); - let proc1 = new_process(*class); - let proc2 = new_process(*class); + let typ = empty_process_type("A"); + let proc1 = new_process(*typ); + let proc2 = new_process(*typ); let mut events = sys::Events::with_capacity(1); poller.add(*proc1, &sock1, Interest::Write); diff --git a/rt/src/process.rs b/rt/src/process.rs index f22658a51..fcd5a3080 100644 --- a/rt/src/process.rs +++ b/rt/src/process.rs @@ -1,5 +1,5 @@ use crate::arc_without_weak::ArcWithoutWeak; -use crate::mem::{allocate, header_of, ClassPointer, Header}; +use crate::mem::{allocate, header_of, Header, TypePointer}; use crate::scheduler::process::Thread; use crate::scheduler::timeouts::Timeout; use crate::stack::Stack; @@ -405,7 +405,7 @@ pub struct Process { /// The fields of this process. /// /// The length of this flexible array is derived from the number of fields - /// defined in this process' class. + /// defined in this process' type. pub fields: [*mut u8; 0], } @@ -413,15 +413,19 @@ impl Process { pub(crate) fn drop_and_deallocate(ptr: ProcessPointer) { unsafe { let raw = ptr.as_ptr(); - let layout = header_of(raw).class.instance_layout(); + let layout = header_of(raw).instance_of.instance_layout(); drop_in_place(raw); dealloc(raw as *mut u8, layout); } } - pub(crate) fn alloc(class: ClassPointer, stack: Stack) -> ProcessPointer { - let ptr = allocate(unsafe { class.instance_layout() }) as *mut Self; + pub(crate) fn alloc( + instance_of: TypePointer, + stack: Stack, + ) -> ProcessPointer { + let ptr = + allocate(unsafe { instance_of.instance_layout() }) as *mut Self; let obj = unsafe { &mut *ptr }; let mut state = ProcessState::new(); @@ -445,7 +449,7 @@ impl Process { ); } - obj.header.init_atomic(class); + obj.header.init_atomic(instance_of); init!(obj.run_lock => UnsafeCell::new(Mutex::new(()))); init!(obj.stack_pointer => stack.stack_pointer()); init!(obj.stack => ManuallyDrop::new(stack)); @@ -458,11 +462,11 @@ impl Process { /// /// This process always runs on the main thread. pub(crate) fn main( - class: ClassPointer, + instance_of: TypePointer, method: NativeAsyncMethod, stack: Stack, ) -> ProcessPointer { - let mut process = Self::alloc(class, stack); + let mut process = Self::alloc(instance_of, stack); let message = Message { method, data: null_mut() }; process.set_main(); @@ -715,7 +719,7 @@ impl DerefMut for ProcessPointer { #[cfg(test)] mod tests { use super::*; - use crate::test::{empty_process_class, setup, OwnedProcess}; + use crate::test::{empty_process_type, setup, OwnedProcess}; use rustix::param::page_size; use std::mem::size_of; use std::time::Duration; @@ -751,9 +755,9 @@ mod tests { #[test] fn test_field_offsets() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let proc = OwnedProcess::new(Process::alloc(*proc_class, stack)); + let proc = OwnedProcess::new(Process::alloc(*proc_type, stack)); assert_eq!(offset_of!(proc, header), 0); assert_eq!( @@ -967,30 +971,30 @@ mod tests { #[test] fn test_process_new() { - let class = empty_process_class("A"); + let typ = empty_process_type("A"); let process = OwnedProcess::new(Process::alloc( - *class, + *typ, Stack::new(32, page_size()), )); - assert_eq!(process.header.class, class.0); + assert_eq!(process.header.instance_of, typ.0); } #[test] fn test_process_main() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); let process = - OwnedProcess::new(Process::main(*proc_class, method, stack)); + OwnedProcess::new(Process::main(*proc_type, method, stack)); assert!(process.is_main()); } #[test] fn test_process_set_main() { - let class = empty_process_class("A"); + let typ = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let mut process = OwnedProcess::new(Process::alloc(*class, stack)); + let mut process = OwnedProcess::new(Process::alloc(*typ, stack)); assert!(!process.is_main()); @@ -1001,9 +1005,9 @@ mod tests { #[test] fn test_process_state_suspend() { let state = setup(); - let class = empty_process_class("A"); + let typ = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let process = OwnedProcess::new(Process::alloc(*class, stack)); + let process = OwnedProcess::new(Process::alloc(*typ, stack)); let timeout = Timeout::duration(&state, Duration::from_secs(0)); process.state().suspend(timeout); @@ -1015,9 +1019,9 @@ mod tests { #[test] fn test_process_timeout_expired() { let state = setup(); - let class = empty_process_class("A"); + let typ = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let process = OwnedProcess::new(Process::alloc(*class, stack)); + let process = OwnedProcess::new(Process::alloc(*typ, stack)); let timeout = Timeout::duration(&state, Duration::from_secs(0)); assert!(!process.timeout_expired()); @@ -1046,9 +1050,9 @@ mod tests { #[test] fn test_process_send_message() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let mut process = OwnedProcess::new(Process::alloc(*proc_class, stack)); + let mut process = OwnedProcess::new(Process::alloc(*proc_type, stack)); let msg = Message { method, data: null_mut() }; assert_eq!(process.send_message(msg), RescheduleRights::Acquired); @@ -1057,18 +1061,18 @@ mod tests { #[test] fn test_process_next_task_without_messages() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let mut process = OwnedProcess::new(Process::alloc(*proc_class, stack)); + let mut process = OwnedProcess::new(Process::alloc(*proc_type, stack)); assert!(matches!(process.next_task(), Task::Wait)); } #[test] fn test_process_next_task_with_new_message() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let mut process = OwnedProcess::new(Process::alloc(*proc_class, stack)); + let mut process = OwnedProcess::new(Process::alloc(*proc_type, stack)); let msg = Message { method, data: null_mut() }; process.send_message(msg); @@ -1077,9 +1081,9 @@ mod tests { #[test] fn test_process_next_task_with_existing_message() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let mut process = OwnedProcess::new(Process::alloc(*proc_class, stack)); + let mut process = OwnedProcess::new(Process::alloc(*proc_type, stack)); let msg1 = Message { method, data: null_mut() }; let msg2 = Message { method, data: null_mut() }; @@ -1092,9 +1096,9 @@ mod tests { #[test] fn test_process_take_stack() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let mut process = OwnedProcess::new(Process::alloc(*proc_class, stack)); + let mut process = OwnedProcess::new(Process::alloc(*proc_type, stack)); assert!(process.take_stack().is_some()); assert!(process.stack_pointer.is_null()); @@ -1102,9 +1106,9 @@ mod tests { #[test] fn test_process_finish_message() { - let proc_class = empty_process_class("A"); + let proc_type = empty_process_type("A"); let stack = Stack::new(32, page_size()); - let mut process = OwnedProcess::new(Process::alloc(*proc_class, stack)); + let mut process = OwnedProcess::new(Process::alloc(*proc_type, stack)); assert!(!process.finish_message()); assert!(process.state().status.is_waiting_for_message()); diff --git a/rt/src/runtime.rs b/rt/src/runtime.rs index 246b63a7f..34c84a98d 100644 --- a/rt/src/runtime.rs +++ b/rt/src/runtime.rs @@ -1,5 +1,4 @@ mod byte_array; -mod class; mod env; mod float; mod general; @@ -11,9 +10,10 @@ mod socket; mod string; mod time; mod tls; +mod types; use crate::config::Config; -use crate::mem::ClassPointer; +use crate::mem::TypePointer; use crate::network_poller::Worker as NetworkPollerWorker; use crate::process::{NativeAsyncMethod, Process}; use crate::scheduler::reset_affinity; @@ -88,10 +88,10 @@ pub unsafe extern "system" fn inko_runtime_drop(runtime: *mut Runtime) { #[no_mangle] pub unsafe extern "system" fn inko_runtime_start( runtime: *mut Runtime, - class: ClassPointer, + main_type: TypePointer, method: NativeAsyncMethod, ) { - (*runtime).start(class, method); + (*runtime).start(main_type, method); } #[no_mangle] @@ -120,7 +120,7 @@ pub struct Runtime { impl Runtime { /// Returns a new `Runtime` instance. /// - /// This method sets up the runtime and allocates the core classes, but + /// This method sets up the runtime and allocates the core types, but /// doesn't start any threads. fn new(counts: &MethodCounts, args: Vec) -> Self { Self { state: State::new(Config::from_env(), counts, args) } @@ -132,7 +132,7 @@ impl Runtime { /// This method blocks the current thread until the program terminates, /// though this thread itself doesn't run any processes (= it just /// waits/blocks until completion). - fn start(&self, main_class: ClassPointer, main_method: NativeAsyncMethod) { + fn start(&self, main_type: TypePointer, main_method: NativeAsyncMethod) { let state = self.state.clone(); thread::Builder::new() @@ -165,7 +165,7 @@ impl Runtime { let stack_size = self.state.config.stack_size as usize; let stack = Stack::new(stack_size, page_size()); - let main_proc = Process::main(main_class, main_method, stack); + let main_proc = Process::main(main_type, main_method, stack); self.state.scheduler.run(&self.state, main_proc); } diff --git a/rt/src/runtime/byte_array.rs b/rt/src/runtime/byte_array.rs index 3459d989b..a6aa7fbd4 100644 --- a/rt/src/runtime/byte_array.rs +++ b/rt/src/runtime/byte_array.rs @@ -7,7 +7,7 @@ use std::slice; pub unsafe extern "system" fn inko_byte_array_new( state: *const State, ) -> *mut ByteArray { - ByteArray::alloc((*state).byte_array_class, Vec::new()) + ByteArray::alloc((*state).byte_array_type, Vec::new()) } #[no_mangle] @@ -16,7 +16,7 @@ pub unsafe extern "system" fn inko_byte_array_with_capacity( size: i64, ) -> *mut ByteArray { ByteArray::alloc( - (*state).byte_array_class, + (*state).byte_array_type, Vec::with_capacity(size as usize), ) } @@ -98,7 +98,7 @@ pub unsafe extern "system" fn inko_byte_array_clone( state: *const State, bytes: *const ByteArray, ) -> *mut ByteArray { - ByteArray::alloc((*state).byte_array_class, (*bytes).value.clone()) + ByteArray::alloc((*state).byte_array_type, (*bytes).value.clone()) } #[no_mangle] @@ -111,7 +111,7 @@ pub unsafe extern "system" fn inko_byte_array_to_string( state: *const State, bytes: *const ByteArray, ) -> *const InkoString { - InkoString::from_bytes((*state).string_class, (*bytes).value.clone()) + InkoString::from_bytes((*state).string_type, (*bytes).value.clone()) } #[no_mangle] @@ -119,7 +119,7 @@ pub unsafe extern "system" fn inko_byte_array_drain_to_string( state: *const State, bytes: *mut ByteArray, ) -> *const InkoString { - InkoString::from_bytes((*state).string_class, (*bytes).take_bytes()) + InkoString::from_bytes((*state).string_type, (*bytes).take_bytes()) } #[no_mangle] @@ -133,7 +133,7 @@ pub unsafe extern "system" fn inko_byte_array_slice( let end = min((start + length) as usize, bytes.value.len()); ByteArray::alloc( - (*state).byte_array_class, + (*state).byte_array_type, bytes.value[start as usize..end].to_vec(), ) } @@ -187,5 +187,5 @@ pub unsafe extern "system" fn inko_byte_array_from_pointer( ) -> *mut ByteArray { let bytes = slice::from_raw_parts(pointer, length as usize).to_vec(); - ByteArray::alloc((*state).byte_array_class, bytes) + ByteArray::alloc((*state).byte_array_type, bytes) } diff --git a/rt/src/runtime/env.rs b/rt/src/runtime/env.rs index 1f8bbb43f..3fed1f2a8 100644 --- a/rt/src/runtime/env.rs +++ b/rt/src/runtime/env.rs @@ -16,7 +16,7 @@ pub unsafe extern "system" fn inko_env_get( .environment .get(name) .cloned() - .map(|v| InkoResult::ok(InkoString::alloc(state.string_class, v) as _)) + .map(|v| InkoResult::ok(InkoString::alloc(state.string_type, v) as _)) .unwrap_or_else(InkoResult::none) } @@ -32,7 +32,7 @@ pub unsafe extern "system" fn inko_env_get_key( // of returning a result value. let val = state.environment.key(index as _).unwrap().clone(); - InkoString::alloc(state.string_class, val) + InkoString::alloc(state.string_type, val) } #[no_mangle] @@ -46,7 +46,7 @@ pub unsafe extern "system" fn inko_env_temp_directory( ) -> *const InkoString { let path = canonalize(env::temp_dir().to_string_lossy().into_owned()); - InkoString::alloc((*state).string_class, path) + InkoString::alloc((*state).string_type, path) } #[no_mangle] @@ -56,7 +56,7 @@ pub unsafe extern "system" fn inko_env_get_working_directory( env::current_dir() .map(|path| canonalize(path.to_string_lossy().into_owned())) .map(|path| { - InkoResult::ok(InkoString::alloc((*state).string_class, path) as _) + InkoResult::ok(InkoString::alloc((*state).string_type, path) as _) }) .unwrap_or_else(InkoResult::io_error) } @@ -87,7 +87,7 @@ pub unsafe extern "system" fn inko_env_argument( let state = &(*state); InkoString::alloc( - state.string_class, + state.string_type, state.arguments.get_unchecked(index as usize).clone(), ) } @@ -99,7 +99,7 @@ pub unsafe extern "system" fn inko_env_executable( env::current_exe() .map(|path| path.to_string_lossy().into_owned()) .map(|path| { - InkoResult::ok(InkoString::alloc((*state).string_class, path) as _) + InkoResult::ok(InkoString::alloc((*state).string_type, path) as _) }) .unwrap_or_else(InkoResult::io_error) } diff --git a/rt/src/runtime/float.rs b/rt/src/runtime/float.rs index cc80cbb99..07bf7c74a 100644 --- a/rt/src/runtime/float.rs +++ b/rt/src/runtime/float.rs @@ -16,5 +16,5 @@ pub unsafe extern "system" fn inko_float_to_string( format!("{:?}", value) }; - InkoString::alloc((*state).string_class, string) + InkoString::alloc((*state).string_type, string) } diff --git a/rt/src/runtime/general.rs b/rt/src/runtime/general.rs index 5c46531e8..6b98b9020 100644 --- a/rt/src/runtime/general.rs +++ b/rt/src/runtime/general.rs @@ -15,7 +15,7 @@ pub unsafe extern "system" fn inko_reference_count_error( process, &format!( "can't drop a value of type '{}' as it still has {} reference(s)", - &header.class.name, header.references + &header.instance_of.name, header.references ), ); } diff --git a/rt/src/runtime/process.rs b/rt/src/runtime/process.rs index c93fb20b0..fc3e5be34 100644 --- a/rt/src/runtime/process.rs +++ b/rt/src/runtime/process.rs @@ -1,5 +1,5 @@ use crate::context; -use crate::mem::{ClassPointer, String as InkoString}; +use crate::mem::{String as InkoString, TypePointer}; use crate::process::{ Message, NativeAsyncMethod, Process, ProcessPointer, RescheduleRights, StackFrame, @@ -45,7 +45,7 @@ pub(crate) fn panic(process: ProcessPointer, message: &str) -> ! { let _ = write!( buffer, "\nProcess '{}' ({:#x}) panicked: {}", - process.header.class.name, + process.header.instance_of.name, process.identifier(), message ); @@ -65,11 +65,11 @@ pub unsafe extern "system" fn inko_process_panic( #[no_mangle] pub unsafe extern "system" fn inko_process_new( mut process: ProcessPointer, - class: ClassPointer, + instance_of: TypePointer, ) -> ProcessPointer { let stack = process.thread().stacks.alloc(); - Process::alloc(class, stack) + Process::alloc(instance_of, stack) } #[no_mangle] @@ -161,7 +161,7 @@ pub unsafe extern "system" fn inko_process_stack_frame_name( ) -> *const InkoString { let val = &(*trace).get_unchecked(index as usize).name; - InkoString::alloc((*state).string_class, val.clone()) + InkoString::alloc((*state).string_type, val.clone()) } #[no_mangle] @@ -172,7 +172,7 @@ pub unsafe extern "system" fn inko_process_stack_frame_path( ) -> *const InkoString { let val = &(*trace).get_unchecked(index as usize).path; - InkoString::alloc((*state).string_class, val.clone()) + InkoString::alloc((*state).string_type, val.clone()) } #[no_mangle] diff --git a/rt/src/runtime/random.rs b/rt/src/runtime/random.rs index 8bc30340e..0bc7114b8 100644 --- a/rt/src/runtime/random.rs +++ b/rt/src/runtime/random.rs @@ -54,7 +54,7 @@ pub unsafe extern "system" fn inko_random_bytes( panic(process, &err.to_string()); } - ByteArray::alloc((*state).byte_array_class, bytes) + ByteArray::alloc((*state).byte_array_type, bytes) } #[no_mangle] diff --git a/rt/src/runtime/string.rs b/rt/src/runtime/string.rs index 38e3e7a7f..6eb8fa24b 100644 --- a/rt/src/runtime/string.rs +++ b/rt/src/runtime/string.rs @@ -17,7 +17,7 @@ pub unsafe extern "system" fn inko_string_new( let bytes = slice::from_raw_parts(bytes, length).to_vec(); let string = String::from_utf8_unchecked(bytes); - InkoString::alloc((*state).string_class, string) + InkoString::alloc((*state).string_type, string) } #[no_mangle] @@ -33,7 +33,7 @@ pub unsafe extern "system" fn inko_string_concat( buffer.push_str(InkoString::read(val)); } - InkoString::alloc((*state).string_class, buffer) + InkoString::alloc((*state).string_type, buffer) } #[no_mangle] @@ -47,7 +47,7 @@ pub unsafe extern "system" fn inko_string_to_lower( string: *const InkoString, ) -> *const InkoString { InkoString::alloc( - (*state).string_class, + (*state).string_type, InkoString::read(string).to_lowercase(), ) } @@ -58,7 +58,7 @@ pub unsafe extern "system" fn inko_string_to_upper( string: *const InkoString, ) -> *const InkoString { InkoString::alloc( - (*state).string_class, + (*state).string_type, InkoString::read(string).to_uppercase(), ) } @@ -70,7 +70,7 @@ pub unsafe extern "system" fn inko_string_to_byte_array( ) -> *mut ByteArray { let bytes = InkoString::read(string).as_bytes().to_vec(); - ByteArray::alloc((*state).byte_array_class, bytes) + ByteArray::alloc((*state).byte_array_type, bytes) } #[no_mangle] @@ -132,8 +132,7 @@ pub unsafe extern "system" fn inko_string_chars_next( iter.next() .map(|v| { - let string = - InkoString::alloc((*state).string_class, v.to_string()); + let string = InkoString::alloc((*state).string_type, v.to_string()); InkoResult::ok(string as _) }) @@ -169,5 +168,5 @@ pub unsafe extern "system" fn inko_string_from_pointer( ) -> *const InkoString { let val = CStr::from_ptr(ptr).to_string_lossy().into_owned(); - InkoString::alloc((*state).string_class, val) + InkoString::alloc((*state).string_type, val) } diff --git a/rt/src/runtime/class.rs b/rt/src/runtime/types.rs similarity index 50% rename from rt/src/runtime/class.rs rename to rt/src/runtime/types.rs index 26427b1e6..a43e2c828 100644 --- a/rt/src/runtime/class.rs +++ b/rt/src/runtime/types.rs @@ -1,31 +1,26 @@ -use crate::mem::{Class, ClassPointer}; +use crate::mem::{Type, TypePointer}; use std::{ffi::CStr, os::raw::c_char}; #[no_mangle] -pub unsafe extern "system" fn inko_class_object( +pub unsafe extern "system" fn inko_type_object( name: *const c_char, size: u32, methods: u16, -) -> ClassPointer { +) -> TypePointer { let name = String::from_utf8_lossy(CStr::from_ptr(name).to_bytes()).into_owned(); - Class::object(name, size, methods) + Type::object(name, size, methods) } #[no_mangle] -pub unsafe extern "system" fn inko_class_process( +pub unsafe extern "system" fn inko_type_process( name: *const c_char, size: u32, methods: u16, -) -> ClassPointer { +) -> TypePointer { let name = String::from_utf8_lossy(CStr::from_ptr(name).to_bytes()).into_owned(); - Class::process(name, size, methods) -} - -#[no_mangle] -pub unsafe extern "system" fn inko_class_drop(class: ClassPointer) { - Class::drop(class); + Type::process(name, size, methods) } diff --git a/rt/src/scheduler/process.rs b/rt/src/scheduler/process.rs index 2ae7a01b1..e78a8b326 100644 --- a/rt/src/scheduler/process.rs +++ b/rt/src/scheduler/process.rs @@ -1062,7 +1062,7 @@ impl Scheduler { mod tests { use super::*; use crate::test::{ - empty_process_class, new_process, new_process_with_message, setup, + empty_process_type, new_process, new_process_with_message, setup, }; use std::thread::sleep; @@ -1076,8 +1076,8 @@ mod tests { #[test] fn test_thread_schedule() { - let class = empty_process_class("A"); - let process = new_process(*class).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process(*typ).take_and_forget(); let scheduler = Scheduler::new(1, 1, 32); let mut thread = Thread::new(1, 0, scheduler.pool.clone()); @@ -1089,8 +1089,8 @@ mod tests { #[test] fn test_thread_schedule_with_overflow() { - let class = empty_process_class("A"); - let process = new_process(*class).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process(*typ).take_and_forget(); let scheduler = Scheduler::new(1, 1, 32); let mut thread = Thread::new(1, 0, scheduler.pool.clone()); @@ -1113,9 +1113,8 @@ mod tests { #[test] fn test_thread_run_with_local_job() { - let class = empty_process_class("A"); - let process = - new_process_with_message(*class, method).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process_with_message(*typ, method).take_and_forget(); let state = setup(); let mut thread = Thread::new(1, 0, state.scheduler.pool.clone()); @@ -1127,9 +1126,8 @@ mod tests { #[test] fn test_thread_run_with_stolen_job() { - let class = empty_process_class("A"); - let process = - new_process_with_message(*class, method).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process_with_message(*typ, method).take_and_forget(); let state = setup(); let mut thread0 = Thread::new(1, 0, state.scheduler.pool.clone()); let mut thread1 = Thread::new(2, 0, state.scheduler.pool.clone()); @@ -1143,9 +1141,8 @@ mod tests { #[test] fn test_thread_run_with_global_job() { - let class = empty_process_class("A"); - let process = - new_process_with_message(*class, method).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process_with_message(*typ, method).take_and_forget(); let state = setup(); let mut thread = Thread::new(1, 0, state.scheduler.pool.clone()); @@ -1158,9 +1155,8 @@ mod tests { #[test] fn test_thread_steal_from_global_with_full_local_queue() { - let class = empty_process_class("A"); - let process = - new_process_with_message(*class, method).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process_with_message(*typ, method).take_and_forget(); let state = setup(); let mut thread = Thread::new(1, 0, state.scheduler.pool.clone()); @@ -1192,9 +1188,8 @@ mod tests { #[test] fn test_thread_run_as_backup() { - let class = empty_process_class("A"); - let process = - new_process_with_message(*class, method).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process_with_message(*typ, method).take_and_forget(); let state = setup(); let mut thread = Thread::new(1, 0, state.scheduler.pool.clone()); @@ -1215,8 +1210,8 @@ mod tests { #[test] fn test_thread_start_blocking() { - let class = empty_process_class("A"); - let proc = new_process(*class).take_and_forget(); + let typ = empty_process_type("A"); + let proc = new_process(*typ).take_and_forget(); let state = setup(); let pool = &state.scheduler.pool; let mut thread = Thread::new(1, 0, pool.clone()); @@ -1238,8 +1233,8 @@ mod tests { let state = setup(); let pool = &state.scheduler.pool; let mut thread = Thread::new(1, 0, pool.clone()); - let class = empty_process_class("A"); - let process = new_process(*class).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process(*typ).take_and_forget(); thread.start_blocking(); thread.stop_blocking(process); @@ -1263,8 +1258,8 @@ mod tests { let state = setup(); let pool = &state.scheduler.pool; let mut thread = Thread::new(1, 0, pool.clone()); - let class = empty_process_class("A"); - let process = new_process(*class).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process(*typ).take_and_forget(); thread.start_blocking(); thread.start_blocking(); @@ -1290,8 +1285,8 @@ mod tests { #[test] fn test_thread_start_blocking_without_stop_blocking() { - let class = empty_process_class("A"); - let proc = new_process_with_message(*class, method).take_and_forget(); + let typ = empty_process_type("A"); + let proc = new_process_with_message(*typ, method).take_and_forget(); let state = setup(); let pool = &state.scheduler.pool; let mut thread = Thread::new(1, 0, pool.clone()); @@ -1315,8 +1310,8 @@ mod tests { #[test] fn test_pool_schedule_with_sleeping_thread() { - let class = empty_process_class("A"); - let process = new_process(*class).take_and_forget(); + let typ = empty_process_type("A"); + let process = new_process(*typ).take_and_forget(); let scheduler = Scheduler::new(1, 1, 32); scheduler.pool.sleeping.fetch_add(1, Ordering::Release); diff --git a/rt/src/scheduler/timeout_worker.rs b/rt/src/scheduler/timeout_worker.rs index 401cd0394..ed29b4eec 100644 --- a/rt/src/scheduler/timeout_worker.rs +++ b/rt/src/scheduler/timeout_worker.rs @@ -189,7 +189,7 @@ mod tests { use super::*; use crate::process::Process; use crate::stack::Stack; - use crate::test::{empty_process_class, new_process, setup}; + use crate::test::{empty_process_type, new_process, setup}; use rustix::param::page_size; #[test] @@ -204,8 +204,8 @@ mod tests { fn test_suspend() { let state = setup(); let worker = TimeoutWorker::new(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); worker.suspend( *process, @@ -227,8 +227,8 @@ mod tests { #[test] fn test_run_with_fragmented_heap() { let state = setup(); - let class = empty_process_class("A"); - let process = Process::alloc(*class, Stack::new(1024, page_size())); + let typ = empty_process_type("A"); + let process = Process::alloc(*typ, Stack::new(1024, page_size())); let worker = TimeoutWorker::new(); for time in &[10_u64, 5_u64] { @@ -253,8 +253,8 @@ mod tests { #[test] fn test_run_with_message() { let state = setup(); - let class = empty_process_class("A"); - let process = Process::alloc(*class, Stack::new(1024, page_size())); + let typ = empty_process_type("A"); + let process = Process::alloc(*typ, Stack::new(1024, page_size())); let worker = TimeoutWorker::new(); let timeout = Timeout::duration(&state, Duration::from_secs(10)); @@ -268,8 +268,8 @@ mod tests { #[test] fn test_run_with_reschedule() { let state = setup(); - let class = empty_process_class("A"); - let process = Process::alloc(*class, Stack::new(1024, page_size())); + let typ = empty_process_type("A"); + let process = Process::alloc(*typ, Stack::new(1024, page_size())); let worker = TimeoutWorker::new(); let timeout = Timeout::duration(&state, Duration::from_secs(0)); @@ -283,8 +283,8 @@ mod tests { #[test] fn test_defragment_heap_without_fragmentation() { let state = setup(); - let class = empty_process_class("A"); - let process = Process::alloc(*class, Stack::new(1024, page_size())); + let typ = empty_process_type("A"); + let process = Process::alloc(*typ, Stack::new(1024, page_size())); let worker = TimeoutWorker::new(); let timeout = Timeout::duration(&state, Duration::from_secs(1)); @@ -301,8 +301,8 @@ mod tests { #[test] fn test_defragment_heap_with_fragmentation() { let state = setup(); - let class = empty_process_class("A"); - let process = Process::alloc(*class, Stack::new(1024, page_size())); + let typ = empty_process_type("A"); + let process = Process::alloc(*typ, Stack::new(1024, page_size())); let worker = TimeoutWorker::new(); for time in &[1_u64, 1_u64] { diff --git a/rt/src/scheduler/timeouts.rs b/rt/src/scheduler/timeouts.rs index 6e6bc5ab7..af7d3b7ef 100644 --- a/rt/src/scheduler/timeouts.rs +++ b/rt/src/scheduler/timeouts.rs @@ -186,7 +186,7 @@ impl Drop for Timeouts { mod tests { use super::*; use crate::stack::Stack; - use crate::test::{empty_process_class, new_process, setup}; + use crate::test::{empty_process_type, new_process, setup}; use rustix::param::page_size; use std::mem::size_of; use std::thread::sleep; @@ -221,14 +221,14 @@ mod tests { mod timeout_entry { use super::*; - use crate::test::{empty_process_class, new_process}; + use crate::test::{empty_process_type, new_process}; use std::cmp; #[test] fn test_partial_cmp() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let entry1 = TimeoutEntry::new( *process, Timeout::duration(&state, Duration::from_secs(1)), @@ -250,8 +250,8 @@ mod tests { #[test] fn test_cmp() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let entry1 = TimeoutEntry::new( *process, Timeout::duration(&state, Duration::from_secs(1)), @@ -269,8 +269,8 @@ mod tests { #[test] fn test_eq() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let entry1 = TimeoutEntry::new( *process, Timeout::duration(&state, Duration::from_secs(1)), @@ -292,8 +292,8 @@ mod tests { #[test] fn test_insert() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let mut timeouts = Timeouts::new(); let timeout = Timeout::duration(&state, Duration::from_secs(10)); @@ -305,8 +305,8 @@ mod tests { #[test] fn test_len() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let mut timeouts = Timeouts::new(); let timeout = Timeout::duration(&state, Duration::from_secs(10)); @@ -318,8 +318,8 @@ mod tests { #[test] fn test_remove_invalid_entries_with_valid_entries() { let state = setup(); - let class = empty_process_class("A"); - let process = Process::alloc(*class, Stack::new(1024, page_size())); + let typ = empty_process_type("A"); + let process = Process::alloc(*typ, Stack::new(1024, page_size())); let mut timeouts = Timeouts::new(); let timeout = Timeout::duration(&state, Duration::from_secs(10)); @@ -333,8 +333,8 @@ mod tests { #[test] fn test_remove_invalid_entries_with_invalid_entries() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let mut timeouts = Timeouts::new(); let timeout = Timeout::duration(&state, Duration::from_secs(10)); @@ -347,8 +347,8 @@ mod tests { #[test] fn test_processes_to_reschedule_with_invalid_entries() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let mut timeouts = Timeouts::new(); let timeout = Timeout::duration(&state, Duration::from_secs(10)); @@ -364,8 +364,8 @@ mod tests { #[test] fn test_processes_to_reschedule_with_remaining_time() { let state = setup(); - let class = empty_process_class("A"); - let process = Process::alloc(*class, Stack::new(1024, page_size())); + let typ = empty_process_type("A"); + let process = Process::alloc(*typ, Stack::new(1024, page_size())); let mut timeouts = Timeouts::new(); let timeout = Timeout::duration(&state, Duration::from_secs(10)); @@ -383,8 +383,8 @@ mod tests { #[test] fn test_processes_to_reschedule_with_entries_to_reschedule() { let state = setup(); - let class = empty_process_class("A"); - let process = new_process(*class); + let typ = empty_process_type("A"); + let process = new_process(*typ); let mut timeouts = Timeouts::new(); let timeout = Timeout::duration(&state, Duration::from_secs(0)); diff --git a/rt/src/state.rs b/rt/src/state.rs index b8a8baf5b..75c4368ec 100644 --- a/rt/src/state.rs +++ b/rt/src/state.rs @@ -1,6 +1,6 @@ use crate::arc_without_weak::ArcWithoutWeak; use crate::config::Config; -use crate::mem::{ByteArray, Class, ClassPointer, String as InkoString}; +use crate::mem::{ByteArray, String as InkoString, Type, TypePointer}; use crate::network_poller::NetworkPoller; use crate::scheduler::process::Scheduler; use crate::scheduler::signal::Signals; @@ -14,11 +14,11 @@ use std::sync::atomic::AtomicU32; use std::thread::available_parallelism; use std::time; -/// Allocates a new class, returning a tuple containing the owned pointer and a +/// Allocates a new type, returning a tuple containing the owned pointer and a /// permanent reference pointer. -macro_rules! class { +macro_rules! new_type { ($name: expr, $methods: expr, $size_source: ident) => {{ - Class::alloc( + Type::alloc( $name.to_string(), $methods, size_of::<$size_source>() as u32, @@ -29,15 +29,15 @@ macro_rules! class { /// A reference counted State. pub(crate) type RcState = ArcWithoutWeak; -/// The number of methods used for the various built-in classes. +/// The number of methods used for the various built-in types. /// /// These counts are used to determine how much memory is needed for allocating -/// the various built-in classes. +/// the various built-in types. #[derive(Default, Debug)] #[repr(C)] pub struct MethodCounts { - pub(crate) string_class: u16, - pub(crate) byte_array_class: u16, + pub(crate) string_type: u16, + pub(crate) byte_array_type: u16, } pub(crate) struct Env { @@ -77,8 +77,8 @@ impl Env { /// The state of the Inko runtime. #[repr(C)] pub struct State { - pub string_class: ClassPointer, - pub byte_array_class: ClassPointer, + pub string_type: TypePointer, + pub byte_array_type: TypePointer, /// The first randomly generated key to use for hashers. pub hash_key0: i64, @@ -142,9 +142,9 @@ impl State { counts: &MethodCounts, arguments: Vec, ) -> RcState { - let string_class = class!("String", counts.string_class, InkoString); - let byte_array_class = - class!("ByteArray", counts.byte_array_class, ByteArray); + let string_type = new_type!("String", counts.string_type, InkoString); + let byte_array_type = + new_type!("ByteArray", counts.byte_array_type, ByteArray); let mut rng = thread_rng(); let hash_key0 = rng.gen(); @@ -171,8 +171,8 @@ impl State { timeout_worker: TimeoutWorker::new(), arguments, network_pollers, - string_class, - byte_array_class, + string_type, + byte_array_type, signals: Signals::new(), }; @@ -187,8 +187,8 @@ impl State { impl Drop for State { fn drop(&mut self) { unsafe { - Class::drop(self.string_class); - Class::drop(self.byte_array_class); + Type::drop(self.string_type); + Type::drop(self.byte_array_type); } } } diff --git a/rt/src/test.rs b/rt/src/test.rs index 219aa3974..c3000c5e8 100644 --- a/rt/src/test.rs +++ b/rt/src/test.rs @@ -1,6 +1,6 @@ //! Helper functions for writing unit tests. use crate::config::Config; -use crate::mem::{Class, ClassPointer}; +use crate::mem::{Type, TypePointer}; use crate::process::{Message, NativeAsyncMethod, Process, ProcessPointer}; use crate::stack::Stack; use crate::state::{MethodCounts, RcState, State}; @@ -50,28 +50,28 @@ impl Drop for OwnedProcess { } } -/// A class that is dropped when this pointer is dropped. +/// A type that is dropped when this pointer is dropped. #[repr(transparent)] -pub(crate) struct OwnedClass(pub(crate) ClassPointer); +pub(crate) struct OwnedType(pub(crate) TypePointer); -impl OwnedClass { - pub(crate) fn new(ptr: ClassPointer) -> Self { +impl OwnedType { + pub(crate) fn new(ptr: TypePointer) -> Self { Self(ptr) } } -impl Deref for OwnedClass { - type Target = ClassPointer; +impl Deref for OwnedType { + type Target = TypePointer; fn deref(&self) -> &Self::Target { &self.0 } } -impl Drop for OwnedClass { +impl Drop for OwnedType { fn drop(&mut self) { unsafe { - Class::drop(self.0); + Type::drop(self.0); } } } @@ -87,16 +87,19 @@ pub(crate) fn setup() -> RcState { State::new(config, &MethodCounts::default(), Vec::new()) } -pub(crate) fn new_process(class: ClassPointer) -> OwnedProcess { - OwnedProcess::new(Process::alloc(class, Stack::new(1024, page_size()))) +pub(crate) fn new_process(instance_of: TypePointer) -> OwnedProcess { + OwnedProcess::new(Process::alloc( + instance_of, + Stack::new(1024, page_size()), + )) } pub(crate) fn new_process_with_message( - class: ClassPointer, + instance_of: TypePointer, method: NativeAsyncMethod, ) -> OwnedProcess { let stack = Stack::new(1024, page_size()); - let mut proc = Process::alloc(class, stack); + let mut proc = Process::alloc(instance_of, stack); // We use a custom message that takes the process as an argument. This way // the tests have access to the current process, without needing to fiddle @@ -107,8 +110,8 @@ pub(crate) fn new_process_with_message( OwnedProcess::new(proc) } -pub(crate) fn empty_process_class(name: &str) -> OwnedClass { - OwnedClass::new(Class::process( +pub(crate) fn empty_process_type(name: &str) -> OwnedType { + OwnedType::new(Type::process( name.to_string(), size_of::() as _, 0, diff --git a/std/fixtures/compile_time_variables.inko b/std/fixtures/compile_time_variables.inko index b8abf4d4d..c8e92f35b 100644 --- a/std/fixtures/compile_time_variables.inko +++ b/std/fixtures/compile_time_variables.inko @@ -5,7 +5,7 @@ let pub INT = 42 let pub BOOL = true let PRIVATE = 42 -class async Main { +type async Main { fn async main { let out = Stdout.new diff --git a/std/fixtures/debug_info/example1.inko b/std/fixtures/debug_info/example1.inko index 185e7a7d5..06ae0f2d5 100644 --- a/std/fixtures/debug_info/example1.inko +++ b/std/fixtures/debug_info/example1.inko @@ -1,4 +1,4 @@ -class async Main { +type async Main { fn async main { foo } diff --git a/std/fixtures/debug_info/example2.inko b/std/fixtures/debug_info/example2.inko index bea023b27..037b312fa 100644 --- a/std/fixtures/debug_info/example2.inko +++ b/std/fixtures/debug_info/example2.inko @@ -1,4 +1,4 @@ -class async Main { +type async Main { fn async main { foo } diff --git a/std/fixtures/debug_info/example3.inko b/std/fixtures/debug_info/example3.inko index 9294c8db9..8737272cd 100644 --- a/std/fixtures/debug_info/example3.inko +++ b/std/fixtures/debug_info/example3.inko @@ -1,4 +1,4 @@ -class async Main { +type async Main { fn async main { foo } diff --git a/std/fixtures/debug_info/example4.inko b/std/fixtures/debug_info/example4.inko index 41066688f..aa3f9517a 100644 --- a/std/fixtures/debug_info/example4.inko +++ b/std/fixtures/debug_info/example4.inko @@ -1,4 +1,4 @@ -class async Main { +type async Main { fn async main { foo } diff --git a/std/fixtures/diagnostics/assign_async_field_recover_owned.inko b/std/fixtures/diagnostics/assign_async_field_recover_owned.inko index c9dfc82ab..4673c182b 100644 --- a/std/fixtures/diagnostics/assign_async_field_recover_owned.inko +++ b/std/fixtures/diagnostics/assign_async_field_recover_owned.inko @@ -1,4 +1,4 @@ -class async Thing[A, B] { +type async Thing[A, B] { let @a: A let @b: B diff --git a/std/fixtures/diagnostics/assign_field_after_move_with_self.inko b/std/fixtures/diagnostics/assign_field_after_move_with_self.inko index a6a0bdf56..ae3210403 100644 --- a/std/fixtures/diagnostics/assign_field_after_move_with_self.inko +++ b/std/fixtures/diagnostics/assign_field_after_move_with_self.inko @@ -1,4 +1,4 @@ -class Thing { +type Thing { let @a: Array[Int] let @b: Array[Int] diff --git a/std/fixtures/diagnostics/casting_value_types.inko b/std/fixtures/diagnostics/casting_value_types.inko index f55727bfe..dcba092ff 100644 --- a/std/fixtures/diagnostics/casting_value_types.inko +++ b/std/fixtures/diagnostics/casting_value_types.inko @@ -1,6 +1,6 @@ import std.string (ToString) -class copy A {} +type copy A {} impl ToString for A { fn pub to_string -> String { @@ -8,7 +8,7 @@ impl ToString for A { } } -class B {} +type B {} impl ToString for B { fn pub to_string -> String { diff --git a/std/fixtures/diagnostics/class_instance_with_receiver.inko b/std/fixtures/diagnostics/class_instance_with_receiver.inko deleted file mode 100644 index e0b9f5ff7..000000000 --- a/std/fixtures/diagnostics/class_instance_with_receiver.inko +++ /dev/null @@ -1,13 +0,0 @@ -import foo - -fn example1 { - foo.Foo(number: 42) - foo.Bar(number: 42) - foo.Foo - foo.Empty() - foo.Empty -} - -# class_instance_with_receiver.inko:5:3 error(invalid-symbol): the method 'Bar' isn't defined for type 'foo' -# class_instance_with_receiver.inko:6:3 error(invalid-symbol): the symbol 'Foo' is defined but isn't a value -# class_instance_with_receiver.inko:8:3 error(invalid-symbol): the symbol 'Empty' is defined but isn't a value diff --git a/std/fixtures/diagnostics/class_instance_with_receiver/foo.inko b/std/fixtures/diagnostics/class_instance_with_receiver/foo.inko deleted file mode 100644 index b94c2b044..000000000 --- a/std/fixtures/diagnostics/class_instance_with_receiver/foo.inko +++ /dev/null @@ -1,5 +0,0 @@ -class pub Foo { - let pub @number: Int -} - -class pub Empty {} diff --git a/std/fixtures/diagnostics/closure_capture_self.inko b/std/fixtures/diagnostics/closure_capture_self.inko index 6fca1f72a..18c7bce70 100644 --- a/std/fixtures/diagnostics/closure_capture_self.inko +++ b/std/fixtures/diagnostics/closure_capture_self.inko @@ -1,4 +1,4 @@ -class A { +type A { fn foo { recover fn { bar } recover fn { self.bar } diff --git a/std/fixtures/diagnostics/closure_capturing_struct.inko b/std/fixtures/diagnostics/closure_capturing_struct.inko index c5e2c78bc..9c6b425bb 100644 --- a/std/fixtures/diagnostics/closure_capturing_struct.inko +++ b/std/fixtures/diagnostics/closure_capturing_struct.inko @@ -1,4 +1,4 @@ -class extern Foo { +type extern Foo { let @value: Int32 } diff --git a/std/fixtures/diagnostics/comparing_generics_with_ownership.inko b/std/fixtures/diagnostics/comparing_generics_with_ownership.inko index 30729817d..3fa2184fc 100644 --- a/std/fixtures/diagnostics/comparing_generics_with_ownership.inko +++ b/std/fixtures/diagnostics/comparing_generics_with_ownership.inko @@ -1,16 +1,16 @@ -class A[T] { +type A[T] { let @value: ref T } -class B[T] { +type B[T] { let @value: T } -class C[T] { +type C[T] { let @value: Pointer[T] } -class List[T] { +type List[T] { let @buffer: Pointer[T] } diff --git a/std/fixtures/diagnostics/copy_enum_definitions.inko b/std/fixtures/diagnostics/copy_enum_definitions.inko index 69eeae8d4..c64ca8a29 100644 --- a/std/fixtures/diagnostics/copy_enum_definitions.inko +++ b/std/fixtures/diagnostics/copy_enum_definitions.inko @@ -1,12 +1,12 @@ -class copy enum Valid { +type copy enum Valid { case A(Int, Float) } -class copy enum Invalid1 { +type copy enum Invalid1 { case A(Int, String) } -class copy enum Invalid2 { +type copy enum Invalid2 { case A(Int, Array[Int]) } diff --git a/std/fixtures/diagnostics/copy_type_definitions.inko b/std/fixtures/diagnostics/copy_type_definitions.inko index 0011a4287..9f69f4804 100644 --- a/std/fixtures/diagnostics/copy_type_definitions.inko +++ b/std/fixtures/diagnostics/copy_type_definitions.inko @@ -1,14 +1,14 @@ -class copy A {} +type copy A {} -class pub copy B {} +type pub copy B {} -class copy enum C {} +type copy enum C {} -class pub copy enum D {} +type pub copy enum D {} -class copy async E {} +type copy async E {} -class copy extern F {} +type copy extern F {} -# copy_type_definitions.inko:9:18 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords -# copy_type_definitions.inko:11:19 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords +# copy_type_definitions.inko:9:17 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords +# copy_type_definitions.inko:11:18 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords diff --git a/std/fixtures/diagnostics/copy_type_instances.inko b/std/fixtures/diagnostics/copy_type_instances.inko index daa25be19..f1293ef1d 100644 --- a/std/fixtures/diagnostics/copy_type_instances.inko +++ b/std/fixtures/diagnostics/copy_type_instances.inko @@ -1,8 +1,8 @@ -class copy A[T] { +type copy A[T] { let @value: T } -class extern B { +type extern B { let @value: Int } diff --git a/std/fixtures/diagnostics/copy_type_parameters.inko b/std/fixtures/diagnostics/copy_type_parameters.inko index 77041dd0e..9d4ce3ac4 100644 --- a/std/fixtures/diagnostics/copy_type_parameters.inko +++ b/std/fixtures/diagnostics/copy_type_parameters.inko @@ -1,4 +1,4 @@ -class Example[T: copy] { +type Example[T: copy] { let @value: T } diff --git a/std/fixtures/diagnostics/copy_types_as_mutable_arguments.inko b/std/fixtures/diagnostics/copy_types_as_mutable_arguments.inko index 04eca2da9..2c991b707 100644 --- a/std/fixtures/diagnostics/copy_types_as_mutable_arguments.inko +++ b/std/fixtures/diagnostics/copy_types_as_mutable_arguments.inko @@ -1,4 +1,4 @@ -class copy A { +type copy A { let @value: Int } diff --git a/std/fixtures/diagnostics/copy_types_with_fields.inko b/std/fixtures/diagnostics/copy_types_with_fields.inko index 3b4c2665d..fa40e22ca 100644 --- a/std/fixtures/diagnostics/copy_types_with_fields.inko +++ b/std/fixtures/diagnostics/copy_types_with_fields.inko @@ -1,21 +1,21 @@ -class copy A { +type copy A { let @value: Int } -class copy B { +type copy B { let @value1: A let @value2: C } -class extern C { +type extern C { let @value: Int } -class copy D[T] { +type copy D[T] { let @value: T } -class copy E { +type copy E { let @valid: D[Int] let @invalid: D[String] } diff --git a/std/fixtures/diagnostics/copy_types_with_methods.inko b/std/fixtures/diagnostics/copy_types_with_methods.inko index 1e2b08b3e..6695b103a 100644 --- a/std/fixtures/diagnostics/copy_types_with_methods.inko +++ b/std/fixtures/diagnostics/copy_types_with_methods.inko @@ -1,4 +1,4 @@ -class copy A { +type copy A { fn a { self.test } diff --git a/std/fixtures/diagnostics/default_method_with_bounds.inko b/std/fixtures/diagnostics/default_method_with_bounds.inko index 52c3124af..1b378b8ed 100644 --- a/std/fixtures/diagnostics/default_method_with_bounds.inko +++ b/std/fixtures/diagnostics/default_method_with_bounds.inko @@ -6,7 +6,7 @@ trait A { trait B {} -class Box[T] { +type Box[T] { let @value: T } @@ -14,7 +14,7 @@ impl A for Box if T: B { fn foo {} } -class Thing {} +type Thing {} impl B for Thing {} diff --git a/std/fixtures/diagnostics/duplicate_class.inko b/std/fixtures/diagnostics/duplicate_class.inko deleted file mode 100644 index 393bcaea8..000000000 --- a/std/fixtures/diagnostics/duplicate_class.inko +++ /dev/null @@ -1,5 +0,0 @@ -class A {} - -class A {} - -# duplicate_class.inko:3:7 error(duplicate-symbol): the symbol 'A' is already defined diff --git a/std/fixtures/diagnostics/duplicate_type.inko b/std/fixtures/diagnostics/duplicate_type.inko new file mode 100644 index 000000000..fcd6b00e2 --- /dev/null +++ b/std/fixtures/diagnostics/duplicate_type.inko @@ -0,0 +1,5 @@ +type A {} + +type A {} + +# duplicate_type.inko:3:6 error(duplicate-symbol): the symbol 'A' is already defined diff --git a/std/fixtures/diagnostics/field_in_recover.inko b/std/fixtures/diagnostics/field_in_recover.inko index ed2c6732f..4bb34a80e 100644 --- a/std/fixtures/diagnostics/field_in_recover.inko +++ b/std/fixtures/diagnostics/field_in_recover.inko @@ -1,4 +1,4 @@ -class List { +type List { let @values: Array[Int] let @sendable: uni Array[Int] diff --git a/std/fixtures/diagnostics/fn_move_captures_uni.inko b/std/fixtures/diagnostics/fn_move_captures_uni.inko index 5e789658c..368cc3fe4 100644 --- a/std/fixtures/diagnostics/fn_move_captures_uni.inko +++ b/std/fixtures/diagnostics/fn_move_captures_uni.inko @@ -1,4 +1,4 @@ -class A {} +type A {} fn example1 { let a = recover [A()] diff --git a/std/fixtures/diagnostics/immutable_types_implementing_mutating_methods.inko b/std/fixtures/diagnostics/immutable_types_implementing_mutating_methods.inko index 7ed000a87..d63419e74 100644 --- a/std/fixtures/diagnostics/immutable_types_implementing_mutating_methods.inko +++ b/std/fixtures/diagnostics/immutable_types_implementing_mutating_methods.inko @@ -8,7 +8,7 @@ trait Mutate { fn mut quix {} } -class copy A {} +type copy A {} impl Mutate for A { fn mut foo {} diff --git a/std/fixtures/diagnostics/immutable_types_with_mutating_methods.inko b/std/fixtures/diagnostics/immutable_types_with_mutating_methods.inko index 77a79d683..ad4fa0442 100644 --- a/std/fixtures/diagnostics/immutable_types_with_mutating_methods.inko +++ b/std/fixtures/diagnostics/immutable_types_with_mutating_methods.inko @@ -1,4 +1,4 @@ -class copy A { +type copy A { fn mut invalid {} } diff --git a/std/fixtures/diagnostics/inline_enum_definitions.inko b/std/fixtures/diagnostics/inline_enum_definitions.inko index ac3dd37d9..461d8ecec 100644 --- a/std/fixtures/diagnostics/inline_enum_definitions.inko +++ b/std/fixtures/diagnostics/inline_enum_definitions.inko @@ -1,11 +1,11 @@ -class inline enum Valid { +type inline enum Valid { case A(Int, Float) } -class inline enum Invalid1 { +type inline enum Invalid1 { case A(Int, String) } -class inline enum Invalid2 { +type inline enum Invalid2 { case A(Int, Array[Int]) } diff --git a/std/fixtures/diagnostics/inline_methods.inko b/std/fixtures/diagnostics/inline_methods.inko index 32de37c9f..d58ae2429 100644 --- a/std/fixtures/diagnostics/inline_methods.inko +++ b/std/fixtures/diagnostics/inline_methods.inko @@ -1,7 +1,7 @@ fn inline module_method1 {} fn pub inline module_method2 {} -class A { +type A { fn inline instance_method1 {} fn inline mut instance_method2 {} fn inline move instance_method3 {} @@ -35,7 +35,7 @@ trait B { fn pub inline move valid6 {} } -class async C { +type async C { fn inline async invalid1 {} fn inline async mut invalid2 {} diff --git a/std/fixtures/diagnostics/inline_type_definitions.inko b/std/fixtures/diagnostics/inline_type_definitions.inko index e8b25875a..957c76ffa 100644 --- a/std/fixtures/diagnostics/inline_type_definitions.inko +++ b/std/fixtures/diagnostics/inline_type_definitions.inko @@ -1,14 +1,14 @@ -class inline A {} +type inline A {} -class pub inline B {} +type pub inline B {} -class inline enum C {} +type inline enum C {} -class pub inline enum D {} +type pub inline enum D {} -class inline async E {} +type inline async E {} -class inline extern F {} +type inline extern F {} -# inline_type_definitions.inko:9:20 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords -# inline_type_definitions.inko:11:21 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords +# inline_type_definitions.inko:9:19 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords +# inline_type_definitions.inko:11:20 error(invalid-type): only regular and 'enum' types support the 'inline' and 'copy' keywords diff --git a/std/fixtures/diagnostics/inline_type_instances.inko b/std/fixtures/diagnostics/inline_type_instances.inko index 1c0754e78..e72d9ff2a 100644 --- a/std/fixtures/diagnostics/inline_type_instances.inko +++ b/std/fixtures/diagnostics/inline_type_instances.inko @@ -1,8 +1,8 @@ -class inline A[T] { +type inline A[T] { let @value: T } -class extern B { +type extern B { let @value: Int } diff --git a/std/fixtures/diagnostics/inline_type_parameters.inko b/std/fixtures/diagnostics/inline_type_parameters.inko index 08e403a6d..c65058edf 100644 --- a/std/fixtures/diagnostics/inline_type_parameters.inko +++ b/std/fixtures/diagnostics/inline_type_parameters.inko @@ -1,4 +1,4 @@ -class Example[T: copy] { +type Example[T: copy] { let @value: T } diff --git a/std/fixtures/diagnostics/inline_types_as_mutable_arguments.inko b/std/fixtures/diagnostics/inline_types_as_mutable_arguments.inko index 62584b71b..06717195f 100644 --- a/std/fixtures/diagnostics/inline_types_as_mutable_arguments.inko +++ b/std/fixtures/diagnostics/inline_types_as_mutable_arguments.inko @@ -1,4 +1,4 @@ -class inline A { +type inline A { let @value: Int } diff --git a/std/fixtures/diagnostics/inline_types_with_fields.inko b/std/fixtures/diagnostics/inline_types_with_fields.inko index 09880854a..9afaac286 100644 --- a/std/fixtures/diagnostics/inline_types_with_fields.inko +++ b/std/fixtures/diagnostics/inline_types_with_fields.inko @@ -1,20 +1,20 @@ -class inline A { +type inline A { let @value: Int } -class inline B { +type inline B { let @value1: A let @value2: C } -class extern C { +type extern C { let @value: Int } -class inline D[T] { +type inline D[T] { let @value: T } -class inline E { +type inline E { let @valid: D[Int] } diff --git a/std/fixtures/diagnostics/inline_types_with_methods.inko b/std/fixtures/diagnostics/inline_types_with_methods.inko index 6fcf7de99..95b0b5a3a 100644 --- a/std/fixtures/diagnostics/inline_types_with_methods.inko +++ b/std/fixtures/diagnostics/inline_types_with_methods.inko @@ -1,4 +1,4 @@ -class inline A { +type inline A { fn a { self.test } diff --git a/std/fixtures/diagnostics/mutating_copy_types.inko b/std/fixtures/diagnostics/mutating_copy_types.inko index 9863e8cff..160d5228f 100644 --- a/std/fixtures/diagnostics/mutating_copy_types.inko +++ b/std/fixtures/diagnostics/mutating_copy_types.inko @@ -1,4 +1,4 @@ -class copy A { +type copy A { let @value: Int } diff --git a/std/fixtures/diagnostics/never_in_constructor.inko b/std/fixtures/diagnostics/never_in_constructor.inko index e4ae1d3a3..f47a0833f 100644 --- a/std/fixtures/diagnostics/never_in_constructor.inko +++ b/std/fixtures/diagnostics/never_in_constructor.inko @@ -1,4 +1,4 @@ -class enum Example { +type enum Example { case A(Never) } diff --git a/std/fixtures/diagnostics/never_in_field.inko b/std/fixtures/diagnostics/never_in_field.inko index 133c17176..4272be343 100644 --- a/std/fixtures/diagnostics/never_in_field.inko +++ b/std/fixtures/diagnostics/never_in_field.inko @@ -1,4 +1,4 @@ -class Example { +type Example { let @value: Never } diff --git a/std/fixtures/diagnostics/owned_with_pointer.inko b/std/fixtures/diagnostics/owned_with_pointer.inko index b460af432..b357c592b 100644 --- a/std/fixtures/diagnostics/owned_with_pointer.inko +++ b/std/fixtures/diagnostics/owned_with_pointer.inko @@ -1,4 +1,4 @@ -class Thing {} +type Thing {} fn pointer_owned(value: Pointer[Thing]) {} diff --git a/std/fixtures/diagnostics/pattern_matching.inko b/std/fixtures/diagnostics/pattern_matching.inko index 29ebb683c..76fc9f226 100644 --- a/std/fixtures/diagnostics/pattern_matching.inko +++ b/std/fixtures/diagnostics/pattern_matching.inko @@ -1,4 +1,4 @@ -class enum Letter { +type enum Letter { case A case B } diff --git a/std/fixtures/diagnostics/process_fields.inko b/std/fixtures/diagnostics/process_fields.inko index 1d0272971..c286c2e84 100644 --- a/std/fixtures/diagnostics/process_fields.inko +++ b/std/fixtures/diagnostics/process_fields.inko @@ -1,4 +1,4 @@ -class async Foo { +type async Foo { let @value: Int fn async mut update(value: Int) { diff --git a/std/fixtures/diagnostics/recursive_classes.inko b/std/fixtures/diagnostics/recursive_classes.inko deleted file mode 100644 index 58067df94..000000000 --- a/std/fixtures/diagnostics/recursive_classes.inko +++ /dev/null @@ -1,71 +0,0 @@ -class A { - let @a: A -} - -class copy B { - let @a: Int - let @b: Float - let @c: Pointer[Int64] -} - -class copy C { - let @a: D -} - -class copy D { - let @a: Int -} - -class copy E { - let @a: E -} - -class copy F { - let @a: G[F] -} - -class copy G[T] { - let @a: T -} - -class copy H { - let @a: I[Int] -} - -class copy I[T] { - let @a: T - let @b: H -} - -class extern J { - let @a: Int64 -} - -class extern K { - let @a: K -} - -class extern L { - let @a: M -} - -class extern M { - let @a: L -} - -class extern N { - let @a: Pointer[N] -} - -class inline O { - let @a: O -} - -# recursive_classes.inko:19:1 error(invalid-type): types allocated on the stack can't be recursive -# recursive_classes.inko:23:1 error(invalid-type): types allocated on the stack can't be recursive -# recursive_classes.inko:31:1 error(invalid-type): types allocated on the stack can't be recursive -# recursive_classes.inko:35:1 error(invalid-type): types allocated on the stack can't be recursive -# recursive_classes.inko:44:1 error(invalid-type): types allocated on the stack can't be recursive -# recursive_classes.inko:48:1 error(invalid-type): types allocated on the stack can't be recursive -# recursive_classes.inko:52:1 error(invalid-type): types allocated on the stack can't be recursive -# recursive_classes.inko:60:1 error(invalid-type): types allocated on the stack can't be recursive diff --git a/std/fixtures/diagnostics/recursive_type.inko b/std/fixtures/diagnostics/recursive_type.inko new file mode 100644 index 000000000..647463b95 --- /dev/null +++ b/std/fixtures/diagnostics/recursive_type.inko @@ -0,0 +1,71 @@ +type A { + let @a: A +} + +type copy B { + let @a: Int + let @b: Float + let @c: Pointer[Int64] +} + +type copy C { + let @a: D +} + +type copy D { + let @a: Int +} + +type copy E { + let @a: E +} + +type copy F { + let @a: G[F] +} + +type copy G[T] { + let @a: T +} + +type copy H { + let @a: I[Int] +} + +type copy I[T] { + let @a: T + let @b: H +} + +type extern J { + let @a: Int64 +} + +type extern K { + let @a: K +} + +type extern L { + let @a: M +} + +type extern M { + let @a: L +} + +type extern N { + let @a: Pointer[N] +} + +type inline O { + let @a: O +} + +# recursive_type.inko:19:1 error(invalid-type): types allocated on the stack can't be recursive +# recursive_type.inko:23:1 error(invalid-type): types allocated on the stack can't be recursive +# recursive_type.inko:31:1 error(invalid-type): types allocated on the stack can't be recursive +# recursive_type.inko:35:1 error(invalid-type): types allocated on the stack can't be recursive +# recursive_type.inko:44:1 error(invalid-type): types allocated on the stack can't be recursive +# recursive_type.inko:48:1 error(invalid-type): types allocated on the stack can't be recursive +# recursive_type.inko:52:1 error(invalid-type): types allocated on the stack can't be recursive +# recursive_type.inko:60:1 error(invalid-type): types allocated on the stack can't be recursive diff --git a/std/fixtures/diagnostics/ref_value_type_with_uni_ref.inko b/std/fixtures/diagnostics/ref_value_type_with_uni_ref.inko index 980ccb216..a6031f660 100644 --- a/std/fixtures/diagnostics/ref_value_type_with_uni_ref.inko +++ b/std/fixtures/diagnostics/ref_value_type_with_uni_ref.inko @@ -2,12 +2,12 @@ trait Eq[T] { fn eq(other: T) } -class enum Opt[T] { +type enum Opt[T] { case Some(T) case None } -class Thing {} +type Thing {} impl Eq[ref Thing] for Thing { fn eq(other: ref Thing) {} diff --git a/std/fixtures/diagnostics/return_when_any_is_expected.inko b/std/fixtures/diagnostics/return_when_any_is_expected.inko index af29e5ec2..5628f7bd9 100644 --- a/std/fixtures/diagnostics/return_when_any_is_expected.inko +++ b/std/fixtures/diagnostics/return_when_any_is_expected.inko @@ -1,4 +1,4 @@ -class Box[V] { +type Box[V] { let @value: V fn foo -> V { diff --git a/std/fixtures/diagnostics/swap_fields.inko b/std/fixtures/diagnostics/swap_fields.inko index 541bd7ecf..ded2c1c60 100644 --- a/std/fixtures/diagnostics/swap_fields.inko +++ b/std/fixtures/diagnostics/swap_fields.inko @@ -1,4 +1,4 @@ -class Person { +type Person { let @name: String let @numbers: Array[Int] diff --git a/std/fixtures/diagnostics/class_extern_without_fields.inko b/std/fixtures/diagnostics/type_extern_without_fields.inko similarity index 65% rename from std/fixtures/diagnostics/class_extern_without_fields.inko rename to std/fixtures/diagnostics/type_extern_without_fields.inko index e04763ed8..886b5425f 100644 --- a/std/fixtures/diagnostics/class_extern_without_fields.inko +++ b/std/fixtures/diagnostics/type_extern_without_fields.inko @@ -1,4 +1,4 @@ -class extern Foo { +type extern Foo { let @a: Int32 let @b: Int32 let @c: Int32 @@ -16,4 +16,4 @@ fn example3 { let foo = Foo(a: 0 as Int32, b: 1 as Int32) } -# class_extern_without_fields.inko:16:13 error(missing-field): the field 'c' must be assigned a value +# type_extern_without_fields.inko:16:13 error(missing-field): the field 'c' must be assigned a value diff --git a/std/fixtures/diagnostics/type_instance_with_receiver.inko b/std/fixtures/diagnostics/type_instance_with_receiver.inko new file mode 100644 index 000000000..106116ed5 --- /dev/null +++ b/std/fixtures/diagnostics/type_instance_with_receiver.inko @@ -0,0 +1,13 @@ +import foo + +fn example1 { + foo.Foo(number: 42) + foo.Bar(number: 42) + foo.Foo + foo.Empty() + foo.Empty +} + +# type_instance_with_receiver.inko:5:3 error(invalid-symbol): the method 'Bar' isn't defined for type 'foo' +# type_instance_with_receiver.inko:6:3 error(invalid-symbol): the symbol 'Foo' is defined but isn't a value +# type_instance_with_receiver.inko:8:3 error(invalid-symbol): the symbol 'Empty' is defined but isn't a value diff --git a/std/fixtures/diagnostics/type_instance_with_receiver/foo.inko b/std/fixtures/diagnostics/type_instance_with_receiver/foo.inko new file mode 100644 index 000000000..e0440abc6 --- /dev/null +++ b/std/fixtures/diagnostics/type_instance_with_receiver/foo.inko @@ -0,0 +1,5 @@ +type pub Foo { + let pub @number: Int +} + +type pub Empty {} diff --git a/std/fixtures/diagnostics/type_parameter_bounds.inko b/std/fixtures/diagnostics/type_parameter_bounds.inko index 88dfa9e4a..f32a333aa 100644 --- a/std/fixtures/diagnostics/type_parameter_bounds.inko +++ b/std/fixtures/diagnostics/type_parameter_bounds.inko @@ -1,4 +1,4 @@ -class A[T] {} +type A[T] {} impl A if T: mut {} diff --git a/std/fixtures/diagnostics/type_parameter_requirements.inko b/std/fixtures/diagnostics/type_parameter_requirements.inko index 9f279c823..99c393ded 100644 --- a/std/fixtures/diagnostics/type_parameter_requirements.inko +++ b/std/fixtures/diagnostics/type_parameter_requirements.inko @@ -1,10 +1,10 @@ -class A[T: mut] {} +type A[T: mut] {} -class B[T: copy] {} +type B[T: copy] {} -class C[T: copy + mut] {} +type C[T: copy + mut] {} -class D[T: copy + mut] {} +type D[T: copy + mut] {} -# type_parameter_requirements.inko:5:19 error(invalid-type): type parameters can't be both 'mut' and 'copy', as 'copy' types are immutable -# type_parameter_requirements.inko:7:19 error(invalid-type): type parameters can't be both 'mut' and 'copy', as 'copy' types are immutable +# type_parameter_requirements.inko:5:18 error(invalid-type): type parameters can't be both 'mut' and 'copy', as 'copy' types are immutable +# type_parameter_requirements.inko:7:18 error(invalid-type): type parameters can't be both 'mut' and 'copy', as 'copy' types are immutable diff --git a/std/fixtures/diagnostics/class_with_trait_with_default_method.inko b/std/fixtures/diagnostics/type_with_trait_with_default_method.inko similarity index 88% rename from std/fixtures/diagnostics/class_with_trait_with_default_method.inko rename to std/fixtures/diagnostics/type_with_trait_with_default_method.inko index 72a5b5e9a..e5950b1bc 100644 --- a/std/fixtures/diagnostics/class_with_trait_with_default_method.inko +++ b/std/fixtures/diagnostics/type_with_trait_with_default_method.inko @@ -1,6 +1,6 @@ import foo (Foo) -class Bar { +type Bar { fn baz {} } diff --git a/std/fixtures/diagnostics/class_with_trait_with_default_method/foo.inko b/std/fixtures/diagnostics/type_with_trait_with_default_method/foo.inko similarity index 100% rename from std/fixtures/diagnostics/class_with_trait_with_default_method/foo.inko rename to std/fixtures/diagnostics/type_with_trait_with_default_method/foo.inko diff --git a/std/fixtures/diagnostics/uni_aliasing.inko b/std/fixtures/diagnostics/uni_aliasing.inko index 55501a06f..fd1e60c55 100644 --- a/std/fixtures/diagnostics/uni_aliasing.inko +++ b/std/fixtures/diagnostics/uni_aliasing.inko @@ -1,8 +1,8 @@ -class User { +type User { let @name: String } -class Box[T] { +type Box[T] { let @value: Option[T] let @borrow: Option[ref T] diff --git a/std/fixtures/diagnostics/uni_type_parameter_with_owned.inko b/std/fixtures/diagnostics/uni_type_parameter_with_owned.inko index e5bb1bb03..cbd65db75 100644 --- a/std/fixtures/diagnostics/uni_type_parameter_with_owned.inko +++ b/std/fixtures/diagnostics/uni_type_parameter_with_owned.inko @@ -1,4 +1,4 @@ -class Thing {} +type Thing {} fn foo[T](value: uni T) {} diff --git a/std/fixtures/diagnostics/uni_with_owned.inko b/std/fixtures/diagnostics/uni_with_owned.inko index 7e520399f..727d5b8ee 100644 --- a/std/fixtures/diagnostics/uni_with_owned.inko +++ b/std/fixtures/diagnostics/uni_with_owned.inko @@ -2,7 +2,7 @@ trait Eq[T] { fn eq(other: T) } -class Thing {} +type Thing {} impl Eq[uni Thing] for Thing { fn eq(other: uni Thing) {} diff --git a/std/fixtures/diagnostics/unreachable.inko b/std/fixtures/diagnostics/unreachable.inko index 5b47818b0..cc6182fad 100644 --- a/std/fixtures/diagnostics/unreachable.inko +++ b/std/fixtures/diagnostics/unreachable.inko @@ -1,4 +1,4 @@ -class Example { +type Example { fn example1 { return 42 diff --git a/std/fixtures/diagnostics/unused_imports/source.inko b/std/fixtures/diagnostics/unused_imports/source.inko index 50c3d5c76..c40bd9297 100644 --- a/std/fixtures/diagnostics/unused_imports/source.inko +++ b/std/fixtures/diagnostics/unused_imports/source.inko @@ -1,6 +1,6 @@ -class pub UnusedClass {} +type pub UnusedClass {} -class pub UsedClass {} +type pub UsedClass {} fn pub unused_method {} diff --git a/std/fixtures/diagnostics/value_types_passed_to_mutable_arguments.inko b/std/fixtures/diagnostics/value_types_passed_to_mutable_arguments.inko index c1a483b71..26e85a905 100644 --- a/std/fixtures/diagnostics/value_types_passed_to_mutable_arguments.inko +++ b/std/fixtures/diagnostics/value_types_passed_to_mutable_arguments.inko @@ -1,4 +1,4 @@ -class copy A { +type copy A { let @value: Int } diff --git a/std/fixtures/fmt/class_pattern/input.inko b/std/fixtures/fmt/type_pattern/input.inko similarity index 100% rename from std/fixtures/fmt/class_pattern/input.inko rename to std/fixtures/fmt/type_pattern/input.inko diff --git a/std/fixtures/fmt/class_pattern/output.inko b/std/fixtures/fmt/type_pattern/output.inko similarity index 100% rename from std/fixtures/fmt/class_pattern/output.inko rename to std/fixtures/fmt/type_pattern/output.inko diff --git a/std/fixtures/fmt/classes/input.inko b/std/fixtures/fmt/types/input.inko similarity index 50% rename from std/fixtures/fmt/classes/input.inko rename to std/fixtures/fmt/types/input.inko index f0c411420..b587a67a4 100644 --- a/std/fixtures/fmt/classes/input.inko +++ b/std/fixtures/fmt/types/input.inko @@ -1,59 +1,59 @@ -class A { +type A { let @b: Int } -class pub B { +type pub B { let @b: Int } -class async C { +type async C { let @b: Int } -class pub async D { +type pub async D { let @b: Int } -class builtin E { +type builtin E { let @b: Int } -class enum F { +type enum F { case A(Int) } -class pub enum G { +type pub enum G { case A(Int) } -class extern H { +type extern H { let @a: Int } -class pub extern I { +type pub extern I { let @a: Int } -class copy J { +type copy J { let @a: Int } -class pub copy K { +type pub copy K { let @a: Int } -class L { +type L { let @a: Int } -class pub M { +type pub M { let @a: Int } -class inline N { +type inline N { let @a: Int } -class inline enum O { +type inline enum O { case A } diff --git a/std/fixtures/fmt/classes/output.inko b/std/fixtures/fmt/types/output.inko similarity index 50% rename from std/fixtures/fmt/classes/output.inko rename to std/fixtures/fmt/types/output.inko index f0c411420..b587a67a4 100644 --- a/std/fixtures/fmt/classes/output.inko +++ b/std/fixtures/fmt/types/output.inko @@ -1,59 +1,59 @@ -class A { +type A { let @b: Int } -class pub B { +type pub B { let @b: Int } -class async C { +type async C { let @b: Int } -class pub async D { +type pub async D { let @b: Int } -class builtin E { +type builtin E { let @b: Int } -class enum F { +type enum F { case A(Int) } -class pub enum G { +type pub enum G { case A(Int) } -class extern H { +type extern H { let @a: Int } -class pub extern I { +type pub extern I { let @a: Int } -class copy J { +type copy J { let @a: Int } -class pub copy K { +type pub copy K { let @a: Int } -class L { +type L { let @a: Int } -class pub M { +type pub M { let @a: Int } -class inline N { +type inline N { let @a: Int } -class inline enum O { +type inline enum O { case A } diff --git a/std/src/std/array.inko b/std/src/std/array.inko index e33a22e1b..0886201d0 100644 --- a/std/src/std/array.inko +++ b/std/src/std/array.inko @@ -109,7 +109,7 @@ fn pub inline bounds_check(index: Int, size: Int) { # # All values in an array must be of the same type, and the array's value type is # based on the type of the first value. -class builtin Array[T] { +type builtin Array[T] { # The compiler depends on the order of these fields, so don't change it # without also updating the compiler. let @size: Int @@ -862,7 +862,7 @@ impl Array if T: Compare[T] { # # When this iterator is dropped, any values not yet moved out of the `Array` are # dropped. -class pub IntoIter[T] { +type pub IntoIter[T] { let @array: Array[T] let @index: Int diff --git a/std/src/std/base64.inko b/std/src/std/base64.inko index dac51107e..739c20d8e 100644 --- a/std/src/std/base64.inko +++ b/std/src/std/base64.inko @@ -618,7 +618,7 @@ fn pub decode(input: ref ByteArray) -> Result[ByteArray, DecodeError] { # Encoder.url_safe.encode(in, out) # out.into_string #=> 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5fEB7fS8mI1tdXCE_KCk8Pj0rKjsnImA6XiUkfg==' # ``` -class pub Encoder { +type pub Encoder { let @table0: ref Array[Int] let @table1: ref Array[Int] let @table2: ref Array[Int] @@ -713,7 +713,7 @@ class pub Encoder { } # An error produced when decoding a base64 encoded sequence of bytes. -class pub copy enum DecodeError { +type pub copy enum DecodeError { # The input size isn't a multiple of 4 bytes. case InvalidSize @@ -789,7 +789,7 @@ impl Equal[ref DecodeError] for DecodeError { # Decoder.url_safe.decode('8J-Ygw=='.to_byte_array, into: plain) # plain.into_string # => '😃' # ``` -class pub Decoder { +type pub Decoder { let @table0: ref Array[Int] let @table1: ref Array[Int] let @table2: ref Array[Int] diff --git a/std/src/std/bool.inko b/std/src/std/bool.inko index c9bee61d9..5793b41c4 100644 --- a/std/src/std/bool.inko +++ b/std/src/std/bool.inko @@ -7,7 +7,7 @@ import std.int (ToInt) import std.string (ToString) # The class for boolean `true` and `false`. -class builtin Bool { +type builtin Bool { # Returns `true` if `self` is `true`. # # # Examples diff --git a/std/src/std/byte_array.inko b/std/src/std/byte_array.inko index 699f52860..be9a81dbe 100644 --- a/std/src/std/byte_array.inko +++ b/std/src/std/byte_array.inko @@ -110,7 +110,7 @@ trait pub IntoByteArray { # Byte arrays are primarily meant for reading and writing data from/to a stream, # such as a file or a socket. If you simply want to store a list of numbers, # you're better off using the `Array` type. -class builtin ByteArray { +type builtin ByteArray { # Returns a new empty `ByteArray`. fn pub static new -> ByteArray { inko_byte_array_new(_INKO.state) diff --git a/std/src/std/cmp.inko b/std/src/std/cmp.inko index 7d810446e..663118188 100644 --- a/std/src/std/cmp.inko +++ b/std/src/std/cmp.inko @@ -3,7 +3,7 @@ import std.fmt (Format, Formatter) # A type describing the ordering between two values. -class pub copy enum Ordering { +type pub copy enum Ordering { case Less case Equal case Greater diff --git a/std/src/std/crypto/chacha.inko b/std/src/std/crypto/chacha.inko index 5edb1ad8a..da616b9ca 100644 --- a/std/src/std/crypto/chacha.inko +++ b/std/src/std/crypto/chacha.inko @@ -106,7 +106,7 @@ fn pub hchacha20(key: ref ByteArray, nonce: ref ByteArray) -> ByteArray { out } -class inline Matrix { +type inline Matrix { let @words: Array[Int] fn mut quarter_round(a: Int, b: Int, c: Int, d: Int) { @@ -216,7 +216,7 @@ class inline Matrix { # .decrypt(encrypted) # .to_string # => 'I like turtles' # ``` -class pub inline ChaCha20 { +type pub inline ChaCha20 { let @matrix: Matrix # Returns a new ChaCha20 cipher from the given key and nonce. @@ -363,7 +363,7 @@ impl Cipher for ChaCha20 { # For more information about XChaCha20 and the differences between it and # ChaCha20, consider reading the RFC that describes XChaCha20 at # . -class pub inline XChaCha20 { +type pub inline XChaCha20 { let @chacha: ChaCha20 # Returns a new XChaCha20 cipher from the given key and nonce. diff --git a/std/src/std/crypto/hash.inko b/std/src/std/crypto/hash.inko index 518732ca1..c4e7a988c 100644 --- a/std/src/std/crypto/hash.inko +++ b/std/src/std/crypto/hash.inko @@ -9,7 +9,7 @@ import std.string (ToString) let HEX_DIGITS = '0123456789abcdef' # A fixed-size block of bytes. -class pub Block { +type pub Block { let @bytes: ByteArray # The index to write the next byte to. @@ -117,7 +117,7 @@ class pub Block { # trait to implement. In addition it's aimed at hasher related to cryptography, # such as SHA256 and Poly1305. This type isn't suitable for hashing arbitrary # Inko types. -class pub inline Hash { +type pub inline Hash { # The bytes that make up this Hash. let pub @bytes: ByteArray diff --git a/std/src/std/crypto/md5.inko b/std/src/std/crypto/md5.inko index d99a1bdbe..0c4aead66 100644 --- a/std/src/std/crypto/md5.inko +++ b/std/src/std/crypto/md5.inko @@ -70,7 +70,7 @@ let SHIFTS = [ let BLOCK_SIZE = 64 # An MD5 hasher. -class pub Md5 { +type pub Md5 { let @block: Block let @words: Array[Int] let @size: Int diff --git a/std/src/std/crypto/pem.inko b/std/src/std/crypto/pem.inko index 63be95181..92224d0b1 100644 --- a/std/src/std/crypto/pem.inko +++ b/std/src/std/crypto/pem.inko @@ -76,7 +76,7 @@ let WHITESPACE = [ ] # A value/section parsed from a PEM file. -class pub inline enum Item { +type pub inline enum Item { # An X.509 certificate. case Certificate(Certificate) @@ -104,7 +104,7 @@ impl Equal[ref Item] for Item { } # An error produced while parsing a PEM file. -class pub inline enum ParseError { +type pub inline enum ParseError { # An IO error occurred while reading data to parse. case Read(Error) @@ -193,7 +193,7 @@ impl Equal[ref ParseError] for ParseError { # # parser.next_certificate # => Result.Ok(Option.Some(Certificate(...))) # ``` -class pub PemFile[I: mut + Read] { +type pub PemFile[I: mut + Read] { let @input: BufferedReader[I] let @line: Int let @buffer: ByteArray diff --git a/std/src/std/crypto/poly1305.inko b/std/src/std/crypto/poly1305.inko index e39fb3ceb..c1b5abd88 100644 --- a/std/src/std/crypto/poly1305.inko +++ b/std/src/std/crypto/poly1305.inko @@ -30,7 +30,7 @@ fn key_size_error(size: Int) -> Never { } # The Poly1305 universal hash function. -class pub Poly1305 { +type pub Poly1305 { let @block: Block # The constant multipliers derived from the secret key. diff --git a/std/src/std/crypto/sha1.inko b/std/src/std/crypto/sha1.inko index 5e5308511..ebcf6698a 100644 --- a/std/src/std/crypto/sha1.inko +++ b/std/src/std/crypto/sha1.inko @@ -33,7 +33,7 @@ import std.endian.big let BLOCK_SIZE = 64 # A SHA1 hasher. -class pub Sha1 { +type pub Sha1 { let @block: Block let @words: Array[Int] let @size: Int diff --git a/std/src/std/crypto/sha2.inko b/std/src/std/crypto/sha2.inko index a217deedc..cbf11f60a 100644 --- a/std/src/std/crypto/sha2.inko +++ b/std/src/std/crypto/sha2.inko @@ -75,7 +75,7 @@ let SHA512_TABLE = [ ] # A SHA256 hasher. -class pub Sha256 { +type pub Sha256 { let @block: Block let @words: Array[Int] let @size: Int @@ -235,7 +235,7 @@ impl Hasher for Sha256 { } # A SHA512 hasher. -class pub Sha512 { +type pub Sha512 { let @block: Block let @words: Array[Int] let @size: Int diff --git a/std/src/std/crypto/x509.inko b/std/src/std/crypto/x509.inko index e2f4659eb..3bcf5ea7d 100644 --- a/std/src/std/crypto/x509.inko +++ b/std/src/std/crypto/x509.inko @@ -5,7 +5,7 @@ import std.fmt (Format, Formatter) # An X.509 certificate. # # This is currently just an opaque wrapper around a `ByteArray`. -class pub inline Certificate { +type pub inline Certificate { let @bytes: ByteArray # Returns a new `Certificate` that wraps the given `ByteArray`. @@ -29,7 +29,7 @@ impl Equal[ref Certificate] for Certificate { # An X.509 private key. # # This is currently just an opaque wrapper around a `ByteArray`. -class pub inline PrivateKey { +type pub inline PrivateKey { let @bytes: ByteArray # Returns a new `PrivateKey` that wraps the given `ByteArray`. diff --git a/std/src/std/csv.inko b/std/src/std/csv.inko index ed800ac0b..5dafa650a 100644 --- a/std/src/std/csv.inko +++ b/std/src/std/csv.inko @@ -62,7 +62,7 @@ fn quote?(value: String, separator: Int) -> Bool { } # An error produced when parsing a CSV stream. -class pub inline Error { +type pub inline Error { # The kind of error that's produced. let pub @kind: ErrorKind @@ -101,7 +101,7 @@ impl Equal[ref Error] for Error { } # A type indicating what kind of error is produced. -class pub inline enum ErrorKind { +type pub inline enum ErrorKind { # An error produced when reading input. # # This error is produced when the underlying stream of a `Parser` produces an @@ -140,7 +140,7 @@ impl Equal[ref ErrorKind] for ErrorKind { } # A type describing the column separator. -class pub copy enum Separator { +type pub copy enum Separator { # Columns are separated using a comma (","). case Comma @@ -288,7 +288,7 @@ impl ToInt for Separator { # # rows # => [['foo', 'bar', 'baz'], ['1', '2', '3']] # ``` -class pub Parser[I: mut + Read] { +type pub Parser[I: mut + Read] { let @input: BufferedReader[I] let @buffer: ByteArray let @offset: Int @@ -714,7 +714,7 @@ impl Iter[Result[Array[String], Error]] for Parser { # gen.write(['foo', 'bar', 'baz']) # gen.write(['1', '2', '3']) # ``` -class pub Generator[I: mut + Write] { +type pub Generator[I: mut + Write] { let @output: I let @separator_string: String let @separator_byte: Int diff --git a/std/src/std/debug.inko b/std/src/std/debug.inko index 70907ce7f..6cae37a0c 100644 --- a/std/src/std/debug.inko +++ b/std/src/std/debug.inko @@ -29,7 +29,7 @@ fn extern inko_process_stack_frame_path( ) -> String # Details of a single stack frame in a stack trace. -class pub inline StackFrame { +type pub inline StackFrame { # The path of the file the frame belongs to. let pub @path: Path diff --git a/std/src/std/deque.inko b/std/src/std/deque.inko index 16d858674..1a1d8f1ab 100644 --- a/std/src/std/deque.inko +++ b/std/src/std/deque.inko @@ -18,7 +18,7 @@ fn invalid_capacity(size: Int) -> Never { # The implementation is currently based on Rust's `VecDeque` type, which in turn # is based on a comment by dizzy57 on [this # article](https://www.snellman.net/blog/archive/2016-12-13-ring-buffers/). -class pub Deque[T] { +type pub Deque[T] { # The number of values stored in the deque. let @size: Int @@ -474,7 +474,7 @@ impl Drop for Deque { # # When this iterator is dropped, any values not yet moved out of the `Deque` are # dropped. -class pub IntoIter[T] { +type pub IntoIter[T] { let @deque: Deque[T] let @indexes: Stream[Int] } diff --git a/std/src/std/env.inko b/std/src/std/env.inko index e8d486783..3336af745 100644 --- a/std/src/std/env.inko +++ b/std/src/std/env.inko @@ -22,7 +22,7 @@ import std.fs.path (Path) import std.io (Error) import std.string (ToString) -class extern AnyResult { +type extern AnyResult { let @tag: Int let @value: UInt64 } diff --git a/std/src/std/float.inko b/std/src/std/float.inko index 5ef7e372f..29782c5d7 100644 --- a/std/src/std/float.inko +++ b/std/src/std/float.inko @@ -7,7 +7,7 @@ import std.int (MAX, MIN, ToInt) import std.ops (Add, Divide, Modulo, Multiply, Power, Subtract) import std.string (Bytes, ToString) -class extern FloatResult { +type extern FloatResult { let @tag: Int let @value: UInt64 } @@ -23,7 +23,7 @@ trait pub ToFloat { } # A 64-bit floating point number. -class builtin Float { +type builtin Float { # Returns a NaN. fn pub inline static not_a_number -> Float { 0.0 / 0.0 diff --git a/std/src/std/fmt.inko b/std/src/std/fmt.inko index aeef180b8..a6238001e 100644 --- a/std/src/std/fmt.inko +++ b/std/src/std/fmt.inko @@ -23,7 +23,7 @@ fn pub fmt[T: Format](value: ref T) -> String { # A type for making it easy to format tuple-like values, such as tuples and # enums. -class pub TupleFormatter { +type pub TupleFormatter { let @formatter: mut Formatter let @named: Bool let @fields: Int @@ -55,7 +55,7 @@ class pub TupleFormatter { } # A type for making it easy to format array-like values. -class pub ArrayFormatter { +type pub ArrayFormatter { let @formatter: mut Formatter let @fields: Int @@ -79,7 +79,7 @@ class pub ArrayFormatter { } # A type for making it easy to format regular objects. -class pub ObjectFormatter { +type pub ObjectFormatter { let @formatter: mut Formatter let @named: Bool let @fields: Int @@ -118,7 +118,7 @@ class pub ObjectFormatter { } # The default formatter to use when formatting an object. -class pub Formatter { +type pub Formatter { let @buffer: StringBuffer let @nesting: Int diff --git a/std/src/std/fs.inko b/std/src/std/fs.inko index d1566ba64..a490ae1fa 100644 --- a/std/src/std/fs.inko +++ b/std/src/std/fs.inko @@ -5,7 +5,7 @@ import std.fs.path (Path) import std.time (DateTime) # A type describing the type of file, such as a file or directory. -class pub copy enum FileType { +type pub copy enum FileType { # The file is a file. case File @@ -72,7 +72,7 @@ impl Format for FileType { # # Instances of this type are typically produced by `std.fs.path.Path.list`, # so see that method's documentation for additional details. -class pub inline DirectoryEntry { +type pub inline DirectoryEntry { # The path to the entry. let pub @path: Path @@ -100,7 +100,7 @@ impl Format for DirectoryEntry { # # The seconds and nanoseconds are stored separately to ensure no loss of # precision, something that might happen when storing the time as a `Float`. -class copy Time { +type copy Time { let @secs: Int let @nanos: Int @@ -113,7 +113,7 @@ class copy Time { # A type containing metadata of a file or directory, such as its type and # creation time. -class pub inline Metadata { +type pub inline Metadata { # The type of the file. let pub @type: FileType diff --git a/std/src/std/fs/file.inko b/std/src/std/fs/file.inko index caded2280..97e2f312c 100644 --- a/std/src/std/fs/file.inko +++ b/std/src/std/fs/file.inko @@ -27,7 +27,7 @@ import std.sys.unix.fs (self as sys) if unix # # `ReadOnlyFile` is allocated on the heap as this allows one to cast it to a # trait, such as the `Read` trait. -class pub ReadOnlyFile { +type pub ReadOnlyFile { let @fd: Int32 # The path of the file. @@ -108,7 +108,7 @@ impl Seek for ReadOnlyFile { # # `WriteOnlyFile` is allocated on the heap as this allows one to cast it to a # trait, such as the `Write` trait. -class pub WriteOnlyFile { +type pub WriteOnlyFile { let @fd: Int32 # The path of the file. @@ -223,7 +223,7 @@ impl Seek for WriteOnlyFile { # # `ReadWriteFile` is allocated on the heap as this allows one to cast it to a # trait, such as the `Write` trait. -class pub ReadWriteFile { +type pub ReadWriteFile { let @fd: Int32 # The path of the file. diff --git a/std/src/std/fs/path.inko b/std/src/std/fs/path.inko index 92e3e931e..2a4ab5d07 100644 --- a/std/src/std/fs/path.inko +++ b/std/src/std/fs/path.inko @@ -10,7 +10,7 @@ import std.iter (Iter, Stream) import std.string (IntoString, StringBuffer, ToString) import std.sys.unix.fs (self as sys) if unix -class extern AnyResult { +type extern AnyResult { let @tag: Int let @value: UInt64 } @@ -82,7 +82,7 @@ fn join_strings(base: ref String, with: ref String) -> String { # An iterator over the entries in a directory. # # See the documentation of `std.fs.path.Path.list` for more details. -class pub ReadDirectory { +type pub ReadDirectory { let @path: String let @inner: sys.ReadDirectory } @@ -90,11 +90,11 @@ class pub ReadDirectory { impl Iter[Result[DirectoryEntry, Error]] for ReadDirectory { fn pub mut next -> Option[Result[DirectoryEntry, Error]] { let ret = match try { @inner.next } { - case Ok((path, type)) -> { + case Ok((path, typ)) -> { Result.Ok( DirectoryEntry( path: Path.new(join_strings(@path, with: path)), - type: type, + type: typ, ), ) } @@ -106,7 +106,7 @@ impl Iter[Result[DirectoryEntry, Error]] for ReadDirectory { } # An iterator over the components in a `Path`. -class pub Components { +type pub Components { let @path: ref Path let @index: Int let @size: Int @@ -212,7 +212,7 @@ impl Iter[String] for Components { # # '/tmp/hello.txt'.to_path # ``` -class pub inline Path { +type pub inline Path { # The raw file path. let @path: String diff --git a/std/src/std/hash/siphash.inko b/std/src/std/hash/siphash.inko index 47c04ba03..61d9e4373 100644 --- a/std/src/std/hash/siphash.inko +++ b/std/src/std/hash/siphash.inko @@ -19,7 +19,7 @@ import std.hash (Hasher) # hasher.write(42) # hasher.finish # ``` -class pub SipHasher13 { +type pub SipHasher13 { let @size: Int let @m_index: Int let @m: Int diff --git a/std/src/std/int.inko b/std/src/std/int.inko index 3204f25d9..d87d67348 100644 --- a/std/src/std/int.inko +++ b/std/src/std/int.inko @@ -39,7 +39,7 @@ let LOWER_X = 120 # # This is the `{i64, i1}` type returned by the LLVM checked arithmetic # intrinsics, and must match its layout. -class builtin CheckedIntResult { +type builtin CheckedIntResult { let @value: Int64 let @tag: UInt8 } @@ -55,7 +55,7 @@ fn overflow(left: Int, right: Int) -> Never { } # The format to use for parsing and formatting an `Int`. -class pub copy enum Format { +type pub copy enum Format { # The `Int` is to be parsed or formatted as a binary number. case Binary @@ -82,7 +82,7 @@ class pub copy enum Format { # # Panics # # Integer operations that would result in an overflow produce a panic. -class builtin Int { +type builtin Int { # Parses a `Bytes` into an `Int` in the format specified in `format`, # returning a `Some` if the value is valid, and a `None` otherwise. # diff --git a/std/src/std/io.inko b/std/src/std/io.inko index cebab516d..4252bab81 100644 --- a/std/src/std/io.inko +++ b/std/src/std/io.inko @@ -110,7 +110,7 @@ fn reset_os_error { # Unix systems. This enum doesn't define a constructor for every possible error. # Instead, we define a constructor for the most commonly used errors, and # represent other errors using the `Other` constructor. -class pub copy enum Error { +type pub copy enum Error { # The address is already in use. case AddressInUse @@ -753,7 +753,7 @@ trait pub BufferedRead: Read { # may involve many system calls. `BufferedReader` wraps a `Read` and buffers # data into an internal buffer, reducing the total amount of system calls, at # the cost of needing to maintain an in-memory buffer. -class pub BufferedReader[T: mut + Read] { +type pub BufferedReader[T: mut + Read] { let @reader: T let @buffer: ByteArray let @capacity: Int @@ -883,7 +883,7 @@ impl Read for BufferedReader { # writer.write_string('hello') # => Result.Ok(nil) # writer.flush # => Result.Ok(nil) # ``` -class pub BufferedWriter[T: mut + Write] { +type pub BufferedWriter[T: mut + Write] { let @writer: T let @buffer: ByteArray let @size: Int @@ -1034,7 +1034,7 @@ impl Drop for BufferedWriter { # # read_string(reader) # => "hello" # ``` -class pub Buffer[T: Bytes] { +type pub Buffer[T: Bytes] { let @bytes: T let @offset: Int diff --git a/std/src/std/iter.inko b/std/src/std/iter.inko index cc16a45e2..753b08567 100644 --- a/std/src/std/iter.inko +++ b/std/src/std/iter.inko @@ -671,7 +671,7 @@ trait pub IntoIter[T] { # nums.next # => Option.Some(1) # } # ``` -class pub Stream[T] { +type pub Stream[T] { let @func: fn -> Option[T] # Returns a new iterator using the closure. @@ -688,7 +688,7 @@ impl Iter[T] for Stream { # An iterator that allows looking at the next element in an iterator, without # consuming it. -class pub Peekable[T] { +type pub Peekable[T] { let @iter: Iter[T] let @peeked: Option[Option[T]] diff --git a/std/src/std/json.inko b/std/src/std/json.inko index 777068f37..e6b1b30f0 100644 --- a/std/src/std/json.inko +++ b/std/src/std/json.inko @@ -146,7 +146,7 @@ fn char(byte: Int) -> String { # End users don't really care about the difference between # RecursionLimitExceeded and InvalidSurrogate(...), nor can they really act # differently based on the kind of error. -class pub inline enum ErrorKind { +type pub inline enum ErrorKind { # The maximum recursion limit is exceeded. case RecursionLimitExceeded(Int) @@ -201,7 +201,7 @@ impl ToString for ErrorKind { } # A type describing an error produced while parsing a JSON document. -class pub inline Error { +type pub inline Error { # A value describing the kind of error. let pub @kind: ErrorKind @@ -284,7 +284,7 @@ impl ToString for Error { # and `Query.index` to get the value of an array index. Methods such as # `Query.as_string` and `Query.as_int` are used to extract the final value as a # certain type, if such a value is present. -class pub inline Query { +type pub inline Query { let @value: Option[ref Json] # Returns a `Query` that matches the value assigned to the object key `name`, @@ -437,7 +437,7 @@ class pub inline Query { } # A JSON value, such as `true` or an array. -class pub inline enum Json { +type pub inline enum Json { case Int(Int) case Float(Float) case String(String) @@ -550,7 +550,7 @@ impl Equal[ref Json] for Json { } # A numeric value that's either an `Int` or a `Float`. -class pub inline enum Number { +type pub inline enum Number { case Int(Int) case Float(Float) } @@ -576,7 +576,7 @@ impl FormatTrait for Number { # A type describing what kind of value is located at the current position in an # input stream. -class pub inline enum Type { +type pub inline enum Type { case Array case Bool case Null @@ -654,7 +654,7 @@ impl FormatTrait for Type { # .parse # .get # ``` -class pub PullParser[T: mut + Read] { +type pub PullParser[T: mut + Read] { let @input: BufferedReader[T] let @offset: Int let @buffer: ByteArray @@ -1294,7 +1294,7 @@ class pub PullParser[T: mut + Read] { } # A parsing rule defined for an `ObjectParser`. -class pub Rule[T: mut + Read] { +type pub Rule[T: mut + Read] { let @id: Int let @parser: fn (mut PullParser[T]) -> Result[Nil, Error] let @required: Bool @@ -1324,7 +1324,7 @@ class pub Rule[T: mut + Read] { # obj.int('b', fn (v) { nums.push(v) }).optional # obj.parse(parser).or_panic('failed to parse the JSON') # ``` -class pub inline ObjectParser[T: mut + Read] { +type pub inline ObjectParser[T: mut + Read] { # The keys to parse along with the closures that parse their values. let @rules: Map[String, Rule[T]] @@ -1437,7 +1437,7 @@ class pub inline ObjectParser[T: mut + Read] { # This parser enforces a limit on the number of nested arrays and objects. The # default is sufficiently large that most documents won't result in an error # being thrown. This limit is controlled by the field `Parser.max_depth`. -class pub Parser[T: mut + Read] { +type pub Parser[T: mut + Read] { let @pull: PullParser[T] let @depth: Int @@ -1547,7 +1547,7 @@ class pub Parser[T: mut + Read] { # This type is used by `Json.to_string` and `Json.to_pretty_string`. Unless you # want to use custom indentation, it's recommended to use these methods instead # of using `Generator` directly. -class pub Generator { +type pub Generator { let @pretty: Bool let @spaces: String let @depth: Int diff --git a/std/src/std/libc.inko b/std/src/std/libc.inko index 2a142ba3a..73f297dcb 100644 --- a/std/src/std/libc.inko +++ b/std/src/std/libc.inko @@ -93,24 +93,24 @@ let SO_SNDBUF = sys.SO_SNDBUF let TCP_NODELAY = sys.TCP_NODELAY let WNOHANG = sys.WNOHANG -class extern SigSet { +type extern SigSet { let @inner: sys.SigSet } -class extern PosixSpawnAttrs { +type extern PosixSpawnAttrs { let @inner: sys.PosixSpawnAttrs } -class extern PosixSpawnFileActions { +type extern PosixSpawnFileActions { let @inner: sys.PosixSpawnFileActions } -class extern Linger { +type extern Linger { let @l_onoff: Int32 let @l_linger: Int32 } -class extern Tm { +type extern Tm { let @tm_sec: Int32 let @tm_min: Int32 let @tm_hour: Int32 @@ -124,7 +124,7 @@ class extern Tm { let @tm_zone: Pointer[UInt8] } -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } @@ -246,7 +246,7 @@ fn extern free(pointer: Pointer[UInt8]) fn extern exit(status: Int32) -> Never -fn extern socket(domain: Int32, type: Int32, protocol: Int32) -> Int32 +fn extern socket(domain: Int32, typ: Int32, protocol: Int32) -> Int32 fn extern bind(socket: Int32, addr: Pointer[UInt8], size: UInt32) -> Int32 diff --git a/std/src/std/libc/freebsd.inko b/std/src/std/libc/freebsd.inko index bc4af9f5d..0c892bc6e 100644 --- a/std/src/std/libc/freebsd.inko +++ b/std/src/std/libc/freebsd.inko @@ -90,7 +90,7 @@ let WNOHANG = 0x00000001 # easier to handle platform differences. let ETIME = -1 -class extern Dirent { +type extern Dirent { let @d_fileno: UInt64 let @d_off: UInt64 let @d_reclen: UInt16 @@ -99,12 +99,12 @@ class extern Dirent { let @d_pad0: UInt32 } -class extern Timespec { +type extern Timespec { let @tv_sec: Int64 let @tv_nsec: Int64 } -class extern StatBuf { +type extern StatBuf { let @st_dev: UInt64 let @st_ino: UInt64 let @st_nlink: UInt64 @@ -135,27 +135,27 @@ class extern StatBuf { let @st_spare9: Int64 } -class extern Pipes { +type extern Pipes { let @reader: Int32 let @writer: Int32 } -class extern SigSet { +type extern SigSet { let @__val0: UInt32 let @__val1: UInt32 let @__val2: UInt32 let @__val3: UInt32 } -class extern PosixSpawnAttrs { +type extern PosixSpawnAttrs { let @inner: Pointer[UInt8] } -class extern PosixSpawnFileActions { +type extern PosixSpawnFileActions { let @inner: Pointer[UInt8] } -class extern SockAddrIn { +type extern SockAddrIn { let @sin_len: UInt8 let @sin_family: UInt8 let @sin_port: UInt16 @@ -163,7 +163,7 @@ class extern SockAddrIn { let @sin_zero: UInt64 } -class extern SockAddrIn6 { +type extern SockAddrIn6 { let @sin6_len: UInt8 let @sin6_family: UInt8 let @sin6_port: UInt16 @@ -175,7 +175,7 @@ class extern SockAddrIn6 { let @sin6_scope_id: UInt32 } -class extern SockAddrUn { +type extern SockAddrUn { let @sun_len: UInt8 let @sun_family: UInt8 let @sun_path0: UInt8 @@ -284,7 +284,7 @@ class extern SockAddrUn { let @sun_path103: UInt8 } -class extern SockAddr { +type extern SockAddr { let @sa_len: UInt8 let @sa_family: UInt8 let @sa_data0: UInt8 @@ -303,7 +303,7 @@ class extern SockAddr { let @sa_data13: UInt8 } -class extern SockAddrStorage { +type extern SockAddrStorage { let @ss_len: UInt8 let @ss_family: UInt8 let @__pad0: UInt16 diff --git a/std/src/std/libc/linux.inko b/std/src/std/libc/linux.inko index 3d9d34902..52d554cd5 100644 --- a/std/src/std/libc/linux.inko +++ b/std/src/std/libc/linux.inko @@ -93,14 +93,14 @@ let S_IFREG = 0x8000 let TCP_NODELAY = 1 let WNOHANG = 0x00000001 -class extern Dirent { +type extern Dirent { let @d_ino: UInt64 let @d_off: UInt64 let @d_reclen: UInt16 let @d_type: UInt8 } -class extern StatxBuf { +type extern StatxBuf { let @stx_mask: UInt32 let @stx_blksize: UInt32 let @stx_attributes: UInt64 @@ -138,13 +138,13 @@ class extern StatxBuf { let @__pad12: UInt64 } -class extern StatxTimestamp { +type extern StatxTimestamp { let @tv_sec: Int64 let @tv_nsec: UInt32 let @__pad0: Int32 } -class extern SigSet { +type extern SigSet { let @__val0: UInt64 let @__val1: UInt64 let @__val2: UInt64 @@ -163,7 +163,7 @@ class extern SigSet { let @__val15: UInt64 } -class extern PosixSpawnAttrs { +type extern PosixSpawnAttrs { let @__flags: Int16 let @__pgrp: Int32 let @__sd: SigSet @@ -188,7 +188,7 @@ class extern PosixSpawnAttrs { let @__pad14: Int32 } -class extern PosixSpawnFileActions { +type extern PosixSpawnFileActions { let @__allocated: Int32 let @__used: Int32 let @__actions: Pointer[UInt8] @@ -210,19 +210,19 @@ class extern PosixSpawnFileActions { let @__pad15: Int32 } -class extern Pipes { +type extern Pipes { let @reader: Int32 let @writer: Int32 } -class extern SockAddrIn { +type extern SockAddrIn { let @sin_family: UInt16 let @sin_port: UInt16 let @sin_addr: UInt32 let @sin_zero: UInt64 } -class extern SockAddrIn6 { +type extern SockAddrIn6 { let @sin6_family: UInt16 let @sin6_port: UInt16 let @sin6_flowinfo: UInt32 @@ -233,7 +233,7 @@ class extern SockAddrIn6 { let @sin6_scope_id: UInt32 } -class extern SockAddrUn { +type extern SockAddrUn { let @sun_family: UInt16 let @sun_path0: UInt8 let @sun_path1: UInt8 @@ -345,7 +345,7 @@ class extern SockAddrUn { let @sun_path107: UInt8 } -class extern SockAddr { +type extern SockAddr { let @sa_family: UInt16 let @sa_data0: UInt8 let @sa_data1: UInt8 @@ -363,7 +363,7 @@ class extern SockAddr { let @sa_data13: UInt8 } -class extern SockAddrStorage { +type extern SockAddrStorage { let @ss_family: UInt16 let @__pad0: UInt16 let @__pad1: UInt32 diff --git a/std/src/std/libc/mac.inko b/std/src/std/libc/mac.inko index 1922609a6..c61588134 100644 --- a/std/src/std/libc/mac.inko +++ b/std/src/std/libc/mac.inko @@ -100,7 +100,7 @@ let WNOHANG = 0x00000001 # instead of ticks, and `SO_LINGER` itself isn't useful. let SO_LINGER = SO_LINGER_SEC -class extern Dirent { +type extern Dirent { let @d_ino: UInt64 let @d_seekoff: UInt64 let @d_reclen: UInt16 @@ -108,7 +108,7 @@ class extern Dirent { let @d_type: UInt8 } -class extern StatBuf { +type extern StatBuf { let @st_dev: Int32 let @st_mode: UInt16 let @st_nlink: UInt16 @@ -134,24 +134,24 @@ class extern StatBuf { let @st_qspare1: Int64 } -class extern Pipes { +type extern Pipes { let @reader: Int32 let @writer: Int32 } -class extern SigSet { +type extern SigSet { let @inner: UInt32 } -class extern PosixSpawnAttrs { +type extern PosixSpawnAttrs { let @inner: Pointer[UInt8] } -class extern PosixSpawnFileActions { +type extern PosixSpawnFileActions { let @inner: Pointer[UInt8] } -class extern SockAddrIn { +type extern SockAddrIn { let @sin_len: UInt8 let @sin_family: UInt8 let @sin_port: UInt16 @@ -159,7 +159,7 @@ class extern SockAddrIn { let @sin_zero: UInt64 } -class extern SockAddrIn6 { +type extern SockAddrIn6 { let @sin6_len: UInt8 let @sin6_family: UInt8 let @sin6_port: UInt16 @@ -171,7 +171,7 @@ class extern SockAddrIn6 { let @sin6_scope_id: UInt32 } -class extern SockAddrUn { +type extern SockAddrUn { let @sun_len: UInt8 let @sun_family: UInt8 let @sun_path0: UInt8 @@ -280,7 +280,7 @@ class extern SockAddrUn { let @sun_path103: UInt8 } -class extern SockAddr { +type extern SockAddr { let @sa_len: UInt8 let @sa_family: UInt8 let @sa_data0: UInt8 @@ -299,7 +299,7 @@ class extern SockAddr { let @sa_data13: UInt8 } -class extern SockAddrStorage { +type extern SockAddrStorage { let @ss_len: UInt8 let @ss_family: UInt8 let @__pad0: UInt16 diff --git a/std/src/std/locale/en.inko b/std/src/std/locale/en.inko index cfe413a16..c184dc2d8 100644 --- a/std/src/std/locale/en.inko +++ b/std/src/std/locale/en.inko @@ -77,7 +77,7 @@ fn month_prefix_index[T: Bytes](input: ref T, start: Int) -> Option[Int] { # # This type handles both US and UK English as in its current implementation # there are no differences between the two. -class pub copy Locale { +type pub copy Locale { # Returns a new `Locale`. fn pub inline static new -> Locale { Locale() diff --git a/std/src/std/locale/ja.inko b/std/src/std/locale/ja.inko index 4e2c15708..30db4ea3b 100644 --- a/std/src/std/locale/ja.inko +++ b/std/src/std/locale/ja.inko @@ -31,7 +31,7 @@ let FULL_WEEKDAYS = [ ] # Locale data for Japanese. -class pub copy Locale { +type pub copy Locale { # Returns a new `Locale`. fn pub inline static new -> Locale { Locale() diff --git a/std/src/std/locale/nl.inko b/std/src/std/locale/nl.inko index 3a6e9ebe3..8763f91d2 100644 --- a/std/src/std/locale/nl.inko +++ b/std/src/std/locale/nl.inko @@ -46,7 +46,7 @@ let FULL_WEEKDAYS = [ ] # Locale data for Dutch. -class pub copy Locale { +type pub copy Locale { # Returns a new `Locale`. fn pub inline static new -> Locale { Locale() diff --git a/std/src/std/map.inko b/std/src/std/map.inko index 948499b4c..4f22bc666 100644 --- a/std/src/std/map.inko +++ b/std/src/std/map.inko @@ -17,7 +17,7 @@ let EMPTY = -1 let DEFAULT_CAPACITY = 4 # An entry stored in a Map. -class pub Entry[K: Equal[ref K] + Hash, V] { +type pub Entry[K: Equal[ref K] + Hash, V] { # The key that was hashed. let @key: K @@ -89,7 +89,7 @@ impl Clone[Entry[K, V]] for Entry if K: Clone[K], V: Clone[V] { # - # - # - -class pub Map[K: Equal[ref K] + Hash, V] { +type pub Map[K: Equal[ref K] + Hash, V] { # The slots we can hash into. # # An index of `-1` indicates the slot isn't used. A value of `0` or more diff --git a/std/src/std/net/ip.inko b/std/src/std/net/ip.inko index fb5950ba3..58f9986fc 100644 --- a/std/src/std/net/ip.inko +++ b/std/src/std/net/ip.inko @@ -43,7 +43,7 @@ fn octets_to_hextet(first: Int, second: Int) -> Int { } # An IPv4 or IPv6 address. -class pub copy enum IpAddress { +type pub copy enum IpAddress { # An IPv4 address. case V4(Ipv4Address) @@ -221,7 +221,7 @@ impl FormatTrait for IpAddress { } # An IPv6 address. -class pub copy Ipv6Address { +type pub copy Ipv6Address { let @a: Int let @b: Int let @c: Int @@ -645,7 +645,7 @@ impl Clone[Ipv6Address] for Ipv6Address { } # An IPv4 address. -class pub copy Ipv4Address { +type pub copy Ipv4Address { let @a: Int let @b: Int let @c: Int diff --git a/std/src/std/net/socket.inko b/std/src/std/net/socket.inko index ada5b431f..03f3c48c9 100644 --- a/std/src/std/net/socket.inko +++ b/std/src/std/net/socket.inko @@ -86,7 +86,7 @@ trait RawSocketOperations { } # An IPv4 or IPv6 socket address. -class pub copy SocketAddress { +type pub copy SocketAddress { # The IPv4/IPv6 address of this socket address. let pub @ip: IpAddress @@ -108,7 +108,7 @@ impl Format for SocketAddress { } # A low-level, non-blocking IPv4 or IPv6 socket. -class pub Socket { +type pub Socket { let @socket: net.RawSocket # A point in time after which socket operations time out. @@ -116,11 +116,11 @@ class pub Socket { # We use an `Int` to remove the need for using `Option[Instant]`. let @deadline: Int - fn static new(ipv6: Bool, type: Int, protocol: Int) -> Result[Socket, Error] { + fn static new(ipv6: Bool, kind: Int, protocol: Int) -> Result[Socket, Error] { let sock = net.raw_socket let domain = if ipv6 { libc.AF_INET6 } else { libc.AF_INET } - try sys.init_socket(mut sock, domain, type, protocol) + try sys.init_socket(mut sock, domain, kind, protocol) Result.Ok(Socket(socket: sock, deadline: net.NO_DEADLINE)) } @@ -615,7 +615,7 @@ impl Write for Socket { # # A `UdpSocket` can be used to easily create a bound UDP socket from an IP # address and a port. -class pub UdpSocket { +type pub UdpSocket { # The raw `Socket` wrapped by this `UdpSocket`. let pub @socket: Socket @@ -780,7 +780,7 @@ impl Write for UdpSocket { } # A TCP socket connected to another TCP socket. -class pub TcpClient { +type pub TcpClient { # The raw `Socket` wrapped by this `TcpClient`. let pub @socket: Socket @@ -918,7 +918,7 @@ impl Write for TcpClient { } # A TCP socket server that can accept incoming connections. -class pub TcpServer { +type pub TcpServer { # The raw `Socket` wrapped by this `TcpServer`. let pub @socket: Socket @@ -1005,7 +1005,7 @@ impl RawSocketOperations for TcpServer { } # A Unix domain socket address. -class pub inline UnixAddress { +type pub inline UnixAddress { # The path or name of the address. # # This is a `String` since using a `Path` does not make sense for abstract @@ -1107,7 +1107,7 @@ impl ToString for UnixAddress { } # A low-level, non-blocking Unix domain socket. -class pub UnixSocket { +type pub UnixSocket { let @socket: net.RawSocket # A point in time after which socket operations time out. @@ -1115,10 +1115,10 @@ class pub UnixSocket { # We use an `Int` to remove the need for using `Option[Instant]`. let @deadline: Int - fn static new(type: Int) -> Result[UnixSocket, Error] { + fn static new(kind: Int) -> Result[UnixSocket, Error] { let sock = net.raw_socket - try sys.init_socket(mut sock, libc.AF_UNIX, type, protocol: 0) + try sys.init_socket(mut sock, libc.AF_UNIX, kind, protocol: 0) Result.Ok(UnixSocket(socket: sock, deadline: net.NO_DEADLINE)) } @@ -1487,7 +1487,7 @@ impl Write for UnixSocket { } # A Unix datagram socket. -class pub UnixDatagram { +type pub UnixDatagram { # The raw `UnixSocket` wrapped by this `UnixDatagram`. let pub @socket: UnixSocket @@ -1634,7 +1634,7 @@ impl Write for UnixDatagram { } # A Unix stream socket connected to another Unix socket. -class pub UnixClient { +type pub UnixClient { # The raw `UnixSocket` wrapped by this `UnixClient`. let pub @socket: UnixSocket @@ -1764,7 +1764,7 @@ impl Write for UnixClient { } # A Unix socket server that can accept incoming connections. -class pub UnixServer { +type pub UnixServer { # The raw `UnixSocket` wrapped by this `UnixServer`. let pub @socket: UnixSocket diff --git a/std/src/std/net/tls.inko b/std/src/std/net/tls.inko index d5a6e8081..81417c8ee 100644 --- a/std/src/std/net/tls.inko +++ b/std/src/std/net/tls.inko @@ -142,12 +142,12 @@ fn extern inko_tls_server_close( let OK = 0 let ERROR = 2 -class extern AnyResult { +type extern AnyResult { let @tag: Int let @value: UInt64 } -class extern IntResult { +type extern IntResult { let @tag: Int let @value: Int } @@ -177,7 +177,7 @@ fn extern write_callback( } # An error produced when creating a `ServerConfig`. -class pub copy enum ServerConfigError { +type pub copy enum ServerConfigError { # The certificate exists but is invalid, such as when it's revoked or not # encoded correctly. case InvalidCertificate @@ -223,7 +223,7 @@ impl Format for ServerConfigError { # create a `ClientConfig` once and use `ClientConfig.clone` to clone it whenever # necessary (e.g. when sharing a `ClientConfig` between processes), as cloning a # `ClientConfig` is cheap. -class pub ClientConfig { +type pub ClientConfig { let @raw: Pointer[UInt8] # Returns a new `ClientConfig` that uses the system's certificate store. @@ -314,7 +314,7 @@ impl Clone[ClientConfig] for ClientConfig { # # client.read_all(response).or_panic('failed to read the response') # ``` -class pub Client[T: mut + RawSocketOperations] { +type pub Client[T: mut + RawSocketOperations] { # The socket wrapped by this `Client`. let pub @socket: T @@ -463,7 +463,7 @@ impl Write for Client { # certificate and private key that are used. As such, it's recommended to only # create a `ServerConfig` once and use `ServerConfig.clone` to clone it whenever # necessary, as cloning a `ServerConfig` is cheap. -class pub ServerConfig { +type pub ServerConfig { let @raw: Pointer[UInt8] # Returns a new `ClientConfig` using the specified PEM encoded X.509 @@ -553,7 +553,7 @@ impl Clone[ServerConfig] for ServerConfig { # # con.read(into: bytes, size: 32).or_panic('failed to read the data') # ``` -class pub Server[T: mut + RawSocketOperations] { +type pub Server[T: mut + RawSocketOperations] { # The socket wrapped by this `Server`. let pub @socket: T diff --git a/std/src/std/nil.inko b/std/src/std/nil.inko index b7bffa7ce..6de808163 100644 --- a/std/src/std/nil.inko +++ b/std/src/std/nil.inko @@ -12,7 +12,7 @@ import std.fmt (Format, Formatter) # # Don't use `Nil` directly, instead use the `Option` type whenever you have # optional values. -class builtin Nil { +type builtin Nil { # Returns a new `Nil`. fn pub static new -> Nil { nil diff --git a/std/src/std/option.inko b/std/src/std/option.inko index 6de1e5117..f8ca78342 100644 --- a/std/src/std/option.inko +++ b/std/src/std/option.inko @@ -15,7 +15,7 @@ import std.fmt (Format, Formatter) # # An `Option` is is either a `Some` containing a value, or a `None` that doesn't # contain a value. -class pub inline enum Option[T] { +type pub inline enum Option[T] { # A value of type `T`. case Some(T) diff --git a/std/src/std/optparse.inko b/std/src/std/optparse.inko index 036081e62..825d93396 100644 --- a/std/src/std/optparse.inko +++ b/std/src/std/optparse.inko @@ -168,7 +168,7 @@ fn basic_latin?(byte: Int) -> Bool { byte <= 127 } -class inline enum Token { +type inline enum Token { # A short option, such as `-h`. case Short(String) @@ -212,7 +212,7 @@ impl Format for Token { } } -class inline enum State { +type inline enum State { case Default case Rest case Value(String) @@ -220,7 +220,7 @@ class inline enum State { # A type that breaks up a list of command-line arguments into a series of # tokens. -class Lexer { +type Lexer { let @input: Stream[String] let @state: State @@ -346,7 +346,7 @@ fn consume_remaining(lexer: Lexer, remaining: mut Array[String]) { } # A type that describes a parsing error. -class pub inline enum Error { +type pub inline enum Error { # The given option isn't recognized. case InvalidOption(String) @@ -401,7 +401,7 @@ impl Format for Error { } } -class inline enum Value { +type inline enum Value { case String(String) case Flag @@ -423,7 +423,7 @@ impl Clone[Value] for Value { } # A type containing the parsed options and any remaining arguments. -class pub inline Matches { +type pub inline Matches { # The remaining/unparsed arguments. let pub @remaining: Array[String] @@ -519,13 +519,13 @@ class pub inline Matches { } } -class copy enum Kind { +type copy enum Kind { case Flag case Single case Multiple } -class Opt { +type Opt { let @kind: Kind let @short: String let @long: String @@ -534,7 +534,7 @@ class Opt { } # A type that describes the options to parse. -class pub Options { +type pub Options { # All options that have been defined. let @options: Array[Opt] @@ -903,7 +903,7 @@ impl ToString for Options { # -h, --help Show this help message # -v, --version Show the version # ``` -class pub Help { +type pub Help { # The name of the program/executable. let @name: String diff --git a/std/src/std/rand.inko b/std/src/std/rand.inko index 58f6f7afb..f1f37ced7 100644 --- a/std/src/std/rand.inko +++ b/std/src/std/rand.inko @@ -34,7 +34,7 @@ fn extern inko_random_bytes( # # The algorithm used is unspecified but guaranteed to be cryptographically # secure. -class pub Random { +type pub Random { # The internal/low-level random number generator. let @rng: Pointer[UInt8] @@ -132,7 +132,7 @@ impl Drop for Random { } # A type for sorting arrays in a random order. -class pub inline Shuffle { +type pub inline Shuffle { let @rng: Random # Returns a new `Shuffle` that sorts values in a random order. diff --git a/std/src/std/range.inko b/std/src/std/range.inko index 089e74ea0..44bf66ce8 100644 --- a/std/src/std/range.inko +++ b/std/src/std/range.inko @@ -45,7 +45,7 @@ trait pub Range: Contains[Int] + Hash + Format { } # An inclusive range of integers. -class pub copy InclusiveRange { +type pub copy InclusiveRange { let @start: Int let @end: Int @@ -145,7 +145,7 @@ impl Format for InclusiveRange { } # An exclusive range of integers. -class pub copy ExclusiveRange { +type pub copy ExclusiveRange { # The start value of the range. let @start: Int diff --git a/std/src/std/result.inko b/std/src/std/result.inko index 80b51cda9..1679c421a 100644 --- a/std/src/std/result.inko +++ b/std/src/std/result.inko @@ -8,7 +8,7 @@ import std.fmt (Format, Formatter) import std.iter (Iter) # A type that represents either success (`Ok(T)`) or failure (`Error(E)`). -class pub inline enum Result[T, E] { +type pub inline enum Result[T, E] { # The case and value for a successful result. case Ok(T) diff --git a/std/src/std/set.inko b/std/src/std/set.inko index 3b9640bdd..26ced5956 100644 --- a/std/src/std/set.inko +++ b/std/src/std/set.inko @@ -8,7 +8,7 @@ import std.iter (Stream) # # The order of values in this Set are not guaranteed. For values to be stored in # a `Set` they must implement the `Hash` and `Equal` traits. -class pub inline Set[V: Equal[ref V] + Hash] { +type pub inline Set[V: Equal[ref V] + Hash] { # The Map used for storing values. # # The keys are the values inserted in this `Set`, the values are always set to diff --git a/std/src/std/signal.inko b/std/src/std/signal.inko index 92e988206..4ede03d79 100644 --- a/std/src/std/signal.inko +++ b/std/src/std/signal.inko @@ -96,7 +96,7 @@ let SIGWINCH = 28 # This type doesn't support all possible signals, instead it only supports the # signals deemed useful and safe to use. Refer to the module documentation for # more details. -class pub copy enum Signal { +type pub copy enum Signal { # The SIGHUP signal. case Hangup diff --git a/std/src/std/stdio.inko b/std/src/std/stdio.inko index acc413ac9..63fac0224 100644 --- a/std/src/std/stdio.inko +++ b/std/src/std/stdio.inko @@ -37,7 +37,7 @@ import std.sys.unix.stdio (self as sys) if unix # # `Stdin` is allocated on the heap as this allows one to cast it to a trait, # such as the `Read` trait. -class pub Stdin { +type pub Stdin { let @fd: Int32 # Returns a new `Stdin`. @@ -80,7 +80,7 @@ impl Read for Stdin { # reason for this is simple: it's easy to apply buffering by combining `Stdout` # with existing types, but opting out of buffering would require additional # flags or types, resulting in a messy API. -class pub Stdout { +type pub Stdout { let @fd: Int32 # Returns a new `Stdout`. @@ -135,7 +135,7 @@ impl Write for Stdout { # This output stream _does not_ use any form of buffering and instead writes its # output directly. If buffering is desired, you can do so by wrapping a `Stdout` # in a `std.io.BufferedWriter`. -class pub Stderr { +type pub Stderr { let @fd: Int32 # Returns a new `Stderr`. diff --git a/std/src/std/string.inko b/std/src/std/string.inko index cec63c80d..13252801e 100644 --- a/std/src/std/string.inko +++ b/std/src/std/string.inko @@ -17,7 +17,7 @@ import std.iter (Iter, Stream) import std.ops (Add) import std.ptr -class extern StringResult { +type extern StringResult { let @tag: Int let @value: Pointer[UInt8] } @@ -151,7 +151,7 @@ trait pub Bytes { } # An UTF-8 encoded and immutable string type. -class builtin String { +type builtin String { # The size of the string in bytes, _excluding_ the trailing NULL byte. let @size: UInt64 @@ -902,7 +902,7 @@ impl Compare[String] for String { # as the Unicode specification changes. If you want to index into a `String` in # a stable way, it's best to calculate the character index, then translate that # to a more stable index such as the code point index, or the byte index. -class pub Chars { +type pub Chars { # The String we're iterating over. # # We need to maintain a reference to the String, otherwise the underlying @@ -973,7 +973,7 @@ impl Drop for Chars { # # buffer.to_string # => 'foobarbaz' # ``` -class pub inline StringBuffer { +type pub inline StringBuffer { let @strings: Array[String] # Returns a new empty `StringBuffer`. diff --git a/std/src/std/sync.inko b/std/src/std/sync.inko index 4b241ea5a..9c363fb56 100644 --- a/std/src/std/sync.inko +++ b/std/src/std/sync.inko @@ -59,7 +59,7 @@ let UNLOCKED = 0 let LOCKED = 1 # The state shared between a `Future` and a `Promise`. -class FutureState[T] { +type FutureState[T] { # A spinlock used to restrict access to the state to a single thread/process # at a time. # @@ -122,7 +122,7 @@ class FutureState[T] { # - `Future.get` # - `Future.try_get` # - `Future.get_until` -class pub Future[T] { +type pub Future[T] { let @state: UInt64 # Returns a new `Future` along with its corresponding `Promise`. @@ -357,7 +357,7 @@ impl Drop for Future { # # A `Promise` is used to write a value to a future, such that a corresponding # `Future` can be resolved into this value. -class pub Promise[T] { +type pub Promise[T] { let @state: UInt64 # Sets the value of the `Future` that belongs to this `Promise` to the given @@ -422,7 +422,7 @@ impl Drop for Promise { } # The shared state of a channel. -class async ChannelState[T] { +type async ChannelState[T] { let @values: Deque[uni T] let @promises: Deque[Promise[uni T]] @@ -485,7 +485,7 @@ class async ChannelState[T] { # # Example().example(chan2) # ``` -class pub inline Channel[T] { +type pub inline Channel[T] { let @state: ChannelState[T] # Returns a new `Channel`. diff --git a/std/src/std/sys.inko b/std/src/std/sys.inko index fe8ff1e55..c0ee4c3b3 100644 --- a/std/src/std/sys.inko +++ b/std/src/std/sys.inko @@ -39,7 +39,7 @@ fn pub exit(status: Int) -> Never { } # A type that describes what to do with an input/output stream of a command. -class pub copy enum Stream { +type pub copy enum Stream { # A stream that should be redirected to the null device. case Null @@ -131,7 +131,7 @@ impl ToInt for Stream { # case _ -> {} # } # ``` -class pub Command { +type pub Command { # The path to the program to spawn. let pub @program: String @@ -241,7 +241,7 @@ class pub Command { } # The status of a process after it terminated. -class pub copy ExitStatus { +type pub copy ExitStatus { # The raw exit code. let @code: Int @@ -271,7 +271,7 @@ impl ToInt for ExitStatus { } # The standard input stream of a child process. -class pub inline Stdin { +type pub inline Stdin { let @fd: Int32 } @@ -302,7 +302,7 @@ impl Write for Stdin { } # The standard output stream of a child process. -class pub inline Stdout { +type pub inline Stdout { let @fd: Int32 } @@ -319,7 +319,7 @@ impl Read for Stdout { } # The standard error stream of a child process. -class pub inline Stderr { +type pub inline Stderr { let @fd: Int32 } @@ -336,7 +336,7 @@ impl Read for Stderr { } # A running or exited child OS process. -class pub ChildProcess { +type pub ChildProcess { # The ID of the child process. let @id: Int32 diff --git a/std/src/std/sys/freebsd/net.inko b/std/src/std/sys/freebsd/net.inko index 847ea47c2..e31526bbe 100644 --- a/std/src/std/sys/freebsd/net.inko +++ b/std/src/std/sys/freebsd/net.inko @@ -6,10 +6,10 @@ import std.libc.freebsd (self as sys) import std.net.ip (Ipv4Address, Ipv6Address) import std.sys.net -fn inline socket(domain: Int, type: Int, protocol: Int) -> Int32 { - let type = type | sys.SOCK_CLOEXEC | sys.SOCK_NONBLOCK +fn inline socket(domain: Int, kind: Int, protocol: Int) -> Int32 { + let kind = kind | sys.SOCK_CLOEXEC | sys.SOCK_NONBLOCK - libc.socket(domain as Int32, type as Int32, protocol as Int32) + libc.socket(domain as Int32, kind as Int32, protocol as Int32) } fn inline accept(fd: Int32) -> Int32 { diff --git a/std/src/std/sys/linux/net.inko b/std/src/std/sys/linux/net.inko index b2f473247..3af530c5e 100644 --- a/std/src/std/sys/linux/net.inko +++ b/std/src/std/sys/linux/net.inko @@ -6,10 +6,10 @@ import std.libc.linux (self as sys) import std.net.ip (Ipv4Address, Ipv6Address) import std.sys.net -fn inline socket(domain: Int, type: Int, protocol: Int) -> Int32 { - let type = type | sys.SOCK_CLOEXEC | sys.SOCK_NONBLOCK +fn inline socket(domain: Int, kind: Int, protocol: Int) -> Int32 { + let kind = kind | sys.SOCK_CLOEXEC | sys.SOCK_NONBLOCK - libc.socket(domain as Int32, type as Int32, protocol as Int32) + libc.socket(domain as Int32, kind as Int32, protocol as Int32) } fn inline accept(fd: Int32) -> Int32 { diff --git a/std/src/std/sys/mac/net.inko b/std/src/std/sys/mac/net.inko index 9592ff819..1f20e499f 100644 --- a/std/src/std/sys/mac/net.inko +++ b/std/src/std/sys/mac/net.inko @@ -8,8 +8,8 @@ import std.sys.net # macOS doesn't have `SOCK_CLOEXEC` and `SOCK_NONBLOCK`, so we need to use # `fcntl()` to make a socket non-blocking. -fn inline socket(domain: Int, type: Int, protocol: Int) -> Int32 { - let fd = libc.socket(domain as Int32, type as Int32, protocol as Int32) +fn inline socket(domain: Int, kind: Int, protocol: Int) -> Int32 { + let fd = libc.socket(domain as Int32, kind as Int32, protocol as Int32) if fd as Int == -1 { return -1 as Int32 } diff --git a/std/src/std/sys/net.inko b/std/src/std/sys/net.inko index f39825a58..afc7fad6b 100644 --- a/std/src/std/sys/net.inko +++ b/std/src/std/sys/net.inko @@ -16,7 +16,7 @@ fn extern inko_socket_poll( ) -> Bool # The raw socket type used by the runtime library. -class extern RawSocket { +type extern RawSocket { # The file descriptor of the socket. let @inner: Int32 diff --git a/std/src/std/sys/unix/fs.inko b/std/src/std/sys/unix/fs.inko index db42f79d7..04b86adde 100644 --- a/std/src/std/sys/unix/fs.inko +++ b/std/src/std/sys/unix/fs.inko @@ -217,7 +217,7 @@ fn copy_file_fallback( Result.Ok(copied) } -class ReadDirectory { +type ReadDirectory { let @stream: Pointer[UInt8] fn static new(path: String) -> Result[ReadDirectory, Error] { @@ -264,14 +264,14 @@ impl Iter[Result[(String, FileType), Error]] for ReadDirectory { } let name = String.from_pointer(name_ptr) - let type = match libc.dirent_type(entry) { + let typ = match libc.dirent_type(entry) { case libc.DT_DIR -> FileType.Directory case libc.DT_REG -> FileType.File case libc.DT_LNK -> FileType.SymbolicLink case _ -> FileType.Other } - return Option.Some(Result.Ok((name, type))) + return Option.Some(Result.Ok((name, typ))) } } } diff --git a/std/src/std/sys/unix/net.inko b/std/src/std/sys/unix/net.inko index 4812576d7..b589eb520 100644 --- a/std/src/std/sys/unix/net.inko +++ b/std/src/std/sys/unix/net.inko @@ -22,10 +22,10 @@ fn address_family_error(value: Int) -> Never { fn inline init_socket( socket: Pointer[net.RawSocket], domain: Int, - type: Int, + kind: Int, protocol: Int, ) -> Result[Nil, Error] { - let fd = sys.socket(domain, type, protocol) + let fd = sys.socket(domain, kind, protocol) if fd as Int == -1 { throw Error.last_os_error } diff --git a/std/src/std/sys/unix/sys.inko b/std/src/std/sys/unix/sys.inko index e7406b9d0..9991841b1 100644 --- a/std/src/std/sys/unix/sys.inko +++ b/std/src/std/sys/unix/sys.inko @@ -7,7 +7,7 @@ import std.sys (Stream) import std.sys.unix.fs import std.sys.unix.stdio -class FileActions { +type FileActions { let @raw: libc.PosixSpawnFileActions let @close: Array[Int32] @@ -86,7 +86,7 @@ impl Drop for FileActions { } } -class StringPointers { +type StringPointers { let @raw: Pointer[UInt64] fn static new(size: Int) -> StringPointers { @@ -257,7 +257,7 @@ fn exit(status: Int) -> Never { libc.exit(status as Int32) } -class ChildProcess { +type ChildProcess { let @id: Int32 let @stdin: Option[Int32] let @stdout: Option[Int32] diff --git a/std/src/std/sys/unix/time.inko b/std/src/std/sys/unix/time.inko index 6c18ac708..39a6a55aa 100644 --- a/std/src/std/sys/unix/time.inko +++ b/std/src/std/sys/unix/time.inko @@ -2,7 +2,7 @@ import std.libc fn extern inko_time_monotonic(state: Pointer[UInt8]) -> Int -class copy RawDateTime { +type copy RawDateTime { let @year: Int let @month: Int let @day: Int diff --git a/std/src/std/test.inko b/std/src/std/test.inko index 14ff45aaa..5343e03cc 100644 --- a/std/src/std/test.inko +++ b/std/src/std/test.inko @@ -94,7 +94,7 @@ fn unit_test_stack_frame -> debug.StackFrame { } # A single unit test. -class pub Test { +type pub Test { # The unique ID of this test. # # This ID can be used when you want to create some sort of resource unique to @@ -201,7 +201,7 @@ trait pub Reporter { } # A test reporter that prints results in a simple text based format. -class pub Plain[T: mut + Write] { +type pub Plain[T: mut + Write] { let @out: T let @tests: Int let @failed: Array[Test] @@ -283,7 +283,7 @@ ${indent} ${red('got:')} ${fail.got}', } } -class async Jobs { +type async Jobs { let @pending: Array[uni Test] fn async mut schedule(runner: Runner) { @@ -296,7 +296,7 @@ class async Jobs { } } -class async Runner { +type async Runner { let @jobs: Jobs let @output: Channel[uni Test] @@ -318,7 +318,7 @@ class async Runner { } # A test failure produced by an assertion. -class pub inline Failure { +type pub inline Failure { # A description of what happened. let pub @got: String @@ -344,7 +344,7 @@ class pub inline Failure { } # A type describing how to filter out tests. -class pub inline enum Filter { +type pub inline enum Filter { # Only run tests of which the description matches this pattern. case Pattern(String) @@ -404,7 +404,7 @@ impl Format for Filter { } # A child process to run as part of a unit test. -class pub Process { +type pub Process { let @cmd: Command let @stdin: String @@ -467,7 +467,7 @@ class pub Process { } # The output of a sub process. -class pub inline Output { +type pub inline Output { # The exit status of the process. let pub @status: ExitStatus @@ -479,7 +479,7 @@ class pub inline Output { } # A collection of tests to run. -class pub Tests { +type pub Tests { # The number of tests to run concurrently. # # This defaults to the number of CPU cores. diff --git a/std/src/std/time.inko b/std/src/std/time.inko index f13fe6091..363f151a0 100644 --- a/std/src/std/time.inko +++ b/std/src/std/time.inko @@ -132,7 +132,7 @@ fn negative_time_error(time: Int) -> Never { # is useful when performing arithmetic on `Duration` objects, as you won't have # to worry about overflows. It also lets you represent a duration that goes back # in time, i.e. "something that happened 5 seconds ago". -class pub copy Duration { +type pub copy Duration { let @nanos: Int # Creates a new `Duration` from the given number of seconds. @@ -318,7 +318,7 @@ impl Format for Duration { # A type representing a date in the Gregorian calendar, without a time and # timezone. -class pub copy Date { +type pub copy Date { # The year, month and day packed into a single set of bits. # # The layout is as follows (starting with the least significant bits): @@ -475,7 +475,7 @@ impl Format for Date { # A type that represents a point in time (hours, minutes and seconds) without a # specific associated date. -class pub copy Time { +type pub copy Time { # The hour, minute, second and sub seconds packed into a single set of bits. # # The layout is as follows (starting with the least significant bits): @@ -600,7 +600,7 @@ impl Format for Time { # If you want to measure the duration between two events, it's best to use the # `Instant` type, as it's not affected by external factors such as clock # adjustments and leap seconds. -class pub inline DateTime { +type pub inline DateTime { let @date: Date let @time: Time let @utc_offset: Int @@ -1383,7 +1383,7 @@ trait pub ToInstant { # is suspended. # # An `Instant` can never represent a negative time (e.g. -5). -class pub copy Instant { +type pub copy Instant { let @nanos: Int # Returns a new `Instant` representing the current time. diff --git a/std/src/std/tuple.inko b/std/src/std/tuple.inko index 87ec059f5..b6d0e0f8f 100644 --- a/std/src/std/tuple.inko +++ b/std/src/std/tuple.inko @@ -47,7 +47,7 @@ import std.fmt (Format, Formatter) import std.hash (Hash, Hasher) # A 1-ary tuple. -class builtin Tuple1[A] { +type builtin Tuple1[A] { let pub @0: A } @@ -76,7 +76,7 @@ impl Format for Tuple1 if A: Format { } # A 2-ary tuple. -class builtin Tuple2[A, B] { +type builtin Tuple2[A, B] { let pub @0: A let pub @1: B } @@ -107,7 +107,7 @@ impl Format for Tuple2 if A: Format, B: Format { } # A 3-ary tuple. -class builtin Tuple3[A, B, C] { +type builtin Tuple3[A, B, C] { let pub @0: A let pub @1: B let pub @2: C @@ -146,7 +146,7 @@ impl Format for Tuple3 if A: Format, B: Format, C: Format { } # A 4-ary tuple. -class builtin Tuple4[A, B, C, D] { +type builtin Tuple4[A, B, C, D] { let pub @0: A let pub @1: B let pub @2: C @@ -193,7 +193,7 @@ impl Format for Tuple4 if A: Format, B: Format, C: Format, D: Format { } # A 5-ary tuple. -class builtin Tuple5[A, B, C, D, E] { +type builtin Tuple5[A, B, C, D, E] { let pub @0: A let pub @1: B let pub @2: C @@ -249,7 +249,7 @@ impl Format for Tuple5 if A: Format, B: Format, C: Format, D: Format, E: Format } # A 6-ary tuple. -class builtin Tuple6[A, B, C, D, E, F] { +type builtin Tuple6[A, B, C, D, E, F] { let pub @0: A let pub @1: B let pub @2: C @@ -325,7 +325,7 @@ if } # A 7-ary tuple. -class builtin Tuple7[A, B, C, D, E, F, G] { +type builtin Tuple7[A, B, C, D, E, F, G] { let pub @0: A let pub @1: B let pub @2: C @@ -417,7 +417,7 @@ if } # A 8-ary tuple. -class builtin Tuple8[A, B, C, D, E, F, G, H] { +type builtin Tuple8[A, B, C, D, E, F, G, H] { let pub @0: A let pub @1: B let pub @2: C diff --git a/std/test/compiler/test_diagnostics.inko b/std/test/compiler/test_diagnostics.inko index a054d5396..0cc7039be 100644 --- a/std/test/compiler/test_diagnostics.inko +++ b/std/test/compiler/test_diagnostics.inko @@ -116,7 +116,7 @@ fn location(map: ref Map[String, Json], key: String) -> Result[Int, String] { throw 'the "${key}" field must be an array of two integers' } -class Parser { +type Parser { let @bytes: ref ByteArray let @index: Int @@ -192,7 +192,7 @@ class Parser { } } -class Diagnostic { +type Diagnostic { let @id: String let @file: String let @level: String diff --git a/std/test/compiler/test_drop.inko b/std/test/compiler/test_drop.inko index d3557cf3b..bf1f66145 100644 --- a/std/test/compiler/test_drop.inko +++ b/std/test/compiler/test_drop.inko @@ -1,7 +1,7 @@ import std.drop (Drop) import std.test (Tests) -class Value { +type Value { let @dropped: Int fn static new -> Value { @@ -9,7 +9,7 @@ class Value { } } -class ValueRef { +type ValueRef { let @value: mut Value fn static new(value: mut Value) -> ValueRef { @@ -23,7 +23,7 @@ impl Drop for ValueRef { } } -class Box { +type Box { let @value: ValueRef fn mut update(value: ValueRef) { @@ -31,15 +31,15 @@ class Box { } } -class CyclicClass { +type CyclicClass { let @backref: Backref[CyclicClass] } -class Backref[T] { +type Backref[T] { let @target: Option[ref T] } -class enum CyclicEnum { +type enum CyclicEnum { case Backref(Backref[CyclicEnum]) } @@ -76,7 +76,7 @@ fn pub tests(t: mut Tests) { t.equal(val.dropped, 1) }) - t.no_panic('Dropping a class with a cyclic reference', fn { + t.no_panic('Dropping a type with a cyclic reference', fn { let val_ref = Backref(Option.None) let val = CyclicClass(val_ref) diff --git a/std/test/compiler/test_extern_types.inko b/std/test/compiler/test_extern_types.inko index c987dabf4..28c167411 100644 --- a/std/test/compiler/test_extern_types.inko +++ b/std/test/compiler/test_extern_types.inko @@ -1,6 +1,6 @@ import std.test (Tests) -class extern Example { +type extern Example { let @a: Int let @b: Int } diff --git a/std/test/compiler/test_ffi.inko b/std/test/compiler/test_ffi.inko index b3a175a04..77267f6f0 100644 --- a/std/test/compiler/test_ffi.inko +++ b/std/test/compiler/test_ffi.inko @@ -1,12 +1,12 @@ import std.test (Tests) -class extern Foo { +type extern Foo { let @foo: Int32 let @bar: Int32 let @baz: Pointer[Foo] } -class Bar { +type Bar { let @value: Int64 fn mut ptr1 -> Pointer[Int64] { diff --git a/std/test/compiler/test_inline_types.inko b/std/test/compiler/test_inline_types.inko index 9b96a5771..2aad7d870 100644 --- a/std/test/compiler/test_inline_types.inko +++ b/std/test/compiler/test_inline_types.inko @@ -1,7 +1,7 @@ import std.string (ToString) import std.test (Tests) -class copy Example[A, B] { +type copy Example[A, B] { let @a: A let @b: B } @@ -16,7 +16,7 @@ fn to_string[T: ToString](value: T) -> String { value.to_string } -class copy enum Enum[A, B] { +type copy enum Enum[A, B] { case A(Example[A, B]) case B(Int) } diff --git a/std/test/compiler/test_pattern_matching.inko b/std/test/compiler/test_pattern_matching.inko index b4b7e1643..6820f2fac 100644 --- a/std/test/compiler/test_pattern_matching.inko +++ b/std/test/compiler/test_pattern_matching.inko @@ -1,25 +1,25 @@ import std.drop (drop) import std.test (Tests) -class enum Letter { +type enum Letter { case A case B case C } -class enum State { +type enum State { case Closed case Button(State) } -class Dummy {} +type Dummy {} -class enum Transition { +type enum Transition { case Empty(Dummy) case Split(Transition) } -class Person { +type Person { let @name: String } diff --git a/std/test/std/net/test_socket.inko b/std/test/std/net/test_socket.inko index a742d67ab..ca58701e0 100644 --- a/std/test/std/net/test_socket.inko +++ b/std/test/std/net/test_socket.inko @@ -13,7 +13,7 @@ import std.sys.net (NO_DEADLINE) import std.test (Tests) import std.time (Duration) -class SocketPath { +type SocketPath { let @path: Path fn static pair(id: Int) -> (SocketPath, SocketPath) { diff --git a/std/test/std/net/test_tls.inko b/std/test/std/net/test_tls.inko index 708f56378..0e93c53e2 100644 --- a/std/test/std/net/test_tls.inko +++ b/std/test/std/net/test_tls.inko @@ -110,7 +110,7 @@ OzLLhs1TsfEwTGLiapfCFXO610FVPsVynY4Ylr6LRodiFCzIlx2k9O3p6GRAkKy7 -----END CERTIFICATE----- ' -class async DummyServer { +type async DummyServer { let @socket: TcpServer let @config: ServerConfig @@ -156,7 +156,7 @@ class async DummyServer { } } -class async DummyClient { +type async DummyClient { fn async connect( port: Int, output: uni Promise[uni Result[Client[TcpClient], String]], diff --git a/std/test/std/test_array.inko b/std/test/std/test_array.inko index de55fa555..8dbf37959 100644 --- a/std/test/std/test_array.inko +++ b/std/test/std/test_array.inko @@ -4,7 +4,7 @@ import std.drop (Drop, drop) import std.fmt (fmt) import std.test (Tests) -class Person { +type Person { let @name: String let @age: Int } @@ -15,7 +15,7 @@ impl Compare[Person] for Person { } } -class Counter { +type Counter { let @value: Int fn static new -> Counter { @@ -23,7 +23,7 @@ class Counter { } } -class TrackDrop { +type TrackDrop { let @counter: mut Counter fn static new(counter: mut Counter) -> TrackDrop { diff --git a/std/test/std/test_cmp.inko b/std/test/std/test_cmp.inko index 03a51db1b..4fd1e89e5 100644 --- a/std/test/std/test_cmp.inko +++ b/std/test/std/test_cmp.inko @@ -2,7 +2,7 @@ import std.cmp (Compare, Equal, Ordering, max, min) import std.fmt (fmt) import std.test (Tests) -class enum Letter { +type enum Letter { case A case B } diff --git a/std/test/std/test_csv.inko b/std/test/std/test_csv.inko index 065c4c105..986dbee8d 100644 --- a/std/test/std/test_csv.inko +++ b/std/test/std/test_csv.inko @@ -3,7 +3,7 @@ import std.fmt (fmt) import std.io (Buffer, Error as IoError, Write) import std.test (Tests) -class Output { +type Output { let @buffer: ByteArray let @flushed: Bool diff --git a/std/test/std/test_io.inko b/std/test/std/test_io.inko index ac73faed8..0e15a5df1 100644 --- a/std/test/std/test_io.inko +++ b/std/test/std/test_io.inko @@ -7,7 +7,7 @@ import std.io ( import std.libc import std.test (Tests) -class Reader { +type Reader { let @index: Int let @bytes: ByteArray @@ -37,7 +37,7 @@ impl Read for Reader { } } -class SingleByteReader { +type SingleByteReader { let @index: Int let @bytes: ByteArray @@ -59,7 +59,7 @@ impl Read for SingleByteReader { } } -class ErrorReader {} +type ErrorReader {} impl Read for ErrorReader { fn pub mut read(into: mut ByteArray, size: Int) -> Result[Int, Error] { @@ -67,7 +67,7 @@ impl Read for ErrorReader { } } -class Writer { +type Writer { let @buffer: ByteArray fn static new -> Writer { diff --git a/std/test/std/test_sync.inko b/std/test/std/test_sync.inko index 87a70906c..842ac5d82 100644 --- a/std/test/std/test_sync.inko +++ b/std/test/std/test_sync.inko @@ -4,7 +4,7 @@ import std.sync (Channel, Future, Promise) import std.test (Tests) import std.time (Duration) -class async AsyncWriter { +type async AsyncWriter { fn async write(writer: uni Promise[Int]) { # This doesn't strictly guarantee the reader is in fact waiting, but it's # the closest we can get to that. diff --git a/std/test/std/test_test.inko b/std/test/std/test_test.inko index 05d16d4eb..5578c0f8d 100644 --- a/std/test/std/test_test.inko +++ b/std/test/std/test_test.inko @@ -6,7 +6,7 @@ import std.sys import std.test (Filter, Plain, Test, Tests) import std.time (Duration) -class Buffer { +type Buffer { let @bytes: mut ByteArray fn static new(bytes: mut ByteArray) -> Buffer { diff --git a/types/src/check.rs b/types/src/check.rs index ecf75e045..e78882fc1 100644 --- a/types/src/check.rs +++ b/types/src/check.rs @@ -1,6 +1,6 @@ use crate::{ - Arguments, ClassInstance, Database, ForeignType, MethodId, Ownership, - TraitInstance, TypeArguments, TypeBounds, TypeId, TypeParameterId, + Arguments, Database, ForeignType, MethodId, Ownership, TraitInstance, + TypeArguments, TypeBounds, TypeEnum, TypeInstance, TypeParameterId, TypePlaceholderId, TypeRef, FLOAT_ID, INT_ID, }; use std::collections::HashSet; @@ -318,9 +318,9 @@ impl<'a> TypeChecker<'a> { }) } - pub fn class_compatible_with_bound( + pub fn type_compatible_with_bound( &mut self, - left: ClassInstance, + left: TypeInstance, bound: TypeParameterId, ) -> bool { if bound.is_mutable(self.db) @@ -336,7 +336,7 @@ impl<'a> TypeChecker<'a> { bound .requirements(self.db) .into_iter() - .all(|req| self.class_implements_trait(left, req)) + .all(|req| self.type_implements_trait(left, req)) } fn check_type_ref( @@ -357,7 +357,7 @@ impl<'a> TypeChecker<'a> { let allow_never = rules.allow_never; // We only apply the "infer as rigid" rule to the type on the left, - // otherwise we may end up comparing e.g. a class instance to the rigid + // otherwise we may end up comparing e.g. a type instance to the rigid // type parameter on the right, which would always fail. // // This is OK because in practise, Any() only shows up on the left in @@ -433,8 +433,10 @@ impl<'a> TypeChecker<'a> { ) } TypeRef::Pointer(_) if rules.kind.is_cast() => match left_id { - TypeId::ClassInstance(ins) => ins.instance_of().0 == INT_ID, - TypeId::Foreign(ForeignType::Int(_, _)) => true, + TypeEnum::TypeInstance(ins) => { + ins.instance_of().0 == INT_ID + } + TypeEnum::Foreign(ForeignType::Int(_, _)) => true, _ => false, }, TypeRef::Error => true, @@ -489,7 +491,7 @@ impl<'a> TypeChecker<'a> { _ => false, }, TypeRef::Ref(left_id) => match right { - TypeRef::Any(TypeId::TypeParameter(pid)) + TypeRef::Any(TypeEnum::TypeParameter(pid)) if pid.is_mutable(self.db) && !is_val => { false @@ -609,7 +611,7 @@ impl<'a> TypeChecker<'a> { } (Uni, TypeRef::Ref(_) | TypeRef::Mut(_)) => rval, (Uni, TypeRef::Uni(_)) => true, - (Ref, TypeRef::Any(TypeId::TypeParameter(pid))) => { + (Ref, TypeRef::Any(TypeEnum::TypeParameter(pid))) => { !pid.is_mutable(self.db) || rval } (Ref, TypeRef::Any(_)) => !rules.kind.is_return(), @@ -636,10 +638,10 @@ impl<'a> TypeChecker<'a> { rules.kind.is_cast() || self.check_type_id(left_id, right_id, env, rules) } - TypeRef::Owned(TypeId::Foreign(ForeignType::Int(_, _))) => { + TypeRef::Owned(TypeEnum::Foreign(ForeignType::Int(_, _))) => { rules.kind.is_cast() } - TypeRef::Owned(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) => { rules.kind.is_cast() && ins.instance_of().0 == INT_ID } TypeRef::Placeholder(right_id) => { @@ -660,8 +662,8 @@ impl<'a> TypeChecker<'a> { fn check_type_id( &mut self, - left_id: TypeId, - right_id: TypeId, + left_id: TypeEnum, + right_id: TypeEnum, env: &mut Environment, mut rules: Rules, ) -> bool { @@ -672,15 +674,15 @@ impl<'a> TypeChecker<'a> { } match left_id { - TypeId::Class(_) | TypeId::Trait(_) | TypeId::Module(_) => { + TypeEnum::Type(_) | TypeEnum::Trait(_) | TypeEnum::Module(_) => { // Classes, traits and modules themselves aren't treated as // types and thus can't be passed around, mostly because this // just isn't useful. To further reinforce this, these types // aren't compatible with anything. false } - TypeId::ClassInstance(lhs) => match right_id { - TypeId::ClassInstance(rhs) => { + TypeEnum::TypeInstance(lhs) => match right_id { + TypeEnum::TypeInstance(rhs) => { if lhs.instance_of != rhs.instance_of { if rules.kind.is_cast() && lhs.instance_of.is_numeric() @@ -710,17 +712,17 @@ impl<'a> TypeChecker<'a> { }, ) } - TypeId::TraitInstance(rhs) => { + TypeEnum::TraitInstance(rhs) => { if rules.kind.is_cast() && !lhs.instance_of().allow_cast_to_trait(self.db) { return false; } - self.check_class_with_trait(lhs, rhs, env, trait_rules) + self.check_type_with_trait(lhs, rhs, env, trait_rules) } - TypeId::TypeParameter(_) if rules.kind.is_cast() => false, - TypeId::TypeParameter(rhs) => { + TypeEnum::TypeParameter(_) if rules.kind.is_cast() => false, + TypeEnum::TypeParameter(rhs) => { if rhs.is_copy(self.db) && !lhs.instance_of().is_copy_type(self.db) { @@ -729,9 +731,9 @@ impl<'a> TypeChecker<'a> { rhs.requirements(self.db).into_iter().all(|req| { // One-time subtyping is enabled because we want to - // allow passing classes to type parameters with + // allow passing types to type parameters with // requirements. - self.check_class_with_trait( + self.check_type_with_trait( lhs, req, env, @@ -739,37 +741,37 @@ impl<'a> TypeChecker<'a> { ) }) } - TypeId::Foreign(_) => { + TypeEnum::Foreign(_) => { rules.kind.is_cast() && lhs.instance_of().allow_cast_to_foreign(self.db) } _ => false, }, - TypeId::TraitInstance(lhs) => match right_id { - TypeId::TraitInstance(rhs) => { + TypeEnum::TraitInstance(lhs) => match right_id { + TypeEnum::TraitInstance(rhs) => { self.check_traits(lhs, rhs, env, rules) } - TypeId::TypeParameter(_) if rules.kind.is_cast() => false, - TypeId::TypeParameter(rhs) if rhs.is_copy(self.db) => false, - TypeId::TypeParameter(rhs) => rhs + TypeEnum::TypeParameter(_) if rules.kind.is_cast() => false, + TypeEnum::TypeParameter(rhs) if rhs.is_copy(self.db) => false, + TypeEnum::TypeParameter(rhs) => rhs .requirements(self.db) .into_iter() .all(|req| self.check_traits(lhs, req, env, rules)), _ => false, }, - TypeId::TypeParameter(lhs) => match right_id { - TypeId::TypeParameter(rhs) => { + TypeEnum::TypeParameter(lhs) => match right_id { + TypeEnum::TypeParameter(rhs) => { self.check_parameters(lhs, rhs, env, rules) } - TypeId::Foreign(_) => rules.kind.is_cast(), + TypeEnum::Foreign(_) => rules.kind.is_cast(), _ => false, }, - TypeId::RigidTypeParameter(lhs) - | TypeId::AtomicTypeParameter(lhs) => { + TypeEnum::RigidTypeParameter(lhs) + | TypeEnum::AtomicTypeParameter(lhs) => { self.check_rigid_with_type_id(lhs, right_id, env, rules) } - TypeId::Closure(lhs) => match right_id { - TypeId::Closure(rhs) => { + TypeEnum::Closure(lhs) => match right_id { + TypeEnum::Closure(rhs) => { let lhs_obj = lhs.get(self.db); let rhs_obj = rhs.get(self.db); @@ -786,7 +788,7 @@ impl<'a> TypeChecker<'a> { rules, ) } - TypeId::TypeParameter(rhs) + TypeEnum::TypeParameter(rhs) if rhs.requirements(self.db).is_empty() => { // Closures can't implement traits, so they're only @@ -796,11 +798,11 @@ impl<'a> TypeChecker<'a> { } _ => false, }, - TypeId::Foreign(ForeignType::Int(lsize, lsigned)) => { + TypeEnum::Foreign(ForeignType::Int(lsize, lsigned)) => { if rules.kind.is_cast() { match right_id { - TypeId::Foreign(_) => true, - TypeId::ClassInstance(ins) => { + TypeEnum::Foreign(_) => true, + TypeEnum::TypeInstance(ins) => { // 64-bits integers can be cast to Inko objects, as // this is needed when interfacing with C. matches!(ins.instance_of().0, INT_ID | FLOAT_ID) @@ -810,25 +812,25 @@ impl<'a> TypeChecker<'a> { } } else { match right_id { - TypeId::Foreign(ForeignType::Int(rsize, rsigned)) => { + TypeEnum::Foreign(ForeignType::Int(rsize, rsigned)) => { lsize == rsize && lsigned == rsigned } _ => false, } } } - TypeId::Foreign(ForeignType::Float(lsize)) => { + TypeEnum::Foreign(ForeignType::Float(lsize)) => { if rules.kind.is_cast() { match right_id { - TypeId::Foreign(_) => true, - TypeId::ClassInstance(ins) => { + TypeEnum::Foreign(_) => true, + TypeEnum::TypeInstance(ins) => { matches!(ins.instance_of().0, INT_ID | FLOAT_ID) } _ => false, } } else { match right_id { - TypeId::Foreign(ForeignType::Float(rsize)) => { + TypeEnum::Foreign(ForeignType::Float(rsize)) => { lsize == rsize } _ => false, @@ -841,13 +843,13 @@ impl<'a> TypeChecker<'a> { fn check_rigid_with_type_id( &mut self, left: TypeParameterId, - right: TypeId, + right: TypeEnum, env: &mut Environment, rules: Rules, ) -> bool { match right { - TypeId::RigidTypeParameter(rhs) => left == rhs, - TypeId::TypeParameter(rhs) => { + TypeEnum::RigidTypeParameter(rhs) => left == rhs, + TypeEnum::TypeParameter(rhs) => { if left == rhs { return true; } @@ -860,7 +862,7 @@ impl<'a> TypeChecker<'a> { self.check_parameter_with_trait(left, req, env, rules) }) } - TypeId::Foreign(_) => rules.kind.is_cast(), + TypeEnum::Foreign(_) => rules.kind.is_cast(), _ => false, } } @@ -868,7 +870,7 @@ impl<'a> TypeChecker<'a> { fn check_type_id_with_placeholder( &mut self, left: TypeRef, - left_id: TypeId, + left_id: TypeEnum, original_right: TypeRef, placeholder: TypePlaceholderId, env: &mut Environment, @@ -888,8 +890,8 @@ impl<'a> TypeChecker<'a> { // sense. We don't use Owned() because Owned() isn't compatible with // Any() when using type parameters, which in turn would disallow // certain forms of type inference. - let assign = if let TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) = left_id + let assign = if let TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) = left_id { TypeRef::Any(left_id) } else { @@ -924,13 +926,14 @@ impl<'a> TypeChecker<'a> { // sub-typing through traits. let rules = rules.with_one_time_subtyping(); let res = match left_id { - TypeId::ClassInstance(lhs) => reqs + TypeEnum::TypeInstance(lhs) => reqs .into_iter() - .all(|req| self.check_class_with_trait(lhs, req, env, rules)), - TypeId::TraitInstance(lhs) => reqs + .all(|req| self.check_type_with_trait(lhs, req, env, rules)), + TypeEnum::TraitInstance(lhs) => reqs .into_iter() .all(|req| self.check_traits(lhs, req, env, rules)), - TypeId::TypeParameter(lhs) | TypeId::RigidTypeParameter(lhs) => { + TypeEnum::TypeParameter(lhs) + | TypeEnum::RigidTypeParameter(lhs) => { reqs.into_iter().all(|req| { self.check_parameter_with_trait(lhs, req, env, rules) }) @@ -948,24 +951,24 @@ impl<'a> TypeChecker<'a> { res } - pub fn class_implements_trait( + pub fn type_implements_trait( &mut self, - left: ClassInstance, + left: TypeInstance, right: TraitInstance, ) -> bool { let mut env = Environment::new( - TypeArguments::for_class(self.db, left), + TypeArguments::for_type(self.db, left), TypeArguments::for_trait(self.db, right), ); let rules = Rules::new().with_one_time_subtyping(); - self.check_class_with_trait(left, right, &mut env, rules) + self.check_type_with_trait(left, right, &mut env, rules) } - fn check_class_with_trait( + fn check_type_with_trait( &mut self, - left: ClassInstance, + left: TypeInstance, right: TraitInstance, env: &mut Environment, mut rules: Rules, @@ -978,7 +981,7 @@ impl<'a> TypeChecker<'a> { // fn ==(other: T) -> Bool // } // - // class Thing {} + // type Thing {} // // impl Equal[uni Thing] for Thing { // fn ==(other: uni Thing) -> Bool { @@ -1011,7 +1014,7 @@ impl<'a> TypeChecker<'a> { if left.instance_of.is_generic(self.db) { // The implemented trait may refer to type parameters of the - // implementing class, so we need to expose those using a new scope. + // implementing type, so we need to expose those using a new scope. let mut sub_scope = env.clone(); left.type_arguments(self.db) @@ -1041,14 +1044,14 @@ impl<'a> TypeChecker<'a> { | TypeRef::UniRef(id) | TypeRef::UniMut(id) | TypeRef::Any(id) => match id { - TypeId::ClassInstance(lhs) => { - self.check_class_with_trait(lhs, right, env, rules) + TypeEnum::TypeInstance(lhs) => { + self.check_type_with_trait(lhs, right, env, rules) } - TypeId::TraitInstance(lhs) => { + TypeEnum::TraitInstance(lhs) => { self.check_traits(lhs, right, env, rules) } - TypeId::TypeParameter(lhs) - | TypeId::RigidTypeParameter(lhs) => { + TypeEnum::TypeParameter(lhs) + | TypeEnum::RigidTypeParameter(lhs) => { self.check_parameter_with_trait(lhs, right, env, rules) } _ => false, @@ -1108,7 +1111,7 @@ impl<'a> TypeChecker<'a> { env: &mut Environment, mut rules: Rules, ) -> bool { - // Similar to when checking classes with traits, we have to be more + // Similar to when checking types with traits, we have to be more // strict about comparing `uni T` values with `T` values. rules.uni_compatible_with_owned = false; @@ -1176,7 +1179,7 @@ impl<'a> TypeChecker<'a> { rules: Rules, ) -> TypeRef { let result = match typ { - TypeRef::Owned(TypeId::TypeParameter(id)) => { + TypeRef::Owned(TypeEnum::TypeParameter(id)) => { // Owned type parameters should only be assigned owned types. // This check ensures that if we have e.g. `move T` and // `T = ref User`, we don't turn that into `User`, as this could @@ -1187,7 +1190,7 @@ impl<'a> TypeChecker<'a> { // fn foo -> move T // } // - // class Thing {} + // type Thing {} // // impl Foo[ref Thing] for Thing { // fn foo -> ref Thing { @@ -1213,19 +1216,19 @@ impl<'a> TypeChecker<'a> { _ => TypeRef::Unknown, } } - TypeRef::Uni(TypeId::TypeParameter(id)) => self + TypeRef::Uni(TypeEnum::TypeParameter(id)) => self .resolve_type_parameter(typ, id, arguments, rules) .as_uni(self.db), - TypeRef::Any(TypeId::TypeParameter(id)) => { + TypeRef::Any(TypeEnum::TypeParameter(id)) => { self.resolve_type_parameter(typ, id, arguments, rules) } - TypeRef::Ref(TypeId::TypeParameter(id)) => self + TypeRef::Ref(TypeEnum::TypeParameter(id)) => self .resolve_type_parameter(typ, id, arguments, rules) .as_ref(self.db), - TypeRef::Mut(TypeId::TypeParameter(id)) => self + TypeRef::Mut(TypeEnum::TypeParameter(id)) => self .resolve_type_parameter(typ, id, arguments, rules) .as_mut(self.db), - TypeRef::Pointer(TypeId::TypeParameter(id)) => self + TypeRef::Pointer(TypeEnum::TypeParameter(id)) => self .resolve_type_parameter(typ, id, arguments, rules) .as_pointer(self.db), TypeRef::Placeholder(id) => id @@ -1266,14 +1269,13 @@ mod tests { use crate::test::{ any, closure, generic_instance_id, generic_trait_instance, generic_trait_instance_id, immutable, immutable_uni, implement, - instance, mutable, mutable_uni, new_class, new_extern_class, - new_parameter, new_trait, owned, parameter, placeholder, pointer, - rigid, trait_instance, trait_instance_id, type_arguments, type_bounds, - uni, + instance, mutable, mutable_uni, new_extern_type, new_parameter, + new_trait, new_type, owned, parameter, placeholder, pointer, rigid, + trait_instance, trait_instance_id, type_arguments, type_bounds, uni, }; use crate::{ - Block, Class, ClassId, ClassKind, Closure, Location, ModuleId, Sign, - TraitImplementation, TypePlaceholder, Visibility, + Block, Closure, Location, ModuleId, Sign, TraitImplementation, Type, + TypeId, TypeKind, TypePlaceholder, Visibility, }; #[track_caller] @@ -1366,11 +1368,11 @@ mod tests { } #[test] - fn test_owned_class_instance() { + fn test_owned_type_instance() { let mut db = Database::new(); - let foo = new_class(&mut db, "Foo"); - let bar = new_class(&mut db, "Bar"); - let int = ClassId::int(); + let foo = new_type(&mut db, "Foo"); + let bar = new_type(&mut db, "Bar"); + let int = TypeId::int(); let var1 = TypePlaceholder::alloc(&mut db, None); let to_string = new_trait(&mut db, "ToString"); let p1 = new_parameter(&mut db, "T"); @@ -1446,10 +1448,10 @@ mod tests { } #[test] - fn test_extern_class_instance() { + fn test_extern_type_instance() { let mut db = Database::new(); - let foo = new_extern_class(&mut db, "Foo"); - let bar = new_extern_class(&mut db, "Bar"); + let foo = new_extern_type(&mut db, "Foo"); + let bar = new_extern_type(&mut db, "Bar"); let param = new_parameter(&mut db, "T"); check_ok(&db, owned(instance(foo)), owned(instance(foo))); @@ -1460,10 +1462,10 @@ mod tests { } #[test] - fn test_owned_generic_class_instance() { + fn test_owned_generic_type_instance() { let mut db = Database::new(); - let array = new_class(&mut db, "Array"); - let thing = new_class(&mut db, "Thing"); + let array = new_type(&mut db, "Array"); + let thing = new_type(&mut db, "Thing"); let to_string = new_trait(&mut db, "ToString"); let length = new_trait(&mut db, "Length"); let equal = new_trait(&mut db, "Equal"); @@ -1594,11 +1596,11 @@ mod tests { } #[test] - fn test_uni_class_instance() { + fn test_uni_type_instance() { let mut db = Database::new(); - let foo = new_class(&mut db, "Foo"); - let bar = new_class(&mut db, "Bar"); - let int = ClassId::int(); + let foo = new_type(&mut db, "Foo"); + let bar = new_type(&mut db, "Bar"); + let int = TypeId::int(); let var1 = TypePlaceholder::alloc(&mut db, None); let to_string = new_trait(&mut db, "ToString"); let param = new_parameter(&mut db, "T"); @@ -1640,10 +1642,10 @@ mod tests { } #[test] - fn test_uni_generic_class_instance() { + fn test_uni_generic_type_instance() { let mut db = Database::new(); - let array = new_class(&mut db, "Array"); - let thing = new_class(&mut db, "Thing"); + let array = new_type(&mut db, "Array"); + let thing = new_type(&mut db, "Thing"); let to_string = new_trait(&mut db, "ToString"); let length = new_trait(&mut db, "Length"); let equal = new_trait(&mut db, "Equal"); @@ -1792,8 +1794,8 @@ mod tests { #[test] fn test_ref() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); - let int = ClassId::int(); + let thing = new_type(&mut db, "Thing"); + let int = TypeId::int(); let var = TypePlaceholder::alloc(&mut db, None); let param = new_parameter(&mut db, "T"); let mutable_var = TypePlaceholder::alloc(&mut db, Some(param)); @@ -1825,8 +1827,8 @@ mod tests { #[test] fn test_mut() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); - let int = ClassId::int(); + let thing = new_type(&mut db, "Thing"); + let int = TypeId::int(); let var = TypePlaceholder::alloc(&mut db, None); check_ok(&db, mutable(instance(thing)), immutable(instance(thing))); @@ -1870,7 +1872,7 @@ mod tests { #[test] fn test_ref_instance_with_ref_type_parameter() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let var = TypePlaceholder::alloc(&mut db, None); let mut env = Environment::new( @@ -1891,7 +1893,7 @@ mod tests { #[test] fn test_owned_instance_with_pointer_type_parameter() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let var = TypePlaceholder::alloc(&mut db, None); let mut env = Environment::new( @@ -1911,7 +1913,7 @@ mod tests { #[test] fn test_pointer_instance_with_pointer_type_parameter() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let var = TypePlaceholder::alloc(&mut db, None); let mut env = Environment::new( @@ -1932,7 +1934,7 @@ mod tests { #[test] fn test_ref_instance_with_type_parameter_with_ref_ownership() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let var = TypePlaceholder::alloc(&mut db, None).as_ref(); let mut env = Environment::new( @@ -1953,7 +1955,7 @@ mod tests { #[test] fn test_pointer_instance_with_type_parameter_with_pointer_ownership() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let var = TypePlaceholder::alloc(&mut db, None).as_pointer(); let mut env = Environment::new( @@ -1976,12 +1978,12 @@ mod tests { let mut db = Database::new(); let param = new_parameter(&mut db, "T"); let to_foo = new_trait(&mut db, "ToFoo"); - let array = ClassId::array(); + let array = TypeId::array(); let var = TypePlaceholder::alloc(&mut db, Some(param)); array.new_type_parameter(&mut db, "T".to_string()); param.add_requirements(&mut db, vec![trait_instance(to_foo)]); - ClassId::int().add_trait_implementation( + TypeId::int().add_trait_implementation( &mut db, TraitImplementation { instance: trait_instance(to_foo), @@ -2004,7 +2006,7 @@ mod tests { #[test] fn test_ref_uni() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let var = TypePlaceholder::alloc(&mut db, None); check_ok( @@ -2030,7 +2032,7 @@ mod tests { #[test] fn test_mut_uni() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let var = TypePlaceholder::alloc(&mut db, None); check_ok( @@ -2065,8 +2067,8 @@ mod tests { #[test] fn test_placeholder_with_ownership() { let mut db = Database::new(); - let int = ClassId::int(); - let thing = new_class(&mut db, "Thing"); + let int = TypeId::int(); + let thing = new_type(&mut db, "Thing"); let any_var = TypePlaceholder::alloc(&mut db, None); let owned_var = TypePlaceholder::alloc(&mut db, None).as_owned(); let ref_var = TypePlaceholder::alloc(&mut db, None).as_ref(); @@ -2120,8 +2122,8 @@ mod tests { param2.set_mutable(&mut db); let p1 = TypePlaceholder::alloc(&mut db, None); - let int = ClassId::int(); - let thing = new_class(&mut db, "Thing"); + let int = TypeId::int(); + let thing = new_type(&mut db, "Thing"); check_ok_placeholder(&db, p1, owned(instance(int))); check_ok_placeholder(&db, p1.as_owned(), owned(instance(int))); @@ -2154,7 +2156,7 @@ mod tests { let mut db = Database::new(); let var1 = TypePlaceholder::alloc(&mut db, None); let var2 = TypePlaceholder::alloc(&mut db, None); - let int_ptr = pointer(instance(ClassId::int())); + let int_ptr = pointer(instance(TypeId::int())); check_ok(&db, placeholder(var1), int_ptr); check_ok(&db, int_ptr, placeholder(var2)); @@ -2165,10 +2167,10 @@ mod tests { #[test] fn test_struct_with_placeholder() { let mut db = Database::new(); - let class = new_extern_class(&mut db, "A"); + let typ = new_extern_type(&mut db, "A"); let var = TypePlaceholder::alloc(&mut db, None); - check_ok(&db, owned(instance(class)), placeholder(var)); + check_ok(&db, owned(instance(typ)), placeholder(var)); } #[test] @@ -2183,11 +2185,11 @@ mod tests { } #[test] - fn test_class_with_trait() { + fn test_type_with_trait() { let mut db = Database::new(); let animal = new_trait(&mut db, "Animal"); - let cat = new_class(&mut db, "Cat"); - let array = ClassId::array(); + let cat = new_type(&mut db, "Cat"); + let array = TypeId::array(); array.new_type_parameter(&mut db, "T".to_string()); implement(&mut db, trait_instance(animal), cat); @@ -2277,7 +2279,7 @@ mod tests { fn test_generic_traits() { let mut db = Database::new(); let equal = new_trait(&mut db, "Equal"); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); equal.new_type_parameter(&mut db, "T".to_string()); @@ -2404,7 +2406,7 @@ mod tests { fn test_type_parameter_ref_assigned_to_owned() { let mut db = Database::new(); let param = new_parameter(&mut db, "A"); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let args = type_arguments(vec![(param, owned(instance(thing)))]); let mut env = Environment::new(args.clone(), args); let res = TypeChecker::new(&db).run( @@ -2554,7 +2556,7 @@ mod tests { #[test] fn test_recursive_type() { let mut db = Database::new(); - let array = ClassId::array(); + let array = TypeId::array(); let var = TypePlaceholder::alloc(&mut db, None); array.new_type_parameter(&mut db, "T".to_string()); @@ -2572,8 +2574,8 @@ mod tests { #[test] fn test_mutable_bounds() { let mut db = Database::new(); - let array = ClassId::array(); - let thing = new_class(&mut db, "Thing"); + let array = TypeId::array(); + let thing = new_type(&mut db, "Thing"); let update = new_trait(&mut db, "Update"); let array_param = array.new_type_parameter(&mut db, "T".to_string()); let array_bounds = new_parameter(&mut db, "T"); @@ -2612,9 +2614,9 @@ mod tests { #[test] fn test_copy_bounds() { let mut db = Database::new(); - let array = ClassId::array(); - let heap = new_class(&mut db, "Heap"); - let stack = new_class(&mut db, "Stack"); + let array = TypeId::array(); + let heap = new_type(&mut db, "Heap"); + let stack = new_type(&mut db, "Stack"); stack.set_copy_storage(&mut db); @@ -2650,15 +2652,15 @@ mod tests { } #[test] - fn test_array_of_generic_classes_with_traits() { + fn test_array_of_generic_types_with_traits() { let mut db = Database::new(); let iter = new_trait(&mut db, "Iter"); - let array = ClassId::array(); + let array = TypeId::array(); array.new_type_parameter(&mut db, "ArrayT".to_string()); iter.new_type_parameter(&mut db, "IterT".to_string()); - let iterator = new_class(&mut db, "Iterator"); + let iterator = new_type(&mut db, "Iterator"); let iterator_param = iterator.new_type_parameter(&mut db, "IteratorT".to_string()); @@ -2696,7 +2698,7 @@ mod tests { #[test] fn test_rigid_type_parameter() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let args = type_arguments(vec![(param, owned(instance(thing)))]); let mut env = Environment::new(args.clone(), args); @@ -2749,7 +2751,7 @@ mod tests { #[test] fn test_check_argument_with_mut() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let to_string = new_trait(&mut db, "ToString"); thing.add_trait_implementation( @@ -2773,8 +2775,8 @@ mod tests { #[test] fn test_check_argument_with_ref() { let mut db = Database::new(); - let array = ClassId::array(); - let int = ClassId::int(); + let array = TypeId::array(); + let int = TypeId::int(); let to_string = new_trait(&mut db, "ToString"); array.new_type_parameter(&mut db, "T".to_string()); @@ -2809,19 +2811,19 @@ mod tests { #[test] fn test_check_foreign_types() { let mut db = Database::new(); - let foo = Class::alloc( + let foo = Type::alloc( &mut db, "foo".to_string(), - ClassKind::Extern, + TypeKind::Extern, Visibility::Public, ModuleId(0), Location::default(), ); - let bar = Class::alloc( + let bar = Type::alloc( &mut db, "bar".to_string(), - ClassKind::Extern, + TypeKind::Extern, Visibility::Public, ModuleId(0), Location::default(), @@ -2871,7 +2873,7 @@ mod tests { check_ok_cast(&db, TypeRef::int(), TypeRef::float()); check_ok_cast( &db, - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Signed, ))), @@ -2879,7 +2881,7 @@ mod tests { ); check_ok_cast( &db, - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Unsigned, ))), @@ -2887,7 +2889,7 @@ mod tests { ); check_ok_cast( &db, - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Signed, ))), @@ -2896,7 +2898,7 @@ mod tests { check_ok_cast( &db, TypeRef::int(), - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Signed, ))), @@ -2904,18 +2906,18 @@ mod tests { check_ok_cast( &db, TypeRef::foreign_signed_int(8), - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Signed, ))), ); check_ok_cast( &db, - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Signed, ))), - TypeRef::pointer(TypeId::Foreign(ForeignType::Float(32))), + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Float(32))), ); check_err( @@ -2943,12 +2945,12 @@ mod tests { check_err( &db, owned(instance(foo)), - TypeRef::pointer(TypeId::ClassInstance(ClassInstance::new(foo))), + TypeRef::pointer(TypeEnum::TypeInstance(TypeInstance::new(foo))), ); check_err( &db, - TypeRef::pointer(TypeId::ClassInstance(ClassInstance::new(foo))), - TypeRef::pointer(TypeId::ClassInstance(ClassInstance::new(bar))), + TypeRef::pointer(TypeEnum::TypeInstance(TypeInstance::new(foo))), + TypeRef::pointer(TypeEnum::TypeInstance(TypeInstance::new(bar))), ); } @@ -2957,18 +2959,18 @@ mod tests { let mut db = Database::new(); let to_string = new_trait(&mut db, "ToString"); let param = new_parameter(&mut db, "T"); - let stack = new_class(&mut db, "Stack"); + let stack = new_type(&mut db, "Stack"); stack.set_copy_storage(&mut db); - for class in [ - ClassId::int(), - ClassId::float(), - ClassId::boolean(), - ClassId::nil(), - ClassId::string(), + for typ in [ + TypeId::int(), + TypeId::float(), + TypeId::boolean(), + TypeId::nil(), + TypeId::string(), ] { - class.add_trait_implementation( + typ.add_trait_implementation( &mut db, TraitImplementation { instance: trait_instance(to_string), @@ -2989,14 +2991,14 @@ mod tests { check_err_cast( &db, owned(instance(stack)), - owned(TypeId::Foreign(ForeignType::Int(32, Sign::Signed))), + owned(TypeEnum::Foreign(ForeignType::Int(32, Sign::Signed))), ); } #[test] fn test_ref_value_type_with_uni_reference() { let db = Database::new(); - let int = ClassId::int(); + let int = TypeId::int(); check_ok(&db, immutable(instance(int)), immutable_uni(instance(int))); check_ok(&db, mutable(instance(int)), mutable_uni(instance(int))); @@ -3005,7 +3007,7 @@ mod tests { #[test] fn test_check_ref_against_owned_parameter_with_assigned_type() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let mut env = Environment::new(TypeArguments::new(), TypeArguments::new()); @@ -3021,7 +3023,7 @@ mod tests { #[test] fn test_check_ref_against_owned_parameter_with_assigned_placeholder() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let var = TypePlaceholder::alloc(&mut db, None); let param = new_parameter(&mut db, "T"); let mut env1 = @@ -3049,7 +3051,7 @@ mod tests { #[test] fn test_check_owned_against_uni_placeholder() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let var = TypePlaceholder::alloc(&mut db, Some(param)); let mut env = @@ -3066,7 +3068,7 @@ mod tests { #[test] fn test_check_bounded_type_parameter() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let param = new_parameter(&mut db, "T"); let bound = new_parameter(&mut db, "T"); @@ -3087,7 +3089,7 @@ mod tests { #[test] fn test_check_return() { let mut db = Database::new(); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let owned_var = TypePlaceholder::alloc(&mut db, None).as_owned(); let uni_var = TypePlaceholder::alloc(&mut db, None).as_uni(); let ref_var = TypePlaceholder::alloc(&mut db, None).as_ref(); diff --git a/types/src/format.rs b/types/src/format.rs index fcfd8dd3c..7d5a11744 100644 --- a/types/src/format.rs +++ b/types/src/format.rs @@ -1,9 +1,9 @@ //! Formatting of types. use crate::{ - Arguments, ClassId, ClassInstance, ClassKind, ClosureId, Database, - ForeignType, Inline, MethodId, MethodKind, ModuleId, Ownership, Sign, - TraitId, TraitInstance, TypeArguments, TypeId, TypeParameterId, - TypePlaceholderId, TypeRef, Visibility, + Arguments, ClosureId, Database, ForeignType, Inline, MethodId, MethodKind, + ModuleId, Ownership, Sign, TraitId, TraitInstance, TypeArguments, TypeEnum, + TypeId, TypeInstance, TypeKind, TypeParameterId, TypePlaceholderId, + TypeRef, Visibility, }; const MAX_FORMATTING_DEPTH: usize = 8; @@ -328,24 +328,24 @@ impl FormatType for TraitInstance { } } -impl FormatType for ClassId { +impl FormatType for TypeId { fn format_type(&self, buffer: &mut TypeFormatter) { buffer.write(&self.get(buffer.db).name); buffer.type_parameters(&self.type_parameters(buffer.db)); } } -impl FormatType for ClassInstance { +impl FormatType for TypeInstance { fn format_type(&self, buffer: &mut TypeFormatter) { buffer.descend(|buffer| { let ins_of = self.instance_of.get(buffer.db); - if !matches!(ins_of.kind, ClassKind::Tuple) { + if !matches!(ins_of.kind, TypeKind::Tuple) { buffer.write(&ins_of.name); } if !ins_of.type_parameters.is_empty() { - let (open, close) = if let ClassKind::Tuple = ins_of.kind { + let (open, close) = if let TypeKind::Tuple = ins_of.kind { ("(", ")") } else { ("[", "]") @@ -429,10 +429,10 @@ impl FormatType for ClosureId { impl FormatType for TypeRef { fn format_type(&self, buffer: &mut TypeFormatter) { match self { - TypeRef::Owned(TypeId::TypeParameter(id)) => { + TypeRef::Owned(TypeEnum::TypeParameter(id)) => { format_type_parameter(*id, buffer, true); } - TypeRef::Owned(TypeId::RigidTypeParameter(id)) => { + TypeRef::Owned(TypeEnum::RigidTypeParameter(id)) => { format_type_parameter_without_argument( *id, buffer, true, false, ); @@ -487,29 +487,29 @@ impl FormatType for TypeRef { } } -impl FormatType for TypeId { +impl FormatType for TypeEnum { fn format_type(&self, buffer: &mut TypeFormatter) { match self { - TypeId::Class(id) => id.format_type(buffer), - TypeId::Trait(id) => id.format_type(buffer), - TypeId::Module(id) => id.format_type(buffer), - TypeId::ClassInstance(ins) => ins.format_type(buffer), - TypeId::TraitInstance(id) => id.format_type(buffer), - TypeId::TypeParameter(id) => id.format_type(buffer), - TypeId::RigidTypeParameter(id) - | TypeId::AtomicTypeParameter(id) => { + TypeEnum::Type(id) => id.format_type(buffer), + TypeEnum::Trait(id) => id.format_type(buffer), + TypeEnum::Module(id) => id.format_type(buffer), + TypeEnum::TypeInstance(ins) => ins.format_type(buffer), + TypeEnum::TraitInstance(id) => id.format_type(buffer), + TypeEnum::TypeParameter(id) => id.format_type(buffer), + TypeEnum::RigidTypeParameter(id) + | TypeEnum::AtomicTypeParameter(id) => { format_type_parameter_without_argument( *id, buffer, false, false, ); } - TypeId::Closure(id) => id.format_type(buffer), - TypeId::Foreign(ForeignType::Int(size, Sign::Signed)) => { + TypeEnum::Closure(id) => id.format_type(buffer), + TypeEnum::Foreign(ForeignType::Int(size, Sign::Signed)) => { buffer.write(&format!("Int{}", size)) } - TypeId::Foreign(ForeignType::Int(size, Sign::Unsigned)) => { + TypeEnum::Foreign(ForeignType::Int(size, Sign::Unsigned)) => { buffer.write(&format!("UInt{}", size)) } - TypeId::Foreign(ForeignType::Float(size)) => { + TypeEnum::Foreign(ForeignType::Float(size)) => { buffer.write(&format!("Float{}", size)) } } @@ -521,12 +521,12 @@ mod tests { use super::*; use crate::test::{ any, immutable, immutable_uni, instance, mutable, mutable_uni, - new_class, new_parameter, owned, placeholder, uni, + new_parameter, new_type, owned, placeholder, uni, }; use crate::{ - Block, Class, ClassInstance, ClassKind, Closure, Database, Inline, - Location, Method, MethodKind, Module, ModuleId, ModuleName, Trait, - TraitInstance, TypeArguments, TypeId, TypeParameter, TypePlaceholder, + Block, Closure, Database, Inline, Location, Method, MethodKind, Module, + ModuleId, ModuleName, Trait, TraitInstance, Type, TypeArguments, + TypeEnum, TypeInstance, TypeKind, TypeParameter, TypePlaceholder, TypeRef, Visibility, }; @@ -571,26 +571,26 @@ mod tests { #[test] fn test_method_id_format_type_with_instance_method() { let mut db = Database::new(); - let class_a = Class::alloc( + let type_a = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_b = Class::alloc( + let type_b = Type::alloc( &mut db, "B".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_d = Class::alloc( + let type_d = Type::alloc( &mut db, "D".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -605,13 +605,13 @@ mod tests { ); let ins_a = - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(class_a))); + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(type_a))); let ins_b = - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(class_b))); + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(type_b))); let ins_d = - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(class_d))); + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(type_d))); let loc = Location::default(); @@ -750,12 +750,12 @@ mod tests { } #[test] - fn test_type_id_format_type_with_class() { + fn test_type_id_format_type_with_type() { let mut db = Database::new(); - let id = TypeId::Class(Class::alloc( + let id = TypeEnum::Type(Type::alloc( &mut db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -765,7 +765,7 @@ mod tests { } #[test] - fn test_type_id_format_type_with_generic_class() { + fn test_type_id_format_type_with_generic_type() { let mut db = Database::new(); let to_a = Trait::alloc( &mut db, @@ -781,10 +781,10 @@ mod tests { ModuleId(0), Location::default(), ); - let id = Class::alloc( + let id = Type::alloc( &mut db, "Foo".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -798,7 +798,7 @@ mod tests { param1.set_mutable(&mut db); assert_eq!( - format_type(&db, TypeId::Class(id)), + format_type(&db, TypeEnum::Type(id)), "Foo[A: mut + ToA + ToB, B]" ); } @@ -806,7 +806,7 @@ mod tests { #[test] fn test_type_id_format_type_with_trait() { let mut db = Database::new(); - let id = TypeId::Trait(Trait::alloc( + let id = TypeEnum::Trait(Trait::alloc( &mut db, "ToString".to_string(), Visibility::Private, @@ -850,7 +850,7 @@ mod tests { param1.set_mutable(&mut db); assert_eq!( - format_type(&db, TypeId::Trait(id)), + format_type(&db, TypeEnum::Trait(id)), "Foo[A: mut + ToA + ToB, B]" ); } @@ -858,7 +858,7 @@ mod tests { #[test] fn test_type_id_format_type_with_module() { let mut db = Database::new(); - let id = TypeId::Module(Module::alloc( + let id = TypeEnum::Module(Module::alloc( &mut db, ModuleName::new("foo::bar"), "foo/bar.inko".into(), @@ -868,29 +868,28 @@ mod tests { } #[test] - fn test_type_id_format_type_with_class_instance() { + fn test_type_id_format_type_with_type_instance() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let ins = TypeId::ClassInstance(ClassInstance::new(id)); + let ins = TypeEnum::TypeInstance(TypeInstance::new(id)); assert_eq!(format_type(&db, ins), "String"); } #[test] - fn test_type_id_format_type_with_generic_class_instance_without_arguments() - { + fn test_type_id_format_type_with_generic_type_instance_without_arguments() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "Array".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -898,7 +897,7 @@ mod tests { id.new_type_parameter(&mut db, "T".to_string()); - let ins = TypeId::ClassInstance(ClassInstance::new(id)); + let ins = TypeEnum::TypeInstance(TypeInstance::new(id)); assert_eq!(format_type(&db, ins), "Array[T]"); } @@ -906,10 +905,10 @@ mod tests { #[test] fn test_type_id_format_type_with_tuple_instance() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "MyTuple".to_string(), - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Private, ModuleId(0), Location::default(), @@ -922,7 +921,7 @@ mod tests { args.assign(param2, TypeRef::Never); let ins = - TypeId::ClassInstance(ClassInstance::generic(&mut db, id, args)); + TypeEnum::TypeInstance(TypeInstance::generic(&mut db, id, args)); assert_eq!(format_type(&db, ins), "(Int, Never)"); } @@ -937,18 +936,18 @@ mod tests { ModuleId(0), Location::default(), ); - let ins = TypeId::TraitInstance(TraitInstance::new(id)); + let ins = TypeEnum::TraitInstance(TraitInstance::new(id)); assert_eq!(format_type(&db, ins), "ToString"); } #[test] - fn test_type_id_format_type_with_generic_class_instance() { + fn test_type_id_format_type_with_generic_type_instance() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "Thing".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -962,7 +961,7 @@ mod tests { targs.assign(param1, TypeRef::int()); let ins = - TypeId::ClassInstance(ClassInstance::generic(&mut db, id, targs)); + TypeEnum::TypeInstance(TypeInstance::generic(&mut db, id, targs)); assert_eq!(format_type(&db, ins), "Thing[Int, E]"); } @@ -986,7 +985,7 @@ mod tests { targs.assign(param1, TypeRef::int()); let ins = - TypeId::TraitInstance(TraitInstance::generic(&mut db, id, targs)); + TypeEnum::TraitInstance(TraitInstance::generic(&mut db, id, targs)); assert_eq!(format_type(&db, ins), "ToFoo[Int, E]"); } @@ -1002,7 +1001,7 @@ mod tests { ModuleId(0), Location::default(), ); - let param_ins = TypeId::TypeParameter(param); + let param_ins = TypeEnum::TypeParameter(param); let to_string_ins = TraitInstance::new(to_string); param.add_requirements(&mut db, vec![to_string_ins]); @@ -1022,7 +1021,7 @@ mod tests { ModuleId(0), Location::default(), ); - let param_ins = TypeId::RigidTypeParameter(param); + let param_ins = TypeEnum::RigidTypeParameter(param); let to_string_ins = TraitInstance::new(to_string); param.add_requirements(&mut db, vec![to_string_ins]); @@ -1034,26 +1033,26 @@ mod tests { fn test_type_id_format_type_with_closure() { let mut db = Database::new(); let loc = Location::default(); - let class_a = Class::alloc( + let type_a = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_b = Class::alloc( + let type_b = Type::alloc( &mut db, "B".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let class_d = Class::alloc( + let type_d = Type::alloc( &mut db, "D".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -1061,19 +1060,19 @@ mod tests { let block = Closure::alloc(&mut db, true); let ins_a = - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(class_a))); + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(type_a))); let ins_b = - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(class_b))); + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(type_b))); let ins_d = - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(class_d))); + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(type_d))); block.new_argument(&mut db, "a".to_string(), ins_a, ins_a, loc); block.new_argument(&mut db, "b".to_string(), ins_b, ins_b, loc); block.set_return_type(&mut db, ins_d); - let block_ins = TypeId::Closure(block); + let block_ins = TypeEnum::Closure(block); assert_eq!(format_type(&db, block_ins), "fn move (A, B) -> D"); } @@ -1081,10 +1080,10 @@ mod tests { #[test] fn test_type_ref_type_name() { let mut db = Database::new(); - let cls = new_class(&mut db, "A"); + let cls = new_type(&mut db, "A"); let ins = instance(cls); - let int = instance(ClassId::int()); - let param = TypeId::TypeParameter(TypeParameter::alloc( + let int = instance(TypeId::int()); + let param = TypeEnum::TypeParameter(TypeParameter::alloc( &mut db, "T".to_string(), )); @@ -1143,7 +1142,7 @@ mod tests { assert_eq!( format_type( &db, - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Signed ))) @@ -1153,7 +1152,7 @@ mod tests { assert_eq!( format_type( &db, - TypeRef::pointer(TypeId::Foreign(ForeignType::Int( + TypeRef::pointer(TypeEnum::Foreign(ForeignType::Int( 8, Sign::Unsigned ))) @@ -1187,8 +1186,8 @@ mod tests { #[test] fn test_format_placeholder_with_assigned_value() { let mut db = Database::new(); - let heap = owned(instance(new_class(&mut db, "Heap"))); - let stack = owned(instance(ClassId::int())); + let heap = owned(instance(new_type(&mut db, "Heap"))); + let stack = owned(instance(TypeId::int())); let mut var = TypePlaceholder::alloc(&mut db, None); let tests = vec![ (heap, Ownership::Any, "Heap"), diff --git a/types/src/lib.rs b/types/src/lib.rs index d3f0a8fe7..2f031e7ea 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -42,11 +42,11 @@ const TUPLE8_ID: u32 = 13; const ARRAY_ID: u32 = 14; const CHECKED_INT_RESULT_ID: u32 = 15; -pub const FIRST_USER_CLASS_ID: u32 = CHECKED_INT_RESULT_ID + 1; +pub const FIRST_USER_TYPE_ID: u32 = CHECKED_INT_RESULT_ID + 1; /// The default module ID to assign to builtin types. /// -/// This ID is corrected using a `builtin class` definition. +/// This ID is corrected using a `builtin type` definition. const DEFAULT_BUILTIN_MODULE_ID: u32 = 0; const INT_NAME: &str = "Int"; @@ -71,7 +71,7 @@ pub const TO_STRING_TRAIT: &str = "ToString"; pub const TO_STRING_METHOD: &str = "to_string"; pub const CALL_METHOD: &str = "call"; pub const EQ_METHOD: &str = "=="; -pub const MAIN_CLASS: &str = "Main"; +pub const MAIN_TYPE: &str = "Main"; pub const MAIN_METHOD: &str = "main"; pub const DROP_MODULE: &str = "std.drop"; pub const DROP_TRAIT: &str = "Drop"; @@ -81,9 +81,9 @@ pub const INCREMENT_METHOD: &str = "$increment"; pub const DECREMENT_METHOD: &str = "$decrement"; pub const ASYNC_DROPPER_METHOD: &str = "$async_dropper"; pub const OPTION_MODULE: &str = "std.option"; -pub const OPTION_CLASS: &str = "Option"; +pub const OPTION_TYPE: &str = "Option"; pub const RESULT_MODULE: &str = "std.result"; -pub const RESULT_CLASS: &str = "Result"; +pub const RESULT_TYPE: &str = "Result"; pub const OPTION_SOME: &str = "Some"; pub const OPTION_NONE: &str = "None"; pub const RESULT_OK: &str = "Ok"; @@ -99,7 +99,7 @@ pub const ENUM_TAG_FIELD: &str = "tag"; pub const ENUM_TAG_INDEX: usize = 0; /// The maximum number of enum constructors that can be defined in a single -/// class. +/// type. pub const CONSTRUCTORS_LIMIT: usize = u16::MAX as usize; /// The maximum number of methods supported. @@ -312,7 +312,7 @@ impl TypePlaceholderId { // `TypePlaceholder::assign()`, which requires a `&mut Database`. unsafe impl Sync for TypePlaceholder {} -/// A type parameter for a method or class. +/// A type parameter for a method or type. #[derive(Clone)] pub struct TypeParameter { /// The name of the type parameter. @@ -439,7 +439,7 @@ impl TypeParameterId { } fn as_rigid(self) -> TypeRef { - TypeRef::Any(TypeId::RigidTypeParameter(self)) + TypeRef::Any(TypeEnum::RigidTypeParameter(self)) } } @@ -455,7 +455,7 @@ pub struct TypeArguments { } impl TypeArguments { - pub fn for_class(db: &Database, instance: ClassInstance) -> TypeArguments { + pub fn for_type(db: &Database, instance: TypeInstance) -> TypeArguments { if instance.instance_of().is_generic(db) { instance.type_arguments(db).unwrap().clone() } else { @@ -562,19 +562,19 @@ impl TypeArguments { /// map those to a common type arguments ID. If we don't do this, we may end up /// specializing the same type many times. pub struct InternedTypeArguments { - /// A cache that maps the raw class instances to their interned type + /// A cache that maps the raw type instances to their interned type /// arguments ID. /// /// This cache is used to avoid the more expensive key generation process /// when comparing the exact same type many times. - cache: HashMap, + cache: HashMap, - /// A mapping of the flattened type IDs from a class instance to the common + /// A mapping of the flattened type IDs from a type instance to the common /// type arguments ID. /// /// For ClassInstance and TraitInstance types, the TypeId is stripped of its /// TypeArguments ID such that it's consistent when hashed. - mapping: HashMap, u32>, + mapping: HashMap, u32>, } impl InternedTypeArguments { @@ -582,7 +582,7 @@ impl InternedTypeArguments { InternedTypeArguments { cache: HashMap::new(), mapping: HashMap::new() } } - pub fn intern(&mut self, db: &Database, instance: ClassInstance) -> u32 { + pub fn intern(&mut self, db: &Database, instance: TypeInstance) -> u32 { // The cache is used such that if we use the exact same type N times, we // only perform the more expensive type walking once. if let Some(&id) = self.cache.get(&instance) { @@ -590,16 +590,16 @@ impl InternedTypeArguments { } let mut key = Vec::new(); - let mut stack = vec![TypeId::ClassInstance(instance)]; + let mut stack = vec![TypeEnum::TypeInstance(instance)]; while let Some(tid) = stack.pop() { let (val, args) = match tid { - // When encountering a specialized class, we use the source - // class ID instead such that we always operate on the same - // stable ID for all specializations. - TypeId::ClassInstance(i) => ( - TypeId::ClassInstance(ClassInstance::new( - i.source_class(db), + // When encountering a specialized type, we use the source type + // ID instead such that we always operate on the same stable ID + // for all specializations. + TypeEnum::TypeInstance(i) => ( + TypeEnum::TypeInstance(TypeInstance::new( + i.source_type(db), )), if i.instance_of.is_generic(db) { i.type_arguments(db) @@ -607,10 +607,16 @@ impl InternedTypeArguments { None }, ), - TypeId::TraitInstance(i) if i.instance_of().is_generic(db) => ( - TypeId::TraitInstance(TraitInstance::new(i.instance_of)), - i.type_arguments(db), - ), + TypeEnum::TraitInstance(i) + if i.instance_of().is_generic(db) => + { + ( + TypeEnum::TraitInstance(TraitInstance::new( + i.instance_of, + )), + i.type_arguments(db), + ) + } _ => (tid, None), }; @@ -621,7 +627,9 @@ impl InternedTypeArguments { pairs.sort_by_key(|(p, _)| *p); stack.extend( - pairs.into_iter().flat_map(|(_, t)| t.type_id(db).ok()), + pairs + .into_iter() + .flat_map(|(_, t)| t.as_type_enum(db).ok()), ); } @@ -641,7 +649,7 @@ pub struct Trait { module: ModuleId, location: Location, documentation: String, - implemented_by: Vec, + implemented_by: Vec, visibility: Visibility, type_parameters: IndexMap, required_traits: Vec, @@ -767,7 +775,7 @@ impl TraitId { self_typ.required_traits.push(requirement); } - pub fn implemented_by(self, db: &Database) -> &Vec { + pub fn implemented_by(self, db: &Database) -> &Vec { &self.get(db).implemented_by } @@ -993,7 +1001,7 @@ impl TraitInstance { } } -/// A field for a class. +/// A field for a type. pub struct Field { index: usize, name: String, @@ -1063,7 +1071,7 @@ impl FieldId { field.module.has_same_root_namespace(db, module) } // TypePrivate fields can only be accessed using the `@name` syntax, - // which in turn is only available inside a class, thus not needing + // which in turn is only available inside a type, thus not needing // any extra checks. Visibility::TypePrivate => false, } @@ -1158,7 +1166,7 @@ pub struct TraitImplementation { pub bounds: TypeBounds, } -/// A single constructor defined in a enum class. +/// A single constructor defined in a enum type. pub struct Constructor { id: u16, name: String, @@ -1252,7 +1260,7 @@ pub enum Storage { } #[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum ClassKind { +pub enum TypeKind { /// The type is an async type, aka a process. Async, @@ -1278,50 +1286,50 @@ pub enum ClassKind { Tuple, } -impl ClassKind { +impl TypeKind { pub fn is_async(self) -> bool { - matches!(self, ClassKind::Async) + matches!(self, TypeKind::Async) } pub fn is_enum(self) -> bool { - matches!(self, ClassKind::Enum) + matches!(self, TypeKind::Enum) } pub fn is_tuple(self) -> bool { - matches!(self, ClassKind::Tuple) + matches!(self, TypeKind::Tuple) } pub fn is_closure(self) -> bool { - matches!(self, ClassKind::Closure) + matches!(self, TypeKind::Closure) } pub fn is_module(self) -> bool { - matches!(self, ClassKind::Module) + matches!(self, TypeKind::Module) } pub fn is_extern(self) -> bool { - matches!(self, ClassKind::Extern) + matches!(self, TypeKind::Extern) } pub fn allow_pattern_matching(self) -> bool { - matches!(self, ClassKind::Regular | ClassKind::Extern) + matches!(self, TypeKind::Regular | TypeKind::Extern) } fn is_atomic(self) -> bool { - matches!(self, ClassKind::Async | ClassKind::Atomic) + matches!(self, TypeKind::Async | TypeKind::Atomic) } } /// A type used as the key for a type specialization lookup. #[derive(Eq, PartialEq, Hash, Clone, Debug)] pub struct SpecializationKey { - /// The shapes of the class, in the same order as the type parameters they + /// The shapes of the type, in the same order as the type parameters they /// belong to. pub shapes: Vec, /// Closures may be defined in a default method, in which case we should /// specialize them for every type that implements the corresponding trait. - pub self_type: Option, + pub self_type: Option, } impl SpecializationKey { @@ -1334,16 +1342,16 @@ impl SpecializationKey { } pub fn for_closure( - self_type: ClassInstance, + self_type: TypeInstance, shapes: Vec, ) -> SpecializationKey { SpecializationKey { self_type: Some(self_type), shapes } } } -/// An Inko class as declared using the `class` keyword. -pub struct Class { - kind: ClassKind, +/// An Inko type as declared using the `type` keyword. +pub struct Type { + kind: TypeKind, name: String, documentation: String, @@ -1365,50 +1373,50 @@ pub struct Class { implemented_traits: HashMap, constructors: IndexMap, - /// The specializations of this class. + /// The specializations of this type. /// /// We use an IndexMap here such that iterations over this data are /// performed in a stable order. - specializations: IndexMap, + specializations: IndexMap, - /// The ID of the class this class is a specialization of. - specialization_source: Option, + /// The ID of the type this type is a specialization of. + specialization_source: Option, - /// The type specialization key used for this class. + /// The type specialization key used for this type. specialization_key: SpecializationKey, } -impl Class { +impl Type { pub fn alloc( db: &mut Database, name: String, - kind: ClassKind, + kind: TypeKind, visibility: Visibility, module: ModuleId, location: Location, - ) -> ClassId { - let class = Class::new(name, kind, visibility, module, location); + ) -> TypeId { + let typ = Type::new(name, kind, visibility, module, location); - Class::add(db, class) + Type::add(db, typ) } - fn add(db: &mut Database, class: Class) -> ClassId { - assert!(db.classes.len() < u32::MAX as usize); + fn add(db: &mut Database, typ: Type) -> TypeId { + assert!(db.types.len() < u32::MAX as usize); - let id = db.classes.len() as u32; + let id = db.types.len() as u32; - db.classes.push(class); - ClassId(id) + db.types.push(typ); + TypeId(id) } fn new( name: String, - kind: ClassKind, + kind: TypeKind, visibility: Visibility, module: ModuleId, location: Location, ) -> Self { - let storage = if let ClassKind::Extern = kind { + let storage = if let TypeKind::Extern = kind { Storage::Copy } else { Storage::Heap @@ -1437,7 +1445,7 @@ impl Class { fn regular(name: String) -> Self { Self::new( name, - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, ModuleId(DEFAULT_BUILTIN_MODULE_ID), Location::default(), @@ -1447,7 +1455,7 @@ impl Class { fn value_type(name: String) -> Self { let mut cls = Self::new( name, - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, ModuleId(DEFAULT_BUILTIN_MODULE_ID), Location::default(), @@ -1460,7 +1468,7 @@ impl Class { fn atomic(name: String) -> Self { Self::new( name, - ClassKind::Atomic, + TypeKind::Atomic, Visibility::Public, ModuleId(DEFAULT_BUILTIN_MODULE_ID), Location::default(), @@ -1470,7 +1478,7 @@ impl Class { fn tuple(name: String) -> Self { let mut cls = Self::new( name, - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Public, ModuleId(DEFAULT_BUILTIN_MODULE_ID), Location::default(), @@ -1486,83 +1494,83 @@ impl Class { } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -pub struct ClassId(pub u32); +pub struct TypeId(pub u32); -impl ClassId { - pub fn int() -> ClassId { - ClassId(INT_ID) +impl TypeId { + pub fn int() -> TypeId { + TypeId(INT_ID) } - pub fn float() -> ClassId { - ClassId(FLOAT_ID) + pub fn float() -> TypeId { + TypeId(FLOAT_ID) } - pub fn string() -> ClassId { - ClassId(STRING_ID) + pub fn string() -> TypeId { + TypeId(STRING_ID) } - pub fn boolean() -> ClassId { - ClassId(BOOL_ID) + pub fn boolean() -> TypeId { + TypeId(BOOL_ID) } - pub fn nil() -> ClassId { - ClassId(NIL_ID) + pub fn nil() -> TypeId { + TypeId(NIL_ID) } - pub fn array() -> ClassId { - ClassId(ARRAY_ID) + pub fn array() -> TypeId { + TypeId(ARRAY_ID) } - pub fn byte_array() -> ClassId { - ClassId(BYTE_ARRAY_ID) + pub fn byte_array() -> TypeId { + TypeId(BYTE_ARRAY_ID) } - pub fn tuple1() -> ClassId { - ClassId(TUPLE1_ID) + pub fn tuple1() -> TypeId { + TypeId(TUPLE1_ID) } - pub fn tuple2() -> ClassId { - ClassId(TUPLE2_ID) + pub fn tuple2() -> TypeId { + TypeId(TUPLE2_ID) } - pub fn tuple3() -> ClassId { - ClassId(TUPLE3_ID) + pub fn tuple3() -> TypeId { + TypeId(TUPLE3_ID) } - pub fn tuple4() -> ClassId { - ClassId(TUPLE4_ID) + pub fn tuple4() -> TypeId { + TypeId(TUPLE4_ID) } - pub fn tuple5() -> ClassId { - ClassId(TUPLE5_ID) + pub fn tuple5() -> TypeId { + TypeId(TUPLE5_ID) } - pub fn tuple6() -> ClassId { - ClassId(TUPLE6_ID) + pub fn tuple6() -> TypeId { + TypeId(TUPLE6_ID) } - pub fn tuple7() -> ClassId { - ClassId(TUPLE7_ID) + pub fn tuple7() -> TypeId { + TypeId(TUPLE7_ID) } - pub fn tuple8() -> ClassId { - ClassId(TUPLE8_ID) + pub fn tuple8() -> TypeId { + TypeId(TUPLE8_ID) } - pub fn checked_int_result() -> ClassId { - ClassId(CHECKED_INT_RESULT_ID) + pub fn checked_int_result() -> TypeId { + TypeId(CHECKED_INT_RESULT_ID) } - pub fn tuple(len: usize) -> Option { + pub fn tuple(len: usize) -> Option { match len { - 1 => Some(ClassId::tuple1()), - 2 => Some(ClassId::tuple2()), - 3 => Some(ClassId::tuple3()), - 4 => Some(ClassId::tuple4()), - 5 => Some(ClassId::tuple5()), - 6 => Some(ClassId::tuple6()), - 7 => Some(ClassId::tuple7()), - 8 => Some(ClassId::tuple8()), + 1 => Some(TypeId::tuple1()), + 2 => Some(TypeId::tuple2()), + 3 => Some(TypeId::tuple3()), + 4 => Some(TypeId::tuple4()), + 5 => Some(TypeId::tuple5()), + 6 => Some(TypeId::tuple6()), + 7 => Some(TypeId::tuple7()), + 8 => Some(TypeId::tuple8()), _ => None, } } @@ -1571,12 +1579,12 @@ impl ClassId { &self.get(db).name } - pub fn kind(self, db: &Database) -> ClassKind { + pub fn kind(self, db: &Database) -> TypeKind { self.get(db).kind } pub fn allow_trait_implementations(self, db: &Database) -> bool { - !matches!(self.kind(db), ClassKind::Async | ClassKind::Extern) + !matches!(self.kind(db), TypeKind::Async | TypeKind::Extern) } pub fn type_parameters(self, db: &Database) -> Vec { @@ -1599,8 +1607,8 @@ impl ClassId { db: &Database, trait_type: TraitId, ) -> Option<&TraitImplementation> { - // For specialized classes, the implementation is stored in the original - // class. + // For specialized types, the implementation is stored in the original + // type. let src = self.specialization_source(db).unwrap_or(self); src.get(db).implemented_traits.get(&trait_type) @@ -1749,7 +1757,7 @@ impl ClassId { pub fn enum_fields(self, db: &Database) -> Vec { let obj = self.get(db); - if let ClassKind::Enum = obj.kind { + if let TypeKind::Enum = obj.kind { // The first value is the tag, so we skip it. obj.fields[1..].values().cloned().collect() } else { @@ -1785,28 +1793,28 @@ impl ClassId { self.get_mut(db).specialization_key = key; } - pub fn specialization_source(self, db: &Database) -> Option { + pub fn specialization_source(self, db: &Database) -> Option { self.get(db).specialization_source } - pub fn set_specialization_source(self, db: &mut Database, class: ClassId) { - self.get_mut(db).specialization_source = Some(class); + pub fn set_specialization_source(self, db: &mut Database, typ: TypeId) { + self.get_mut(db).specialization_source = Some(typ); } pub fn add_specialization( self, db: &mut Database, key: SpecializationKey, - class: ClassId, + typ: TypeId, ) { - class.set_specialization_key(db, key.clone()); - self.get_mut(db).specializations.insert(key, class); + typ.set_specialization_key(db, key.clone()); + self.get_mut(db).specializations.insert(key, typ); } pub fn specializations( self, db: &Database, - ) -> &IndexMap { + ) -> &IndexMap { &self.get(db).specializations } @@ -1854,7 +1862,7 @@ impl ClassId { match typ.kind { // These types are allocated on the heap but treated as value types. - ClassKind::Async | ClassKind::Atomic => true, + TypeKind::Async | TypeKind::Atomic => true, _ => matches!(typ.storage, Storage::Copy), } } @@ -1889,10 +1897,10 @@ impl ClassId { match typ.kind { // Only heap allocated versions of these types have a header and // thus can be casted to a trait. - ClassKind::Enum | ClassKind::Regular | ClassKind::Tuple => { + TypeKind::Enum | TypeKind::Regular | TypeKind::Tuple => { matches!(typ.storage, Storage::Heap) } - // Other types such as closures, processes and extern classes can't + // Other types such as closures, processes and extern types can't // ever be casted to a trait. _ => false, } @@ -1927,9 +1935,9 @@ impl ClassId { self.get_mut(db).storage = Storage::Copy; } - pub fn clone_for_specialization(self, db: &mut Database) -> ClassId { + pub fn clone_for_specialization(self, db: &mut Database) -> TypeId { let src = self.get(db); - let mut new = Class::new( + let mut new = Type::new( src.name.clone(), src.kind, src.visibility, @@ -1938,15 +1946,15 @@ impl ClassId { ); new.storage = src.storage; - Class::add(db, new) + Type::add(db, new) } pub fn allow_mutating(self, db: &Database) -> bool { let obj = self.get(db); match obj.kind { - ClassKind::Extern => true, - ClassKind::Atomic => false, + TypeKind::Extern => true, + TypeKind::Atomic => false, _ => matches!(obj.storage, Storage::Heap | Storage::Inline), } } @@ -1955,32 +1963,31 @@ impl ClassId { let obj = self.get(db); match obj.kind { - ClassKind::Atomic => false, - ClassKind::Extern => true, + TypeKind::Atomic => false, + TypeKind::Extern => true, _ => matches!(obj.storage, Storage::Heap), } } - fn get(self, db: &Database) -> &Class { - &db.classes[self.0 as usize] + fn get(self, db: &Database) -> &Type { + &db.types[self.0 as usize] } - fn get_mut(self, db: &mut Database) -> &mut Class { - &mut db.classes[self.0 as usize] + fn get_mut(self, db: &mut Database) -> &mut Type { + &mut db.types[self.0 as usize] } } -/// An instance of a class, along with its type arguments in case the class is -/// generic. +/// An instance of a type and its type arguments (if any). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct ClassInstance { - /// The ID of the class we're an instance of. - instance_of: ClassId, +pub struct TypeInstance { + /// The ID of the type we're an instance of. + instance_of: TypeId, - /// The index to the TypeArguments structure that belongs to this class + /// The index to the TypeArguments structure that belongs to this type /// instance. /// - /// If the class isn't generic, this index shouldn't be used to obtain the + /// If the type isn't generic, this index shouldn't be used to obtain the /// type arguments, as it won't be used. /// /// After type specialization takes place, this value shouldn't be used any @@ -1988,14 +1995,14 @@ pub struct ClassInstance { type_arguments: u32, } -impl ClassInstance { - pub fn new(instance_of: ClassId) -> Self { +impl TypeInstance { + pub fn new(instance_of: TypeId) -> Self { Self { instance_of, type_arguments: 0 } } pub fn rigid( db: &mut Database, - instance_of: ClassId, + instance_of: TypeId, bounds: &TypeBounds, ) -> Self { if instance_of.is_generic(db) { @@ -2016,7 +2023,7 @@ impl ClassInstance { pub fn generic( db: &mut Database, - instance_of: ClassId, + instance_of: TypeId, arguments: TypeArguments, ) -> Self { assert!(db.type_arguments.len() < u32::MAX as usize); @@ -2024,18 +2031,17 @@ impl ClassInstance { let args_id = db.type_arguments.len() as u32; db.type_arguments.push(arguments); - ClassInstance { instance_of, type_arguments: args_id } + TypeInstance { instance_of, type_arguments: args_id } } pub fn with_types( db: &mut Database, - class: ClassId, + typ: TypeId, arguments: Vec, ) -> Self { let mut args = TypeArguments::new(); - for (index, param) in class.type_parameters(db).into_iter().enumerate() - { + for (index, param) in typ.type_parameters(db).into_iter().enumerate() { let val = arguments .get(index) .cloned() @@ -2044,24 +2050,24 @@ impl ClassInstance { args.assign(param, val); } - Self::generic(db, class, args) + Self::generic(db, typ, args) } - pub fn empty(db: &mut Database, class: ClassId) -> Self { - if !class.is_generic(db) { - return Self::new(class); + pub fn empty(db: &mut Database, typ: TypeId) -> Self { + if !typ.is_generic(db) { + return Self::new(typ); } let mut args = TypeArguments::new(); - for param in class.type_parameters(db) { + for param in typ.type_parameters(db) { args.assign(param, TypeRef::placeholder(db, Some(param))); } - Self::generic(db, class, args) + Self::generic(db, typ, args) } - pub fn instance_of(self) -> ClassId { + pub fn instance_of(self) -> TypeId { self.instance_of } @@ -2083,7 +2089,7 @@ impl ClassInstance { .collect() } - pub fn source_class(self, db: &Database) -> ClassId { + pub fn source_type(self, db: &Database) -> TypeId { self.instance_of.specialization_source(db).unwrap_or(self.instance_of) } @@ -2120,7 +2126,7 @@ impl ClassInstance { self, db: &Database, interned: &mut InternedTypeArguments, - ) -> ClassInstance { + ) -> TypeInstance { let targs = if self.instance_of.is_generic(db) { // We need to make sure that for different references to the same // type (e.g. `SomeType[Int]`), the type arguments ID is the same so @@ -2130,7 +2136,7 @@ impl ClassInstance { 0 }; - ClassInstance { instance_of: self.instance_of, type_arguments: targs } + TypeInstance { instance_of: self.instance_of, type_arguments: targs } } fn named_type(self, db: &Database, name: &str) -> Option { @@ -2412,8 +2418,8 @@ impl Intrinsic { } pub fn return_type(self, db: &Database, arguments: &[TypeRef]) -> TypeRef { - let int_res = TypeRef::Owned(TypeId::ClassInstance( - ClassInstance::new(ClassId::checked_int_result()), + let int_res = TypeRef::Owned(TypeEnum::TypeInstance( + TypeInstance::new(TypeId::checked_int_result()), )); match self { @@ -2459,10 +2465,10 @@ impl Intrinsic { Intrinsic::Moved => TypeRef::nil(), Intrinsic::Panic => TypeRef::Never, Intrinsic::StringConcat => TypeRef::string(), - Intrinsic::State => TypeRef::pointer(TypeId::Foreign( + Intrinsic::State => TypeRef::pointer(TypeEnum::Foreign( ForeignType::Int(8, Sign::Unsigned), )), - Intrinsic::Process => TypeRef::pointer(TypeId::Foreign( + Intrinsic::Process => TypeRef::pointer(TypeEnum::Foreign( ForeignType::Int(8, Sign::Unsigned), )), Intrinsic::FloatRound => TypeRef::float(), @@ -2615,7 +2621,7 @@ pub struct Method { /// The shapes of this method's type parameters, if any. /// /// For static methods this list starts with the shapes of the surrounding - /// class' type parameters, if any. For instance methods, we only include + /// type's type parameters, if any. For instance methods, we only include /// the shapes of the method's type parameters. shapes: Vec, } @@ -2710,12 +2716,12 @@ impl MethodId { self.get_mut(db).receiver = receiver; } - pub fn receiver_for_class_instance( + pub fn receiver_for_type_instance( self, db: &Database, - instance: ClassInstance, + instance: TypeInstance, ) -> TypeRef { - let rec_id = TypeId::ClassInstance(instance); + let rec_id = TypeEnum::TypeInstance(instance); match self.kind(db) { // Async methods always access `self` through a reference even @@ -2737,7 +2743,7 @@ impl MethodId { TypeRef::Mut(rec_id) } MethodKind::Static | MethodKind::Constructor => { - TypeRef::Owned(TypeId::Class(instance.instance_of())) + TypeRef::Owned(TypeEnum::Type(instance.instance_of())) } MethodKind::Moving => TypeRef::Owned(rec_id), MethodKind::Extern => TypeRef::Unknown, @@ -2748,8 +2754,8 @@ impl MethodId { self.get(db).receiver } - pub fn receiver_id(self, db: &Database) -> TypeId { - self.get(db).receiver.type_id(db).unwrap() + pub fn receiver_id(self, db: &Database) -> TypeEnum { + self.get(db).receiver.as_type_enum(db).unwrap() } pub fn source(self, db: &Database) -> MethodSource { @@ -3158,11 +3164,11 @@ pub enum Receiver { /// method with that name). Implicit, - /// The receiver is a class to call a static method on. + /// The receiver is a type to call a static method on. /// /// This is separate from an explicit receiver as we don't need to process /// the receiver expression in this case. - Class, + Type, /// The call is an extern call, and there's no receiver. Extern, @@ -3176,8 +3182,8 @@ impl Receiver { method .receiver(db) - .as_class(db) - .map(|_| Receiver::Class) + .as_type(db) + .map(|_| Receiver::Type) .unwrap_or(Receiver::Implicit) } @@ -3191,8 +3197,8 @@ impl Receiver { } receiver - .as_class(db) - .map(|_| Receiver::Class) + .as_type(db) + .map(|_| Receiver::Type) .unwrap_or(Receiver::Explicit) } @@ -3201,7 +3207,7 @@ impl Receiver { return Receiver::Extern; } - Receiver::Class + Receiver::Type } pub fn is_explicit(&self) -> bool { @@ -3232,15 +3238,15 @@ pub struct IntrinsicCall { #[derive(Clone, Debug, PartialEq, Eq)] pub struct FieldInfo { - pub class: ClassId, + pub type_id: TypeId, pub id: FieldId, pub variable_type: TypeRef, pub as_pointer: bool, } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct ClassInstanceInfo { - pub class_id: ClassId, +pub struct TypeInstanceInfo { + pub type_id: TypeId, pub resolved_type: TypeRef, pub fields: Vec<(FieldId, TypeRef)>, } @@ -3255,7 +3261,7 @@ pub enum CallKind { GetConstant(ConstantId), ReadPointer(TypeRef), WritePointer, - ClassInstance(ClassInstanceInfo), + TypeInstance(TypeInstanceInfo), } #[derive(Clone, Debug, PartialEq, Eq)] @@ -3317,7 +3323,7 @@ impl ThrowKind { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum Symbol { - Class(ClassId), + Type(TypeId), Trait(TraitId), Module(ModuleId), TypeParameter(TypeParameterId), @@ -3329,7 +3335,7 @@ impl Symbol { pub fn is_public(self, db: &Database) -> bool { match self { Symbol::Method(id) => id.is_public(db), - Symbol::Class(id) => id.is_public(db), + Symbol::Type(id) => id.is_public(db), Symbol::Trait(id) => id.is_public(db), Symbol::Constant(id) => id.is_public(db), _ => true, @@ -3347,7 +3353,7 @@ impl Symbol { let mod_id = match self { Symbol::Method(id) => id.module(db), - Symbol::Class(id) => id.module(db), + Symbol::Type(id) => id.module(db), Symbol::Trait(id) => id.module(db), Symbol::Constant(id) => id.module(db), _ => return true, @@ -3376,9 +3382,9 @@ pub struct Module { /// uses a human readable name instead of the generated one. method_symbol_name: ModuleName, - /// The ID of the class that's generated for the modle (containing the + /// The ID of the type that's generated for the module (containing the /// static methods). - class: ClassId, + type_id: TypeId, /// The path to the source file of the module. file: PathBuf, @@ -3402,10 +3408,10 @@ impl Module { assert!(db.modules.len() < u32::MAX as usize); let id = ModuleId(db.modules.len() as u32); - let class_id = Class::alloc( + let tid = Type::alloc( db, name.to_string(), - ClassKind::Module, + TypeKind::Module, Visibility::Private, id, Location::default(), @@ -3416,7 +3422,7 @@ impl Module { name: name.clone(), documentation: String::new(), method_symbol_name: name, - class: class_id, + type_id: tid, file, constants: Vec::new(), symbols: HashMap::default(), @@ -3496,7 +3502,7 @@ impl ModuleId { ) -> Option { let symbol = self.use_symbol(db, name)?; let module_id = match symbol { - Symbol::Class(id) => id.module(db), + Symbol::Type(id) => id.module(db), Symbol::Trait(id) => id.module(db), Symbol::Constant(id) => id.module(db), Symbol::Method(id) => id.module(db), @@ -3519,21 +3525,21 @@ impl ModuleId { } pub fn method(self, db: &Database, name: &str) -> Option { - self.get(db).class.method(db, name) + self.get(db).type_id.method(db, name) } pub fn methods(self, db: &Database) -> Vec { - self.get(db).class.methods(db) + self.get(db).type_id.methods(db) } - pub fn classes(self, db: &Database) -> Vec { + pub fn types(self, db: &Database) -> Vec { self.get(db) .symbols .iter() .filter_map(|(name, s)| match s.symbol { // Generated symbol names start with "$", which we never want to // include. - Symbol::Class(id) + Symbol::Type(id) if id.module(db) == self && !name.starts_with('$') => { Some(id) @@ -3555,7 +3561,7 @@ impl ModuleId { } pub fn add_method(self, db: &mut Database, name: String, method: MethodId) { - self.get(db).class.add_method(db, name, method); + self.get(db).type_id.add_method(db, name, method); } pub fn add_extern_method(self, db: &mut Database, method: MethodId) { @@ -3576,8 +3582,8 @@ impl ModuleId { self.get(db).name.is_std() } - pub fn class(self, db: &Database) -> ClassId { - self.get(db).class + pub fn type_id(self, db: &Database) -> TypeId { + self.get(db).type_id } fn has_same_root_namespace(self, db: &Database, other: ModuleId) -> bool { @@ -3999,16 +4005,16 @@ pub enum Shape { Pointer, /// A stack allocated value type. - Copy(ClassInstance), + Copy(TypeInstance), /// A stack allocated, owned type. - Inline(ClassInstance), + Inline(TypeInstance), /// An immutable borrow of an inline type. - InlineRef(ClassInstance), + InlineRef(TypeInstance), /// A mutable borrow of an inline type. - InlineMut(ClassInstance), + InlineMut(TypeInstance), } impl Shape { @@ -4030,7 +4036,7 @@ impl Shape { } } - pub fn as_stack_instance(self) -> Option { + pub fn as_stack_instance(self) -> Option { match self { Shape::Copy(v) | Shape::Inline(v) @@ -4120,29 +4126,29 @@ pub enum VerificationError { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum TypeRef { /// An owned value subject to move semantics. - Owned(TypeId), + Owned(TypeEnum), /// An owned value subject to move semantics, and doesn't allow aliasing. - Uni(TypeId), + Uni(TypeEnum), /// An immutable reference to a type. - Ref(TypeId), + Ref(TypeEnum), /// An immutable, temporary and unique reference. - UniRef(TypeId), + UniRef(TypeEnum), /// A mutable reference to a type. - Mut(TypeId), + Mut(TypeEnum), /// A mutable, temporary and unique reference. - UniMut(TypeId), + UniMut(TypeEnum), /// A type of which the ownership can be anything. /// /// This constructor is only used with type parameters. We wrap a TypeId /// here so we can reuse various functions more easily, such as those used /// for type-checking; instead of having to special-case this constructor. - Any(TypeId), + Any(TypeEnum), /// A type that signals something never happens. /// @@ -4164,43 +4170,41 @@ pub enum TypeRef { Placeholder(TypePlaceholderId), /// A pointer to a value. - Pointer(TypeId), + Pointer(TypeEnum), } impl TypeRef { pub fn nil() -> TypeRef { - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(ClassId( + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(TypeId( NIL_ID, )))) } pub fn boolean() -> TypeRef { - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new(ClassId( + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(TypeId( BOOL_ID, )))) } pub fn int() -> TypeRef { - TypeRef::Owned(TypeId::ClassInstance( - ClassInstance::new(ClassId::int()), - )) + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new(TypeId::int()))) } pub fn float() -> TypeRef { - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new( - ClassId::float(), + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new( + TypeId::float(), ))) } pub fn string() -> TypeRef { - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new( - ClassId::string(), + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new( + TypeId::string(), ))) } pub fn byte_array() -> TypeRef { - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::new( - ClassId::byte_array(), + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::new( + TypeId::byte_array(), ))) } @@ -4221,23 +4225,26 @@ impl TypeRef { } pub fn foreign_signed_int(size: u32) -> TypeRef { - TypeRef::Owned(TypeId::Foreign(ForeignType::Int(size, Sign::Signed))) + TypeRef::Owned(TypeEnum::Foreign(ForeignType::Int(size, Sign::Signed))) } pub fn foreign_unsigned_int(size: u32) -> TypeRef { - TypeRef::Owned(TypeId::Foreign(ForeignType::Int(size, Sign::Unsigned))) + TypeRef::Owned(TypeEnum::Foreign(ForeignType::Int( + size, + Sign::Unsigned, + ))) } pub fn foreign_float(size: u32) -> TypeRef { - TypeRef::Owned(TypeId::Foreign(ForeignType::Float(size))) + TypeRef::Owned(TypeEnum::Foreign(ForeignType::Float(size))) } - pub fn pointer(of: TypeId) -> TypeRef { + pub fn pointer(of: TypeEnum) -> TypeRef { TypeRef::Pointer(of) } pub fn module(id: ModuleId) -> TypeRef { - TypeRef::Owned(TypeId::Module(id)) + TypeRef::Owned(TypeEnum::Module(id)) } pub fn placeholder( @@ -4247,7 +4254,7 @@ impl TypeRef { TypeRef::Placeholder(TypePlaceholder::alloc(db, required)) } - pub fn type_id(self, db: &Database) -> Result { + pub fn as_type_enum(self, db: &Database) -> Result { match self { TypeRef::Pointer(id) | TypeRef::Owned(id) @@ -4258,14 +4265,14 @@ impl TypeRef { | TypeRef::UniMut(id) | TypeRef::Any(id) => Ok(id), TypeRef::Placeholder(id) => { - id.value(db).ok_or(self).and_then(|t| t.type_id(db)) + id.value(db).ok_or(self).and_then(|t| t.as_type_enum(db)) } _ => Err(self), } } pub fn closure_id(self, db: &Database) -> Option { - if let Ok(TypeId::Closure(id)) = self.type_id(db) { + if let Ok(TypeEnum::Closure(id)) = self.as_type_enum(db) { Some(id) } else { None @@ -4294,12 +4301,12 @@ impl TypeRef { pub fn is_foreign_type(self, db: &Database) -> bool { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of.kind(db).is_extern() => { true } - TypeRef::Owned(TypeId::Foreign(_)) => true, + TypeRef::Owned(TypeEnum::Foreign(_)) => true, TypeRef::Pointer(_) => true, TypeRef::Placeholder(id) => { id.value(db).map_or(false, |v| v.is_foreign_type(db)) @@ -4310,8 +4317,8 @@ impl TypeRef { pub fn is_extern_instance(self, db: &Database) -> bool { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) => { ins.instance_of().kind(db).is_extern() } _ => false, @@ -4371,39 +4378,39 @@ impl TypeRef { pub fn is_type_parameter(self, db: &Database) -> bool { match self { TypeRef::Owned( - TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) - | TypeId::AtomicTypeParameter(_), + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) + | TypeEnum::AtomicTypeParameter(_), ) | TypeRef::Uni( - TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) - | TypeId::AtomicTypeParameter(_), + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) + | TypeEnum::AtomicTypeParameter(_), ) | TypeRef::Ref( - TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) - | TypeId::AtomicTypeParameter(_), + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) + | TypeEnum::AtomicTypeParameter(_), ) | TypeRef::Mut( - TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) - | TypeId::AtomicTypeParameter(_), + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) + | TypeEnum::AtomicTypeParameter(_), ) | TypeRef::Any( - TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) - | TypeId::AtomicTypeParameter(_), + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) + | TypeEnum::AtomicTypeParameter(_), ) | TypeRef::UniRef( - TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) - | TypeId::AtomicTypeParameter(_), + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) + | TypeEnum::AtomicTypeParameter(_), ) | TypeRef::UniMut( - TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) - | TypeId::AtomicTypeParameter(_), + TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) + | TypeEnum::AtomicTypeParameter(_), ) => true, TypeRef::Placeholder(id) => { id.value(db).map_or(false, |v| v.is_type_parameter(db)) @@ -4413,17 +4420,17 @@ impl TypeRef { } pub fn is_rigid_type_parameter(self, db: &Database) -> bool { - matches!(self.type_id(db), Ok(TypeId::RigidTypeParameter(_))) + matches!(self.as_type_enum(db), Ok(TypeEnum::RigidTypeParameter(_))) } pub fn is_trait_instance(self, db: &Database) -> bool { match self { - TypeRef::Owned(TypeId::TraitInstance(_)) - | TypeRef::Uni(TypeId::TraitInstance(_)) - | TypeRef::Ref(TypeId::TraitInstance(_)) - | TypeRef::Mut(TypeId::TraitInstance(_)) - | TypeRef::UniRef(TypeId::TraitInstance(_)) - | TypeRef::UniMut(TypeId::TraitInstance(_)) => true, + TypeRef::Owned(TypeEnum::TraitInstance(_)) + | TypeRef::Uni(TypeEnum::TraitInstance(_)) + | TypeRef::Ref(TypeEnum::TraitInstance(_)) + | TypeRef::Mut(TypeEnum::TraitInstance(_)) + | TypeRef::UniRef(TypeEnum::TraitInstance(_)) + | TypeRef::UniMut(TypeEnum::TraitInstance(_)) => true, TypeRef::Placeholder(id) => { id.value(db).map_or(false, |v| v.is_trait_instance(db)) } @@ -4432,31 +4439,32 @@ impl TypeRef { } pub fn type_arguments(self, db: &Database) -> TypeArguments { - match self.type_id(db) { - Ok(TypeId::TraitInstance(ins)) + match self.as_type_enum(db) { + Ok(TypeEnum::TraitInstance(ins)) if ins.instance_of.is_generic(db) => { ins.type_arguments(db).unwrap().clone() } - Ok(TypeId::ClassInstance(ins)) + Ok(TypeEnum::TypeInstance(ins)) if ins.instance_of.is_generic(db) => { ins.type_arguments(db).unwrap().clone() } - Ok(TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id)) => { - id.requirements(db) - .into_iter() - .filter(|r| r.instance_of.is_generic(db)) - .fold(TypeArguments::new(), |mut targs, req| { - req.type_arguments(db).unwrap().copy_into(&mut targs); - req.instance_of() - .get(db) - .inherited_type_arguments - .copy_into(&mut targs); - - targs - }) - } + Ok( + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), + ) => id + .requirements(db) + .into_iter() + .filter(|r| r.instance_of.is_generic(db)) + .fold(TypeArguments::new(), |mut targs, req| { + req.type_arguments(db).unwrap().copy_into(&mut targs); + req.instance_of() + .get(db) + .inherited_type_arguments + .copy_into(&mut targs); + + targs + }), _ => TypeArguments::new(), } } @@ -4549,30 +4557,30 @@ impl TypeRef { } pub fn use_atomic_reference_counting(self, db: &Database) -> bool { - self.class_id(db).map_or(false, |id| id.is_atomic(db)) + self.type_id(db).map_or(false, |id| id.is_atomic(db)) } pub fn is_bool(self, db: &Database) -> bool { - self.is_instance_of(db, ClassId::boolean()) + self.is_instance_of(db, TypeId::boolean()) } pub fn is_int(self, db: &Database) -> bool { - self.is_instance_of(db, ClassId::int()) + self.is_instance_of(db, TypeId::int()) } pub fn is_string(self, db: &Database) -> bool { - self.is_instance_of(db, ClassId::string()) + self.is_instance_of(db, TypeId::string()) } pub fn is_nil(self, db: &Database) -> bool { - self.is_instance_of(db, ClassId::nil()) + self.is_instance_of(db, TypeId::nil()) } pub fn allow_moving(self, db: &Database) -> bool { match self { TypeRef::Owned(_) | TypeRef::Uni(_) => true, - TypeRef::UniRef(TypeId::ClassInstance(i)) - | TypeRef::UniMut(TypeId::ClassInstance(i)) => { + TypeRef::UniRef(TypeEnum::TypeInstance(i)) + | TypeRef::UniMut(TypeEnum::TypeInstance(i)) => { i.instance_of.is_stack_allocated(db) } TypeRef::Placeholder(id) => { @@ -4584,10 +4592,10 @@ impl TypeRef { pub fn allow_field_assignments(self, db: &Database) -> bool { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) - | TypeRef::Pointer(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) + | TypeRef::Pointer(TypeEnum::TypeInstance(ins)) => { ins.instance_of.allow_field_assignments(db) } TypeRef::Placeholder(id) => { @@ -4599,8 +4607,8 @@ impl TypeRef { pub fn allow_mutating(self, db: &Database) -> bool { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) => { ins.instance_of.allow_mutating(db) } TypeRef::Owned(_) @@ -4609,9 +4617,9 @@ impl TypeRef { | TypeRef::UniMut(_) | TypeRef::Pointer(_) => true, TypeRef::Any( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) => id.is_mutable(db), - TypeRef::Ref(TypeId::ClassInstance(ins)) => { + TypeRef::Ref(TypeEnum::TypeInstance(ins)) => { ins.instance_of.is_value_type(db) && !ins.instance_of().kind(db).is_async() } @@ -4622,22 +4630,22 @@ impl TypeRef { } } - pub fn as_class_instance_for_pattern_matching( + pub fn as_type_instance_for_pattern_matching( self, db: &Database, - ) -> Option { + ) -> Option { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::Ref(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::Ref(TypeEnum::TypeInstance(ins)) if ins.instance_of.kind(db).allow_pattern_matching() => { Some(ins) } TypeRef::Placeholder(id) => id .value(db) - .and_then(|v| v.as_class_instance_for_pattern_matching(db)), + .and_then(|v| v.as_type_instance_for_pattern_matching(db)), _ => None, } } @@ -4655,7 +4663,7 @@ impl TypeRef { pub fn is_sendable(self, db: &Database) -> bool { match self { TypeRef::Uni(_) | TypeRef::Never | TypeRef::Error => true, - TypeRef::Owned(TypeId::Closure(id)) => id.can_infer_as_uni(db), + TypeRef::Owned(TypeEnum::Closure(id)) => id.can_infer_as_uni(db), TypeRef::Placeholder(id) => { id.value(db).map_or(true, |v| v.is_sendable(db)) } @@ -4666,10 +4674,10 @@ impl TypeRef { pub fn is_sendable_output(self, db: &Database) -> bool { match self { TypeRef::Uni(_) | TypeRef::Never | TypeRef::Error => true, - TypeRef::Owned(TypeId::ClassInstance(id)) => { - let class = id.instance_of; + TypeRef::Owned(TypeEnum::TypeInstance(id)) => { + let typ = id.instance_of; - if class.is_generic(db) + if typ.is_generic(db) && !id .type_arguments(db) .unwrap() @@ -4679,8 +4687,7 @@ impl TypeRef { return false; } - class - .fields(db) + typ.fields(db) .into_iter() .all(|f| f.value_type(db).is_sendable_output(db)) } @@ -4721,23 +4728,23 @@ impl TypeRef { pub fn as_ref(self, db: &Database) -> Self { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of().kind(db).is_extern() => { - TypeRef::Pointer(TypeId::ClassInstance(ins)) + TypeRef::Pointer(TypeEnum::TypeInstance(ins)) } - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of().is_copy_type(db) => { - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) } - TypeRef::Owned(TypeId::Foreign(_)) => self, + TypeRef::Owned(TypeEnum::Foreign(_)) => self, TypeRef::Owned(id) | TypeRef::Any(id) | TypeRef::Mut(id) | TypeRef::Ref(id) => match id { - TypeId::TypeParameter(pid) - | TypeId::RigidTypeParameter(pid) + TypeEnum::TypeParameter(pid) + | TypeEnum::RigidTypeParameter(pid) if pid.is_copy(db) => { TypeRef::Owned(id) @@ -4774,8 +4781,8 @@ impl TypeRef { pub fn as_mut(self, db: &Database) -> Self { match self { TypeRef::Any( - id @ TypeId::RigidTypeParameter(pid) - | id @ TypeId::TypeParameter(pid), + id @ TypeEnum::RigidTypeParameter(pid) + | id @ TypeEnum::TypeParameter(pid), ) => { if pid.is_copy(db) { TypeRef::Owned(id) @@ -4786,12 +4793,12 @@ impl TypeRef { } } TypeRef::Owned( - id @ TypeId::RigidTypeParameter(pid) - | id @ TypeId::TypeParameter(pid), + id @ TypeEnum::RigidTypeParameter(pid) + | id @ TypeEnum::TypeParameter(pid), ) | TypeRef::Mut( - id @ TypeId::RigidTypeParameter(pid) - | id @ TypeId::TypeParameter(pid), + id @ TypeEnum::RigidTypeParameter(pid) + | id @ TypeEnum::TypeParameter(pid), ) => { if pid.is_copy(db) { TypeRef::Owned(id) @@ -4800,20 +4807,20 @@ impl TypeRef { } } TypeRef::Uni( - id @ TypeId::RigidTypeParameter(pid) - | id @ TypeId::TypeParameter(pid), + id @ TypeEnum::RigidTypeParameter(pid) + | id @ TypeEnum::TypeParameter(pid), ) if pid.is_copy(db) => TypeRef::Owned(id), - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of().kind(db).is_extern() => { - TypeRef::Pointer(TypeId::ClassInstance(ins)) + TypeRef::Pointer(TypeEnum::TypeInstance(ins)) } - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of().is_value_type(db) => { - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) } - TypeRef::Owned(TypeId::Foreign(_)) => self, + TypeRef::Owned(TypeEnum::Foreign(_)) => self, TypeRef::Owned(id) => TypeRef::Mut(id), TypeRef::Uni(id) => TypeRef::UniMut(id), TypeRef::Placeholder(id) => { @@ -4829,21 +4836,21 @@ impl TypeRef { pub fn force_as_mut(self, db: &Database) -> Self { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of().kind(db).is_extern() => { - TypeRef::Pointer(TypeId::ClassInstance(ins)) + TypeRef::Pointer(TypeEnum::TypeInstance(ins)) } - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of().is_value_type(db) => { - TypeRef::Owned(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) } - TypeRef::Owned(TypeId::Foreign(_)) => self, + TypeRef::Owned(TypeEnum::Foreign(_)) => self, TypeRef::Owned(id) | TypeRef::Any(id) | TypeRef::Mut(id) => { match id { - TypeId::TypeParameter(tid) - | TypeId::RigidTypeParameter(tid) + TypeEnum::TypeParameter(tid) + | TypeEnum::RigidTypeParameter(tid) if tid.is_copy(db) => { TypeRef::Owned(id) @@ -4852,8 +4859,8 @@ impl TypeRef { } } TypeRef::Uni(id) => match id { - TypeId::TypeParameter(tid) - | TypeId::RigidTypeParameter(tid) + TypeEnum::TypeParameter(tid) + | TypeEnum::RigidTypeParameter(tid) if tid.is_copy(db) => { TypeRef::Owned(id) @@ -5009,12 +5016,12 @@ impl TypeRef { } } - pub fn as_enum_instance(self, db: &Database) -> Option { + pub fn as_enum_instance(self, db: &Database) -> Option { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) - | TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) + | TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) if ins.instance_of.kind(db).is_enum() => { Some(ins) @@ -5024,43 +5031,43 @@ impl TypeRef { } pub fn as_trait_instance(self, db: &Database) -> Option { - if let Ok(TypeId::TraitInstance(ins)) = self.type_id(db) { + if let Ok(TypeEnum::TraitInstance(ins)) = self.as_type_enum(db) { Some(ins) } else { None } } - pub fn as_class_instance(self, db: &Database) -> Option { - if let Ok(TypeId::ClassInstance(ins)) = self.type_id(db) { + pub fn as_type_instance(self, db: &Database) -> Option { + if let Ok(TypeEnum::TypeInstance(ins)) = self.as_type_enum(db) { Some(ins) } else { None } } - pub fn as_class(self, db: &Database) -> Option { + pub fn as_type(self, db: &Database) -> Option { match self { - TypeRef::Owned(TypeId::Class(id)) => Some(id), - TypeRef::Owned(TypeId::Module(id)) => Some(id.class(db)), + TypeRef::Owned(TypeEnum::Type(id)) => Some(id), + TypeRef::Owned(TypeEnum::Module(id)) => Some(id.type_id(db)), _ => None, } } pub fn as_type_parameter(self, db: &Database) -> Option { match self { - TypeRef::Owned(TypeId::TypeParameter(id)) - | TypeRef::Uni(TypeId::TypeParameter(id)) - | TypeRef::Ref(TypeId::TypeParameter(id)) - | TypeRef::Mut(TypeId::TypeParameter(id)) - | TypeRef::Any(TypeId::TypeParameter(id)) - | TypeRef::Owned(TypeId::RigidTypeParameter(id)) - | TypeRef::Uni(TypeId::RigidTypeParameter(id)) - | TypeRef::Ref(TypeId::RigidTypeParameter(id)) - | TypeRef::Mut(TypeId::RigidTypeParameter(id)) - | TypeRef::UniRef(TypeId::RigidTypeParameter(id)) - | TypeRef::UniMut(TypeId::RigidTypeParameter(id)) - | TypeRef::Any(TypeId::RigidTypeParameter(id)) => Some(id), + TypeRef::Owned(TypeEnum::TypeParameter(id)) + | TypeRef::Uni(TypeEnum::TypeParameter(id)) + | TypeRef::Ref(TypeEnum::TypeParameter(id)) + | TypeRef::Mut(TypeEnum::TypeParameter(id)) + | TypeRef::Any(TypeEnum::TypeParameter(id)) + | TypeRef::Owned(TypeEnum::RigidTypeParameter(id)) + | TypeRef::Uni(TypeEnum::RigidTypeParameter(id)) + | TypeRef::Ref(TypeEnum::RigidTypeParameter(id)) + | TypeRef::Mut(TypeEnum::RigidTypeParameter(id)) + | TypeRef::UniRef(TypeEnum::RigidTypeParameter(id)) + | TypeRef::UniMut(TypeEnum::RigidTypeParameter(id)) + | TypeRef::Any(TypeEnum::RigidTypeParameter(id)) => Some(id), TypeRef::Placeholder(id) => { id.value(db).and_then(|v| v.as_type_parameter(db)) } @@ -5070,12 +5077,12 @@ impl TypeRef { pub fn fields(self, db: &Database) -> Vec { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::UniRef(TypeId::ClassInstance(ins)) - | TypeRef::UniMut(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::UniRef(TypeEnum::TypeInstance(ins)) + | TypeRef::UniMut(TypeEnum::TypeInstance(ins)) => { ins.instance_of().fields(db) } TypeRef::Placeholder(id) => { @@ -5093,26 +5100,26 @@ impl TypeRef { pub fn as_rigid_type_parameter(self) -> TypeRef { match self { - TypeRef::Owned(TypeId::TypeParameter(id)) => { - TypeRef::Owned(TypeId::RigidTypeParameter(id)) + TypeRef::Owned(TypeEnum::TypeParameter(id)) => { + TypeRef::Owned(TypeEnum::RigidTypeParameter(id)) } - TypeRef::Any(TypeId::TypeParameter(id)) => { - TypeRef::Any(TypeId::RigidTypeParameter(id)) + TypeRef::Any(TypeEnum::TypeParameter(id)) => { + TypeRef::Any(TypeEnum::RigidTypeParameter(id)) } - TypeRef::Ref(TypeId::TypeParameter(id)) => { - TypeRef::Ref(TypeId::RigidTypeParameter(id)) + TypeRef::Ref(TypeEnum::TypeParameter(id)) => { + TypeRef::Ref(TypeEnum::RigidTypeParameter(id)) } - TypeRef::Mut(TypeId::TypeParameter(id)) => { - TypeRef::Mut(TypeId::RigidTypeParameter(id)) + TypeRef::Mut(TypeEnum::TypeParameter(id)) => { + TypeRef::Mut(TypeEnum::RigidTypeParameter(id)) } - TypeRef::Uni(TypeId::TypeParameter(id)) => { - TypeRef::Uni(TypeId::RigidTypeParameter(id)) + TypeRef::Uni(TypeEnum::TypeParameter(id)) => { + TypeRef::Uni(TypeEnum::RigidTypeParameter(id)) } - TypeRef::UniRef(TypeId::TypeParameter(id)) => { - TypeRef::UniRef(TypeId::RigidTypeParameter(id)) + TypeRef::UniRef(TypeEnum::TypeParameter(id)) => { + TypeRef::UniRef(TypeEnum::RigidTypeParameter(id)) } - TypeRef::UniMut(TypeId::TypeParameter(id)) => { - TypeRef::UniMut(TypeId::RigidTypeParameter(id)) + TypeRef::UniMut(TypeEnum::TypeParameter(id)) => { + TypeRef::UniMut(TypeEnum::RigidTypeParameter(id)) } _ => self, } @@ -5125,21 +5132,21 @@ impl TypeRef { /// etc), or non-values (e.g. modules). pub fn is_value_type(self, db: &Database) -> bool { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::UniRef(TypeId::ClassInstance(ins)) - | TypeRef::UniMut(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::UniRef(TypeEnum::TypeInstance(ins)) + | TypeRef::UniMut(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) => { ins.instance_of().is_value_type(db) } // Modules technically aren't values, but this allows certain checks // for value types (e.g. to see if `self` can be captured) to // automatically also handle modules. - TypeRef::Owned(TypeId::Module(_)) - | TypeRef::Ref(TypeId::Module(_)) - | TypeRef::Mut(TypeId::Module(_)) => true, - TypeRef::Owned(TypeId::Foreign(_)) => true, + TypeRef::Owned(TypeEnum::Module(_)) + | TypeRef::Ref(TypeEnum::Module(_)) + | TypeRef::Mut(TypeEnum::Module(_)) => true, + TypeRef::Owned(TypeEnum::Foreign(_)) => true, TypeRef::Pointer(_) => true, TypeRef::Placeholder(id) => { id.value(db).map_or(false, |v| v.is_value_type(db)) @@ -5157,12 +5164,12 @@ impl TypeRef { | TypeRef::Mut(id) | TypeRef::UniMut(id) | TypeRef::Any(id) => match id { - TypeId::ClassInstance(ins) => { + TypeEnum::TypeInstance(ins) => { ins.instance_of().is_copy_type(db) } - TypeId::TypeParameter(tid) - | TypeId::RigidTypeParameter(tid) => tid.is_copy(db), - TypeId::Foreign(_) => true, + TypeEnum::TypeParameter(tid) + | TypeEnum::RigidTypeParameter(tid) => tid.is_copy(db), + TypeEnum::Foreign(_) => true, _ => false, }, TypeRef::Error | TypeRef::Pointer(_) => true, @@ -5193,7 +5200,7 @@ impl TypeRef { | TypeRef::UniRef(id) | TypeRef::UniMut(id) | TypeRef::Any(id) => match id { - TypeId::ClassInstance(ins) + TypeEnum::TypeInstance(ins) if ins.instance_of.is_generic(db) => { ins.type_arguments(db) @@ -5202,7 +5209,7 @@ impl TypeRef { .values() .try_for_each(|v| v.verify_type(db, depth + 1)) } - TypeId::TraitInstance(ins) + TypeEnum::TraitInstance(ins) if ins.instance_of.is_generic(db) => { ins.type_arguments(db) @@ -5211,7 +5218,7 @@ impl TypeRef { .values() .try_for_each(|v| v.verify_type(db, depth + 1)) } - TypeId::Closure(id) => { + TypeEnum::Closure(id) => { id.arguments(db).into_iter().try_for_each(|arg| { arg.value_type.verify_type(db, depth + 1) })?; @@ -5229,43 +5236,43 @@ impl TypeRef { } } - pub fn class_id(self, db: &Database) -> Option { + pub fn type_id(self, db: &Database) -> Option { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) - | TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::UniMut(TypeId::ClassInstance(ins)) - | TypeRef::UniRef(TypeId::ClassInstance(ins)) - | TypeRef::Pointer(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) + | TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::UniMut(TypeEnum::TypeInstance(ins)) + | TypeRef::UniRef(TypeEnum::TypeInstance(ins)) + | TypeRef::Pointer(TypeEnum::TypeInstance(ins)) => { Some(ins.instance_of) } - TypeRef::Owned(TypeId::Class(id)) => Some(id), - TypeRef::Owned(TypeId::Module(id)) => Some(id.class(db)), - TypeRef::Placeholder(p) => p.value(db).and_then(|v| v.class_id(db)), + TypeRef::Owned(TypeEnum::Type(id)) => Some(id), + TypeRef::Owned(TypeEnum::Module(id)) => Some(id.type_id(db)), + TypeRef::Placeholder(p) => p.value(db).and_then(|v| v.type_id(db)), _ => None, } } pub fn throw_kind(self, db: &Database) -> ThrowKind { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) - | TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::UniMut(TypeId::ClassInstance(ins)) - | TypeRef::UniRef(TypeId::ClassInstance(ins)) => { - let opt_class = db.class_in_module(OPTION_MODULE, OPTION_CLASS); - let res_class = db.class_in_module(RESULT_MODULE, RESULT_CLASS); + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) + | TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::UniMut(TypeEnum::TypeInstance(ins)) + | TypeRef::UniRef(TypeEnum::TypeInstance(ins)) => { + let opt_typ = db.type_in_module(OPTION_MODULE, OPTION_TYPE); + let res_typ = db.type_in_module(RESULT_MODULE, RESULT_TYPE); let params = ins.instance_of.type_parameters(db); - if ins.instance_of == res_class { + if ins.instance_of == res_typ { let args = ins.type_arguments(db).unwrap(); let ok = args.get(params[0]).unwrap(); let err = args.get(params[1]).unwrap(); ThrowKind::Result(ok, err) - } else if ins.instance_of == opt_class { + } else if ins.instance_of == opt_typ { let args = ins.type_arguments(db).unwrap(); let some = args.get(params[0]).unwrap(); @@ -5286,27 +5293,27 @@ impl TypeRef { ok: TypeRef, error: TypeRef, ) -> TypeRef { - let class = db.class_in_module(RESULT_MODULE, RESULT_CLASS); - let params = class.type_parameters(db); + let tid = db.type_in_module(RESULT_MODULE, RESULT_TYPE); + let params = tid.type_parameters(db); let mut args = TypeArguments::new(); args.assign(params[0], ok); args.assign(params[1], error); - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::generic( - db, class, args, + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::generic( + db, tid, args, ))) } pub fn option_type(db: &mut Database, some: TypeRef) -> TypeRef { - let class = db.class_in_module(OPTION_MODULE, OPTION_CLASS); - let params = class.type_parameters(db); + let tid = db.type_in_module(OPTION_MODULE, OPTION_TYPE); + let params = tid.type_parameters(db); let mut args = TypeArguments::new(); args.assign(params[0], some); - TypeRef::Owned(TypeId::ClassInstance(ClassInstance::generic( - db, class, args, + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance::generic( + db, tid, args, ))) } @@ -5317,26 +5324,26 @@ impl TypeRef { shapes: &HashMap, ) -> Shape { match self { - TypeRef::Owned(TypeId::ClassInstance(ins)) - | TypeRef::Uni(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) + | TypeRef::Uni(TypeEnum::TypeInstance(ins)) => { ins.shape(db, interned, Shape::Owned) } - TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::UniMut(TypeId::ClassInstance(ins)) => { + TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::UniMut(TypeEnum::TypeInstance(ins)) => { ins.shape(db, interned, Shape::Mut) } - TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::UniRef(TypeId::ClassInstance(ins)) => { + TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::UniRef(TypeEnum::TypeInstance(ins)) => { ins.shape(db, interned, Shape::Ref) } TypeRef::Any( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) | TypeRef::Owned( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) | TypeRef::Uni( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) => { // We panic if a shape is missing, as encountering a missing // shape is the result of a compiler bug. @@ -5350,24 +5357,24 @@ impl TypeRef { } // These types are the result of specialization, so we can return // the shape directly instead of looking at `shapes`. - TypeRef::Owned(TypeId::AtomicTypeParameter(_)) - | TypeRef::Ref(TypeId::AtomicTypeParameter(_)) - | TypeRef::Mut(TypeId::AtomicTypeParameter(_)) => Shape::Atomic, + TypeRef::Owned(TypeEnum::AtomicTypeParameter(_)) + | TypeRef::Ref(TypeEnum::AtomicTypeParameter(_)) + | TypeRef::Mut(TypeEnum::AtomicTypeParameter(_)) => Shape::Atomic, TypeRef::Mut( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) | TypeRef::UniMut( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) => match shapes.get(&id).cloned() { Some(Shape::Owned) | None => Shape::Mut, Some(Shape::Inline(i)) => Shape::InlineMut(i), Some(shape) => shape, }, TypeRef::Ref( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) | TypeRef::UniRef( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) => match shapes.get(&id).cloned() { Some(Shape::Owned) | None => Shape::Ref, Some(Shape::Inline(i)) => Shape::InlineRef(i), @@ -5378,12 +5385,12 @@ impl TypeRef { TypeRef::Placeholder(id) => id .value(db) .map_or(Shape::Owned, |v| v.shape(db, interned, shapes)), - TypeRef::Owned(TypeId::Foreign(ForeignType::Int(size, sign))) - | TypeRef::Uni(TypeId::Foreign(ForeignType::Int(size, sign))) => { + TypeRef::Owned(TypeEnum::Foreign(ForeignType::Int(size, sign))) + | TypeRef::Uni(TypeEnum::Foreign(ForeignType::Int(size, sign))) => { Shape::Int(size, sign) } - TypeRef::Owned(TypeId::Foreign(ForeignType::Float(size))) - | TypeRef::Uni(TypeId::Foreign(ForeignType::Float(size))) => { + TypeRef::Owned(TypeEnum::Foreign(ForeignType::Float(size))) + | TypeRef::Uni(TypeEnum::Foreign(ForeignType::Float(size))) => { Shape::Float(size) } TypeRef::Pointer(_) => Shape::Pointer, @@ -5392,17 +5399,17 @@ impl TypeRef { } pub fn is_signed_int(self, db: &Database) -> bool { - let Ok(id) = self.type_id(db) else { return false }; + let Ok(id) = self.as_type_enum(db) else { return false }; match id { - TypeId::Foreign(ForeignType::Int(_, Sign::Signed)) => true, - TypeId::ClassInstance(ins) => ins.instance_of().0 == INT_ID, + TypeEnum::Foreign(ForeignType::Int(_, Sign::Signed)) => true, + TypeEnum::TypeInstance(ins) => ins.instance_of().0 == INT_ID, _ => false, } } - fn is_instance_of(self, db: &Database, id: ClassId) -> bool { - self.class_id(db) == Some(id) + fn is_instance_of(self, db: &Database, id: TypeId) -> bool { + self.type_id(db) == Some(id) } } @@ -5412,13 +5419,12 @@ pub enum ForeignType { Float(u32), } -/// An ID pointing to a type. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -pub enum TypeId { - Class(ClassId), +pub enum TypeEnum { + Type(TypeId), Trait(TraitId), Module(ModuleId), - ClassInstance(ClassInstance), + TypeInstance(TypeInstance), TraitInstance(TraitInstance), TypeParameter(TypeParameterId), RigidTypeParameter(TypeParameterId), @@ -5433,14 +5439,14 @@ pub enum TypeId { Foreign(ForeignType), } -impl TypeId { +impl TypeEnum { pub fn named_type(self, db: &mut Database, name: &str) -> Option { match self { - TypeId::Module(id) => id.use_symbol(db, name), - TypeId::Trait(id) => id.named_type(db, name), - TypeId::Class(id) => id.named_type(db, name), - TypeId::ClassInstance(id) => id.named_type(db, name), - TypeId::TraitInstance(id) => id.named_type(db, name), + TypeEnum::Module(id) => id.use_symbol(db, name), + TypeEnum::Trait(id) => id.named_type(db, name), + TypeEnum::Type(id) => id.named_type(db, name), + TypeEnum::TypeInstance(id) => id.named_type(db, name), + TypeEnum::TraitInstance(id) => id.named_type(db, name), _ => None, } } @@ -5456,7 +5462,7 @@ impl TypeId { let kind = id.kind(db); let is_ins = !matches!( self, - TypeId::Class(_) | TypeId::Trait(_) | TypeId::Module(_) + TypeEnum::Type(_) | TypeEnum::Trait(_) | TypeEnum::Module(_) ); if is_ins && kind.is_static() { @@ -5468,7 +5474,7 @@ impl TypeId { } else { MethodLookup::Private } - } else if let TypeId::Module(id) = self { + } else if let TypeEnum::Module(id) = self { id.extern_method(db, name) .map(MethodLookup::Ok) .unwrap_or(MethodLookup::None) @@ -5479,12 +5485,12 @@ impl TypeId { pub fn method(self, db: &Database, name: &str) -> Option { match self { - TypeId::Class(id) => id.method(db, name), - TypeId::Trait(id) => id.method(db, name), - TypeId::Module(id) => id.method(db, name), - TypeId::ClassInstance(id) => id.method(db, name), - TypeId::TraitInstance(id) => id.method(db, name), - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id) => { + TypeEnum::Type(id) => id.method(db, name), + TypeEnum::Trait(id) => id.method(db, name), + TypeEnum::Module(id) => id.method(db, name), + TypeEnum::TypeInstance(id) => id.method(db, name), + TypeEnum::TraitInstance(id) => id.method(db, name), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id) => { id.method(db, name) } _ => None, @@ -5494,14 +5500,14 @@ impl TypeId { pub fn use_dynamic_dispatch(self) -> bool { matches!( self, - TypeId::TraitInstance(_) - | TypeId::TypeParameter(_) - | TypeId::RigidTypeParameter(_) + TypeEnum::TraitInstance(_) + | TypeEnum::TypeParameter(_) + | TypeEnum::RigidTypeParameter(_) ) } pub fn has_destructor(self, db: &Database) -> bool { - if let TypeId::ClassInstance(id) = self { + if let TypeEnum::TypeInstance(id) = self { id.instance_of().has_destructor(db) } else { false @@ -5509,7 +5515,9 @@ impl TypeId { } pub fn as_type_for_pointer(self) -> TypeRef { - if let TypeId::TypeParameter(_) | TypeId::RigidTypeParameter(_) = self { + if let TypeEnum::TypeParameter(_) | TypeEnum::RigidTypeParameter(_) = + self + { TypeRef::Any(self) } else { TypeRef::Owned(self) @@ -5542,7 +5550,7 @@ pub struct Database { modules: Vec, module_mapping: HashMap, traits: Vec, - classes: Vec, + types: Vec, type_parameters: Vec, type_arguments: Vec, methods: Vec, @@ -5560,7 +5568,7 @@ pub struct Database { /// When just type-checking a project, this may be left as a None. main_module: Option, main_method: Option, - main_class: Option, + main_type: Option, } impl Database { @@ -5569,25 +5577,25 @@ impl Database { modules: Vec::new(), module_mapping: HashMap::new(), traits: Vec::new(), - classes: vec![ - Class::atomic(STRING_NAME.to_string()), - Class::regular(BYTE_ARRAY_NAME.to_string()), - Class::value_type(INT_NAME.to_string()), - Class::value_type(FLOAT_NAME.to_string()), - Class::value_type(BOOL_NAME.to_string()), - Class::value_type(NIL_NAME.to_string()), - Class::tuple(TUPLE1_NAME.to_string()), - Class::tuple(TUPLE2_NAME.to_string()), - Class::tuple(TUPLE3_NAME.to_string()), - Class::tuple(TUPLE4_NAME.to_string()), - Class::tuple(TUPLE5_NAME.to_string()), - Class::tuple(TUPLE6_NAME.to_string()), - Class::tuple(TUPLE7_NAME.to_string()), - Class::tuple(TUPLE8_NAME.to_string()), - Class::regular(ARRAY_NAME.to_string()), - Class::new( + types: vec![ + Type::atomic(STRING_NAME.to_string()), + Type::regular(BYTE_ARRAY_NAME.to_string()), + Type::value_type(INT_NAME.to_string()), + Type::value_type(FLOAT_NAME.to_string()), + Type::value_type(BOOL_NAME.to_string()), + Type::value_type(NIL_NAME.to_string()), + Type::tuple(TUPLE1_NAME.to_string()), + Type::tuple(TUPLE2_NAME.to_string()), + Type::tuple(TUPLE3_NAME.to_string()), + Type::tuple(TUPLE4_NAME.to_string()), + Type::tuple(TUPLE5_NAME.to_string()), + Type::tuple(TUPLE6_NAME.to_string()), + Type::tuple(TUPLE7_NAME.to_string()), + Type::tuple(TUPLE8_NAME.to_string()), + Type::regular(ARRAY_NAME.to_string()), + Type::new( CHECKED_INT_RESULT_NAME.to_string(), - ClassKind::Extern, + TypeKind::Extern, Visibility::Private, ModuleId(DEFAULT_BUILTIN_MODULE_ID), Location::default(), @@ -5605,7 +5613,7 @@ impl Database { constructors: Vec::new(), main_module: None, main_method: None, - main_class: None, + main_type: None, } } @@ -5617,24 +5625,24 @@ impl Database { self.type_arguments.shrink_to_fit(); } - pub fn builtin_class(&self, name: &str) -> Option { + pub fn builtin_type(&self, name: &str) -> Option { match name { - INT_NAME => Some(ClassId::int()), - FLOAT_NAME => Some(ClassId::float()), - STRING_NAME => Some(ClassId::string()), - ARRAY_NAME => Some(ClassId::array()), - BOOL_NAME => Some(ClassId::boolean()), - NIL_NAME => Some(ClassId::nil()), - BYTE_ARRAY_NAME => Some(ClassId::byte_array()), - TUPLE1_NAME => Some(ClassId::tuple1()), - TUPLE2_NAME => Some(ClassId::tuple2()), - TUPLE3_NAME => Some(ClassId::tuple3()), - TUPLE4_NAME => Some(ClassId::tuple4()), - TUPLE5_NAME => Some(ClassId::tuple5()), - TUPLE6_NAME => Some(ClassId::tuple6()), - TUPLE7_NAME => Some(ClassId::tuple7()), - TUPLE8_NAME => Some(ClassId::tuple8()), - CHECKED_INT_RESULT_NAME => Some(ClassId::checked_int_result()), + INT_NAME => Some(TypeId::int()), + FLOAT_NAME => Some(TypeId::float()), + STRING_NAME => Some(TypeId::string()), + ARRAY_NAME => Some(TypeId::array()), + BOOL_NAME => Some(TypeId::boolean()), + NIL_NAME => Some(TypeId::nil()), + BYTE_ARRAY_NAME => Some(TypeId::byte_array()), + TUPLE1_NAME => Some(TypeId::tuple1()), + TUPLE2_NAME => Some(TypeId::tuple2()), + TUPLE3_NAME => Some(TypeId::tuple3()), + TUPLE4_NAME => Some(TypeId::tuple4()), + TUPLE5_NAME => Some(TypeId::tuple5()), + TUPLE6_NAME => Some(TypeId::tuple6()), + TUPLE7_NAME => Some(TypeId::tuple7()), + TUPLE8_NAME => Some(TypeId::tuple8()), + CHECKED_INT_RESULT_NAME => Some(TypeId::checked_int_result()), _ => None, } } @@ -5655,12 +5663,11 @@ impl Database { self.module_mapping.get(name).cloned() } - pub fn class_in_module(&self, module: &str, name: &str) -> ClassId { - if let Some(Symbol::Class(id)) = self.module(module).symbol(self, name) - { + pub fn type_in_module(&self, module: &str, name: &str) -> TypeId { + if let Some(Symbol::Type(id)) = self.module(module).symbol(self, name) { id } else { - panic!("The class {}.{} isn't defined", module, name) + panic!("The type {}.{} isn't defined", module, name) } } @@ -5685,8 +5692,8 @@ impl Database { self.modules.len() } - pub fn number_of_classes(&self) -> usize { - self.classes.len() + pub fn number_of_types(&self) -> usize { + self.types.len() } pub fn number_of_methods(&self) -> usize { @@ -5709,12 +5716,12 @@ impl Database { self.main_method } - pub fn set_main_class(&mut self, id: ClassId) { - self.main_class = Some(id); + pub fn set_main_type(&mut self, id: TypeId) { + self.main_type = Some(id); } - pub fn main_class(&self) -> Option { - self.main_class + pub fn main_type(&self) -> Option { + self.main_type } } @@ -5723,9 +5730,9 @@ mod tests { use super::*; use crate::test::{ any, closure, generic_instance_id, generic_trait_instance, immutable, - immutable_uni, instance, mutable, mutable_uni, new_async_class, - new_class, new_enum_class, new_extern_class, new_module, new_parameter, - new_trait, owned, parameter, placeholder, pointer, rigid, + immutable_uni, instance, mutable, mutable_uni, new_async_type, + new_enum_type, new_extern_type, new_module, new_parameter, new_trait, + new_type, owned, parameter, placeholder, pointer, rigid, trait_instance, uni, }; use std::collections::hash_map::RandomState; @@ -5736,7 +5743,7 @@ mod tests { #[test] fn test_type_sizes() { - assert_eq!(size_of::(), 16); + assert_eq!(size_of::(), 16); assert_eq!(size_of::(), 24); assert_eq!(size_of::(), 8); } @@ -5935,61 +5942,61 @@ mod tests { } #[test] - fn test_class_alloc() { + fn test_type_alloc() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - assert_eq!(id.0, FIRST_USER_CLASS_ID); + assert_eq!(id.0, FIRST_USER_TYPE_ID); assert_eq!( - &db.classes[FIRST_USER_CLASS_ID as usize].name, + &db.types[FIRST_USER_TYPE_ID as usize].name, &"A".to_string() ); assert_eq!( - db.classes[FIRST_USER_CLASS_ID as usize].kind, - ClassKind::Regular + db.types[FIRST_USER_TYPE_ID as usize].kind, + TypeKind::Regular ); } #[test] - fn test_class_clone_for_specialization() { + fn test_type_clone_for_specialization() { let mut db = Database::new(); - let class1 = new_class(&mut db, "A"); + let type1 = new_type(&mut db, "A"); - class1.set_copy_storage(&mut db); + type1.set_copy_storage(&mut db); - let class2 = class1.clone_for_specialization(&mut db); + let type2 = type1.clone_for_specialization(&mut db); - assert!(class2.is_copy_type(&db)); + assert!(type2.is_copy_type(&db)); } #[test] - fn test_class_new() { - let class = Class::new( + fn test_type_new() { + let typ = Type::new( "A".to_string(), - ClassKind::Async, + TypeKind::Async, Visibility::Private, ModuleId(0), Location::default(), ); - assert_eq!(&class.name, &"A"); - assert_eq!(class.kind, ClassKind::Async); + assert_eq!(&typ.name, &"A"); + assert_eq!(typ.kind, TypeKind::Async); } #[test] - fn test_class_id_name() { + fn test_type_id_name() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -5999,36 +6006,36 @@ mod tests { } #[test] - fn test_class_id_is_async() { + fn test_type_id_is_async() { let mut db = Database::new(); - let regular_class = Class::alloc( + let regular_type = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let async_class = Class::alloc( + let async_type = Type::alloc( &mut db, "A".to_string(), - ClassKind::Async, + TypeKind::Async, Visibility::Private, ModuleId(0), Location::default(), ); - assert!(!regular_class.kind(&db).is_async()); - assert!(async_class.kind(&db).is_async()); + assert!(!regular_type.kind(&db).is_async()); + assert!(async_type.kind(&db).is_async()); } #[test] - fn test_class_id_new_type_parameter() { + fn test_type_id_new_type_parameter() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -6039,40 +6046,40 @@ mod tests { } #[test] - fn test_class_instance_new() { + fn test_type_instance_new() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let ins = ClassInstance::new(id); + let ins = TypeInstance::new(id); - assert_eq!(ins.instance_of.0, FIRST_USER_CLASS_ID); + assert_eq!(ins.instance_of.0, FIRST_USER_TYPE_ID); assert_eq!(ins.type_arguments, 0); } #[test] - fn test_class_instance_generic() { + fn test_type_instance_generic() { let mut db = Database::new(); - let id = Class::alloc( + let id = Type::alloc( &mut db, "A".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); - let ins1 = ClassInstance::generic(&mut db, id, TypeArguments::new()); - let ins2 = ClassInstance::generic(&mut db, id, TypeArguments::new()); + let ins1 = TypeInstance::generic(&mut db, id, TypeArguments::new()); + let ins2 = TypeInstance::generic(&mut db, id, TypeArguments::new()); - assert_eq!(ins1.instance_of.0, FIRST_USER_CLASS_ID); + assert_eq!(ins1.instance_of.0, FIRST_USER_TYPE_ID); assert_eq!(ins1.type_arguments, 0); - assert_eq!(ins2.instance_of.0, FIRST_USER_CLASS_ID); + assert_eq!(ins2.instance_of.0, FIRST_USER_TYPE_ID); assert_eq!(ins2.type_arguments, 1); } @@ -6244,7 +6251,7 @@ mod tests { let foo = new_module(&mut db, "foo"); let bar = new_module(&mut db, "bar"); let fizz = new_module(&mut db, "fizz"); - let class = new_class(&mut db, "A"); + let typ = new_type(&mut db, "A"); let trait_ = Trait::alloc( &mut db, "B".to_string(), @@ -6273,8 +6280,8 @@ mod tests { let type_param = TypeParameter::alloc(&mut db, "E".to_string()); - class.set_module(&mut db, foo); - foo.new_symbol(&mut db, "A".to_string(), Symbol::Class(class)); + typ.set_module(&mut db, foo); + foo.new_symbol(&mut db, "A".to_string(), Symbol::Type(typ)); foo.new_symbol(&mut db, "B".to_string(), Symbol::Trait(trait_)); foo.new_symbol(&mut db, "C".to_string(), Symbol::Constant(constant)); foo.new_symbol(&mut db, "D".to_string(), Symbol::Method(method)); @@ -6286,7 +6293,7 @@ mod tests { foo.new_symbol(&mut db, "fizz".to_string(), Symbol::Module(fizz)); - bar.new_symbol(&mut db, "A".to_string(), Symbol::Class(class)); + bar.new_symbol(&mut db, "A".to_string(), Symbol::Type(typ)); bar.new_symbol(&mut db, "B".to_string(), Symbol::Trait(trait_)); bar.new_symbol(&mut db, "C".to_string(), Symbol::Constant(constant)); bar.new_symbol(&mut db, "D".to_string(), Symbol::Method(method)); @@ -6297,7 +6304,7 @@ mod tests { ); assert_eq!(foo.import_symbol(&mut db, "unknown"), None); - assert_eq!(foo.import_symbol(&mut db, "A"), Some(Symbol::Class(class))); + assert_eq!(foo.import_symbol(&mut db, "A"), Some(Symbol::Type(typ))); assert_eq!(bar.import_symbol(&mut db, "A"), None); assert_eq!( foo.import_symbol(&mut db, "B"), @@ -6360,12 +6367,12 @@ mod tests { } #[test] - fn test_type_id_named_type_with_class() { + fn test_type_id_named_type_with_type() { let mut db = Database::new(); - let array = Class::alloc( + let array = Type::alloc( &mut db, "Array".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -6373,7 +6380,7 @@ mod tests { let param = array.new_type_parameter(&mut db, "T".to_string()); assert_eq!( - TypeId::Class(array).named_type(&mut db, "T"), + TypeEnum::Type(array).named_type(&mut db, "T"), Some(Symbol::TypeParameter(param)) ); } @@ -6391,7 +6398,7 @@ mod tests { let param = to_array.new_type_parameter(&mut db, "T".to_string()); assert_eq!( - TypeId::Trait(to_array).named_type(&mut db, "T"), + TypeEnum::Trait(to_array).named_type(&mut db, "T"), Some(Symbol::TypeParameter(param)) ); } @@ -6399,10 +6406,10 @@ mod tests { #[test] fn test_type_id_named_type_with_module() { let mut db = Database::new(); - let string = Class::alloc( + let string = Type::alloc( &mut db, "String".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), @@ -6410,8 +6417,8 @@ mod tests { let module = Module::alloc(&mut db, ModuleName::new("foo"), "foo.inko".into()); - let symbol = Symbol::Class(string); - let type_id = TypeId::Module(module); + let symbol = Symbol::Type(string); + let type_id = TypeEnum::Module(module); module.new_symbol(&mut db, "String".to_string(), symbol); @@ -6420,18 +6427,18 @@ mod tests { } #[test] - fn test_type_id_named_type_with_class_instance() { + fn test_type_id_named_type_with_type_instance() { let mut db = Database::new(); - let array = Class::alloc( + let array = Type::alloc( &mut db, "Array".to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Private, ModuleId(0), Location::default(), ); let param = array.new_type_parameter(&mut db, "T".to_string()); - let ins = TypeId::ClassInstance(ClassInstance::generic( + let ins = TypeEnum::TypeInstance(TypeInstance::generic( &mut db, array, TypeArguments::new(), @@ -6455,7 +6462,7 @@ mod tests { Location::default(), ); let param = to_array.new_type_parameter(&mut db, "T".to_string()); - let ins = TypeId::TraitInstance(TraitInstance::generic( + let ins = TypeEnum::TraitInstance(TraitInstance::generic( &mut db, to_array, TypeArguments::new(), @@ -6471,7 +6478,7 @@ mod tests { #[test] fn test_type_id_named_type_with_type_parameter() { let mut db = Database::new(); - let param = TypeId::TypeParameter(TypeParameter::alloc( + let param = TypeEnum::TypeParameter(TypeParameter::alloc( &mut db, "T".to_string(), )); @@ -6482,7 +6489,7 @@ mod tests { #[test] fn test_type_id_named_type_with_function() { let mut db = Database::new(); - let block = TypeId::Closure(Closure::alloc(&mut db, false)); + let block = TypeEnum::Closure(Closure::alloc(&mut db, false)); assert!(block.named_type(&mut db, "T").is_none()); } @@ -6491,13 +6498,13 @@ mod tests { fn test_database_new() { let db = Database::new(); - assert_eq!(&db.classes[INT_ID as usize].name, INT_NAME); - assert_eq!(&db.classes[FLOAT_ID as usize].name, FLOAT_NAME); - assert_eq!(&db.classes[STRING_ID as usize].name, STRING_NAME); - assert_eq!(&db.classes[ARRAY_ID as usize].name, ARRAY_NAME); - assert_eq!(&db.classes[BOOL_ID as usize].name, BOOL_NAME); - assert_eq!(&db.classes[NIL_ID as usize].name, NIL_NAME); - assert_eq!(&db.classes[BYTE_ARRAY_ID as usize].name, BYTE_ARRAY_NAME); + assert_eq!(&db.types[INT_ID as usize].name, INT_NAME); + assert_eq!(&db.types[FLOAT_ID as usize].name, FLOAT_NAME); + assert_eq!(&db.types[STRING_ID as usize].name, STRING_NAME); + assert_eq!(&db.types[ARRAY_ID as usize].name, ARRAY_NAME); + assert_eq!(&db.types[BOOL_ID as usize].name, BOOL_NAME); + assert_eq!(&db.types[NIL_ID as usize].name, NIL_NAME); + assert_eq!(&db.types[BYTE_ARRAY_ID as usize].name, BYTE_ARRAY_NAME); } #[test] @@ -6518,10 +6525,10 @@ mod tests { } #[test] - fn test_class_id_is_builtin() { - assert!(ClassId::int().is_builtin()); - assert!(!ClassId::tuple8().is_builtin()); - assert!(!ClassId(42).is_builtin()); + fn test_type_id_is_builtin() { + assert!(TypeId::int().is_builtin()); + assert!(!TypeId::tuple8().is_builtin()); + assert!(!TypeId(42).is_builtin()); } #[test] @@ -6542,7 +6549,7 @@ mod tests { fn test_type_placeholder_id_assign_with_ownership() { let mut db = Database::new(); let mut var = TypePlaceholder::alloc(&mut db, None); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); var.ownership = Ownership::Owned; var.assign(&mut db, immutable(instance(thing))); @@ -6588,7 +6595,7 @@ mod tests { #[test] fn test_type_ref_allow_as_ref() { let mut db = Database::new(); - let int = ClassId::int(); + let int = TypeId::int(); let var = TypePlaceholder::alloc(&mut db, None); let param = new_parameter(&mut db, "A"); @@ -6605,11 +6612,11 @@ mod tests { #[test] fn test_type_ref_as_ref() { let mut db = Database::new(); - let int = ClassId::int(); - let ext = new_extern_class(&mut db, "Extern"); + let int = TypeId::int(); + let ext = new_extern_type(&mut db, "Extern"); let p1 = new_parameter(&mut db, "A"); let p2 = new_parameter(&mut db, "A"); - let int32 = TypeId::Foreign(ForeignType::Int(32, Sign::Signed)); + let int32 = TypeEnum::Foreign(ForeignType::Int(32, Sign::Signed)); p2.set_copy(&mut db); @@ -6631,12 +6638,12 @@ mod tests { #[test] fn test_type_ref_as_mut() { let mut db = Database::new(); - let int = ClassId::int(); - let ext = new_extern_class(&mut db, "Extern"); + let int = TypeId::int(); + let ext = new_extern_type(&mut db, "Extern"); let p1 = new_parameter(&mut db, "A"); let p2 = new_parameter(&mut db, "A"); let p3 = new_parameter(&mut db, "A"); - let int32 = TypeId::Foreign(ForeignType::Int(32, Sign::Signed)); + let int32 = TypeEnum::Foreign(ForeignType::Int(32, Sign::Signed)); p2.set_mutable(&mut db); p3.set_copy(&mut db); @@ -6665,8 +6672,8 @@ mod tests { #[test] fn test_type_ref_as_pointer() { let mut db = Database::new(); - let int = ClassId::int(); - let ext = new_extern_class(&mut db, "Extern"); + let int = TypeId::int(); + let ext = new_extern_type(&mut db, "Extern"); let param = new_parameter(&mut db, "A"); let var = TypePlaceholder::alloc(&mut db, None); @@ -6691,7 +6698,7 @@ mod tests { let mut db = Database::new(); let func1 = Closure::alloc(&mut db, false); let func2 = Closure::alloc(&mut db, false); - let thing = new_class(&mut db, "Thing"); + let thing = new_type(&mut db, "Thing"); let var_type = immutable(instance(thing)); let loc = Location::default(); let var = @@ -6751,7 +6758,7 @@ mod tests { let mut db = Database::new(); let p1 = new_parameter(&mut db, "A"); let p2 = new_parameter(&mut db, "A"); - let int32 = TypeId::Foreign(ForeignType::Int(32, Sign::Signed)); + let int32 = TypeEnum::Foreign(ForeignType::Int(32, Sign::Signed)); p2.set_copy(&mut db); @@ -6788,8 +6795,8 @@ mod tests { #[test] fn test_type_ref_as_uni_reference() { let mut db = Database::new(); - let foo = new_class(&mut db, "Foo"); - let int = ClassId::int(); + let foo = new_type(&mut db, "Foo"); + let int = TypeId::int(); assert_eq!( owned(instance(foo)).as_uni_borrow(&db), @@ -6813,7 +6820,7 @@ mod tests { #[test] fn test_type_ref_as_uni_ref() { let mut db = Database::new(); - let foo = new_class(&mut db, "Foo"); + let foo = new_type(&mut db, "Foo"); assert_eq!( owned(instance(foo)).as_uni_ref(&db), @@ -6840,7 +6847,7 @@ mod tests { #[test] fn test_type_ref_as_uni_mut() { let mut db = Database::new(); - let foo = new_class(&mut db, "Foo"); + let foo = new_type(&mut db, "Foo"); assert_eq!( owned(instance(foo)).as_uni_mut(&db), @@ -6873,12 +6880,12 @@ mod tests { let mut db = Database::new(); let param1 = new_parameter(&mut db, "T"); let param2 = new_parameter(&mut db, "T"); - let proc = new_async_class(&mut db, "X"); + let proc = new_async_type(&mut db, "X"); param2.set_mutable(&mut db); - assert!(uni(instance(ClassId::string())).allow_mutating(&db)); - assert!(immutable(instance(ClassId::string())).allow_mutating(&db)); + assert!(uni(instance(TypeId::string())).allow_mutating(&db)); + assert!(immutable(instance(TypeId::string())).allow_mutating(&db)); assert!(mutable(parameter(param1)).allow_mutating(&db)); assert!(mutable(rigid(param1)).allow_mutating(&db)); assert!(owned(parameter(param1)).allow_mutating(&db)); @@ -6892,7 +6899,7 @@ mod tests { assert!(!immutable(instance(proc)).allow_mutating(&db)); assert!(!immutable(parameter(param1)).allow_mutating(&db)); - assert!(!owned(instance(ClassId::string())).allow_mutating(&db)); + assert!(!owned(instance(TypeId::string())).allow_mutating(&db)); assert!(!any(parameter(param1)).allow_mutating(&db)); assert!(!any(rigid(param1)).allow_mutating(&db)); assert!(!TypeRef::int().allow_mutating(&db)); @@ -6901,8 +6908,8 @@ mod tests { #[test] fn test_type_ref_allow_moving() { let mut db = Database::new(); - let heap = new_class(&mut db, "A"); - let stack = new_class(&mut db, "B"); + let heap = new_type(&mut db, "A"); + let stack = new_type(&mut db, "B"); stack.set_copy_storage(&mut db); @@ -6977,14 +6984,14 @@ mod tests { fn test_type_ref_shape() { let mut db = Database::new(); let mut inter = InternedTypeArguments::new(); - let string = ClassId::string(); - let int = ClassId::int(); - let float = ClassId::float(); - let boolean = ClassId::boolean(); - let cls1 = new_class(&mut db, "Thing"); - let cls2 = new_class(&mut db, "Foo"); - let cls3 = new_class(&mut db, "Bar"); - let ins = ClassInstance::new(cls1); + let string = TypeId::string(); + let int = TypeId::int(); + let float = TypeId::float(); + let boolean = TypeId::boolean(); + let cls1 = new_type(&mut db, "Thing"); + let cls2 = new_type(&mut db, "Foo"); + let cls3 = new_type(&mut db, "Bar"); + let ins = TypeInstance::new(cls1); let var = TypePlaceholder::alloc(&mut db, None); let p1 = new_parameter(&mut db, "T"); let p2 = new_parameter(&mut db, "X"); @@ -7051,17 +7058,17 @@ mod tests { Shape::int() ); assert_eq!( - owned(TypeId::AtomicTypeParameter(p2)) + owned(TypeEnum::AtomicTypeParameter(p2)) .shape(&db, &mut inter, &shapes), Shape::Atomic ); assert_eq!( - immutable(TypeId::AtomicTypeParameter(p2)) + immutable(TypeEnum::AtomicTypeParameter(p2)) .shape(&db, &mut inter, &shapes), Shape::Atomic ); assert_eq!( - mutable(TypeId::AtomicTypeParameter(p2)) + mutable(TypeEnum::AtomicTypeParameter(p2)) .shape(&db, &mut inter, &shapes), Shape::Atomic ); @@ -7099,63 +7106,63 @@ mod tests { Shape::Boolean ); assert_eq!( - owned(TypeId::Foreign(ForeignType::Int(32, Sign::Signed))) + owned(TypeEnum::Foreign(ForeignType::Int(32, Sign::Signed))) .shape(&db, &mut inter, &shapes), Shape::Int(32, Sign::Signed) ); assert_eq!( - owned(TypeId::Foreign(ForeignType::Int(32, Sign::Unsigned))) + owned(TypeEnum::Foreign(ForeignType::Int(32, Sign::Unsigned))) .shape(&db, &mut inter, &shapes), Shape::Int(32, Sign::Unsigned) ); assert_eq!( - uni(TypeId::Foreign(ForeignType::Int(32, Sign::Unsigned))) + uni(TypeEnum::Foreign(ForeignType::Int(32, Sign::Unsigned))) .shape(&db, &mut inter, &shapes), Shape::Int(32, Sign::Unsigned) ); assert_eq!( - owned(TypeId::Foreign(ForeignType::Float(32))) + owned(TypeEnum::Foreign(ForeignType::Float(32))) .shape(&db, &mut inter, &shapes), Shape::Float(32) ); assert_eq!( - owned(TypeId::Foreign(ForeignType::Float(64))) + owned(TypeEnum::Foreign(ForeignType::Float(64))) .shape(&db, &mut inter, &shapes), Shape::Float(64) ); assert_eq!( - uni(TypeId::Foreign(ForeignType::Float(64))) + uni(TypeEnum::Foreign(ForeignType::Float(64))) .shape(&db, &mut inter, &shapes), Shape::Float(64) ); assert_eq!( - pointer(TypeId::Foreign(ForeignType::Int(64, Sign::Signed))) + pointer(TypeEnum::Foreign(ForeignType::Int(64, Sign::Signed))) .shape(&db, &mut inter, &shapes), Shape::Pointer ); assert_eq!( owned(instance(cls2)).shape(&db, &mut inter, &shapes), - Shape::Copy(ClassInstance::new(cls2)) + Shape::Copy(TypeInstance::new(cls2)) ); assert_eq!( mutable(instance(cls2)).shape(&db, &mut inter, &shapes), - Shape::Copy(ClassInstance::new(cls2)) + Shape::Copy(TypeInstance::new(cls2)) ); assert_eq!( immutable(instance(cls2)).shape(&db, &mut inter, &shapes), - Shape::Copy(ClassInstance::new(cls2)) + Shape::Copy(TypeInstance::new(cls2)) ); assert_eq!( owned(instance(cls3)).shape(&db, &mut inter, &shapes), - Shape::Inline(ClassInstance::new(cls3)) + Shape::Inline(TypeInstance::new(cls3)) ); assert_eq!( mutable(instance(cls3)).shape(&db, &mut inter, &shapes), - Shape::InlineMut(ClassInstance::new(cls3)) + Shape::InlineMut(TypeInstance::new(cls3)) ); assert_eq!( immutable(instance(cls3)).shape(&db, &mut inter, &shapes), - Shape::InlineRef(ClassInstance::new(cls3)) + Shape::InlineRef(TypeInstance::new(cls3)) ); assert_eq!( owned(parameter(p3)).shape(&db, &mut inter, &shapes), @@ -7172,18 +7179,18 @@ mod tests { } #[test] - fn test_type_ref_class_id() { + fn test_type_ref_type_id() { let db = Database::new(); - assert_eq!(TypeRef::string().class_id(&db), Some(ClassId::string())); + assert_eq!(TypeRef::string().type_id(&db), Some(TypeId::string())); assert_eq!( - owned(TypeId::Class(ClassId::string())).class_id(&db), - Some(ClassId::string()) + owned(TypeEnum::Type(TypeId::string())).type_id(&db), + Some(TypeId::string()) ); } #[test] - fn test_method_id_receiver_for_class_instance_with_process() { + fn test_method_id_receiver_for_type_instance_with_process() { let mut db = Database::new(); let method = Method::alloc( &mut db, @@ -7194,9 +7201,9 @@ mod tests { MethodKind::Mutable, ); - let proc = new_async_class(&mut db, "A"); + let proc = new_async_type(&mut db, "A"); let rec = - method.receiver_for_class_instance(&db, ClassInstance::new(proc)); + method.receiver_for_type_instance(&db, TypeInstance::new(proc)); assert_eq!(rec, mutable(instance(proc))); } @@ -7212,9 +7219,9 @@ mod tests { } #[test] - fn test_type_ref_is_stack_class_instance() { + fn test_type_ref_is_stack_type_instance() { let mut db = Database::new(); - let ext = new_extern_class(&mut db, "A"); + let ext = new_extern_type(&mut db, "A"); assert!(owned(instance(ext)).is_extern_instance(&db)); assert!(uni(instance(ext)).is_extern_instance(&db)); @@ -7224,34 +7231,34 @@ mod tests { } #[test] - fn test_class_id_allow_cast() { + fn test_type_id_allow_cast() { let mut db = Database::new(); - let enum_class = new_enum_class(&mut db, "Option"); - let regular_class = new_class(&mut db, "Regular"); - let tuple_class = Class::alloc( + let enum_type = new_enum_type(&mut db, "Option"); + let regular_type = new_type(&mut db, "Regular"); + let tuple_type = Type::alloc( &mut db, "Tuple1".to_string(), - ClassKind::Tuple, + TypeKind::Tuple, Visibility::Public, ModuleId(0), Location::default(), ); - assert!(!ClassId::int().allow_cast_to_trait(&db)); - assert!(!ClassId::float().allow_cast_to_trait(&db)); - assert!(!ClassId::boolean().allow_cast_to_trait(&db)); - assert!(!ClassId::nil().allow_cast_to_trait(&db)); - assert!(!ClassId::string().allow_cast_to_trait(&db)); - assert!(enum_class.allow_cast_to_trait(&db)); - assert!(tuple_class.allow_cast_to_trait(&db)); - assert!(regular_class.allow_cast_to_trait(&db)); + assert!(!TypeId::int().allow_cast_to_trait(&db)); + assert!(!TypeId::float().allow_cast_to_trait(&db)); + assert!(!TypeId::boolean().allow_cast_to_trait(&db)); + assert!(!TypeId::nil().allow_cast_to_trait(&db)); + assert!(!TypeId::string().allow_cast_to_trait(&db)); + assert!(enum_type.allow_cast_to_trait(&db)); + assert!(tuple_type.allow_cast_to_trait(&db)); + assert!(regular_type.allow_cast_to_trait(&db)); } #[test] fn test_interned_type_arguments() { let mut db = Database::new(); let mut intern = InternedTypeArguments::new(); - let ary = ClassId::array(); + let ary = TypeId::array(); let ary_spec = ary.clone_for_specialization(&mut db); let int = TypeRef::int(); let p1 = ary.new_type_parameter(&mut db, "A".to_string()); @@ -7279,9 +7286,9 @@ mod tests { targs2.assign(p2, TypeRef::int()); targs2.assign(p1, val2); - let ins1 = ClassInstance::generic(&mut db, ary, targs1.clone()); - let ins2 = ClassInstance::generic(&mut db, ary, targs2); - let ins3 = ClassInstance::generic(&mut db, ary_spec, targs1); + let ins1 = TypeInstance::generic(&mut db, ary, targs1.clone()); + let ins2 = TypeInstance::generic(&mut db, ary, targs2); + let ins3 = TypeInstance::generic(&mut db, ary_spec, targs1); let id1 = intern.intern(&db, ins1); let id2 = intern.intern(&db, ins2); let id3 = intern.intern(&db, ins1); @@ -7297,10 +7304,9 @@ mod tests { #[test] fn test_shape_eq() { - let ins1 = ClassInstance { instance_of: ClassId(1), type_arguments: 0 }; - let ins2 = - ClassInstance { instance_of: ClassId(1), type_arguments: 10 }; - let ins3 = ClassInstance { instance_of: ClassId(2), type_arguments: 0 }; + let ins1 = TypeInstance { instance_of: TypeId(1), type_arguments: 0 }; + let ins2 = TypeInstance { instance_of: TypeId(1), type_arguments: 10 }; + let ins3 = TypeInstance { instance_of: TypeId(2), type_arguments: 0 }; assert_eq!(Shape::Inline(ins1), Shape::Inline(ins2)); assert_ne!(Shape::Inline(ins1), Shape::Inline(ins3)); @@ -7321,10 +7327,9 @@ mod tests { #[test] fn test_shape_hash() { let state = RandomState::new(); - let ins1 = ClassInstance { instance_of: ClassId(1), type_arguments: 0 }; - let ins2 = - ClassInstance { instance_of: ClassId(1), type_arguments: 10 }; - let ins3 = ClassInstance { instance_of: ClassId(2), type_arguments: 0 }; + let ins1 = TypeInstance { instance_of: TypeId(1), type_arguments: 0 }; + let ins2 = TypeInstance { instance_of: TypeId(1), type_arguments: 10 }; + let ins3 = TypeInstance { instance_of: TypeId(2), type_arguments: 0 }; assert_eq!( state.hash_one(Shape::Inline(ins1)), diff --git a/types/src/resolve.rs b/types/src/resolve.rs index c7e8c01e3..3882e6401 100644 --- a/types/src/resolve.rs +++ b/types/src/resolve.rs @@ -1,8 +1,8 @@ //! Resolving abstract types into concrete types. use crate::either::Either; use crate::{ - ClassInstance, Closure, Database, TraitId, TraitInstance, TypeArguments, - TypeBounds, TypeId, TypeParameterId, TypeRef, + Closure, Database, TraitId, TraitInstance, TypeArguments, TypeBounds, + TypeEnum, TypeInstance, TypeParameterId, TypeRef, }; use std::collections::HashMap; @@ -200,9 +200,9 @@ impl<'a> TypeResolver<'a> { resolved } - fn resolve_type_id(&mut self, id: TypeId) -> Either { + fn resolve_type_id(&mut self, id: TypeEnum) -> Either { match id { - TypeId::ClassInstance(ins) => { + TypeEnum::TypeInstance(ins) => { let base = ins.instance_of; if !base.is_generic(self.db) { @@ -213,11 +213,11 @@ impl<'a> TypeResolver<'a> { self.resolve_arguments(&mut args); - Either::Left(TypeId::ClassInstance(ClassInstance::generic( + Either::Left(TypeEnum::TypeInstance(TypeInstance::generic( self.db, base, args, ))) } - TypeId::TraitInstance(ins) => { + TypeEnum::TraitInstance(ins) => { let base = ins.instance_of; if !base.is_generic(self.db) { @@ -228,27 +228,27 @@ impl<'a> TypeResolver<'a> { self.resolve_arguments(&mut args); - Either::Left(TypeId::TraitInstance(TraitInstance::generic( + Either::Left(TypeEnum::TraitInstance(TraitInstance::generic( self.db, base, args, ))) } - TypeId::TypeParameter(pid) => { + TypeEnum::TypeParameter(pid) => { let pid = self.remap_type_parameter(pid); match self.resolve_type_parameter(pid) { Some(val) => Either::Right(val), _ if self.rigid => { - Either::Left(TypeId::RigidTypeParameter(pid)) + Either::Left(TypeEnum::RigidTypeParameter(pid)) } _ => { Either::Right(TypeRef::placeholder(self.db, Some(pid))) } } } - TypeId::RigidTypeParameter(pid) => Either::Left( - TypeId::RigidTypeParameter(self.remap_type_parameter(pid)), + TypeEnum::RigidTypeParameter(pid) => Either::Left( + TypeEnum::RigidTypeParameter(self.remap_type_parameter(pid)), ), - TypeId::Closure(id) => { + TypeEnum::Closure(id) => { let mut new = id.get(self.db).clone(); let immutable = self.immutable; @@ -264,7 +264,7 @@ impl<'a> TypeResolver<'a> { new.return_type = self.resolve_type_ref(new.return_type); self.immutable = immutable; - Either::Left(TypeId::Closure(Closure::add(self.db, new))) + Either::Left(TypeEnum::Closure(Closure::add(self.db, new))) } _ => Either::Left(id), } @@ -317,7 +317,7 @@ mod tests { pointer, rigid, type_arguments, type_bounds, uni, }; use crate::{ - Block, ClassId, Closure, Ownership, TypePlaceholder, TypePlaceholderId, + Block, Closure, Ownership, TypeId, TypePlaceholder, TypePlaceholderId, }; use location::Location; @@ -344,7 +344,7 @@ mod tests { #[test] fn test_owned() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -362,7 +362,7 @@ mod tests { #[test] fn test_pointer() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -393,8 +393,8 @@ mod tests { #[test] fn test_immutable_nested_type() { let mut db = Database::new(); - let array = ClassId::array(); - let int = ClassId::int(); + let array = TypeId::array(); + let int = TypeId::int(); array.new_type_parameter(&mut db, "T".to_string()); @@ -419,7 +419,7 @@ mod tests { #[test] fn test_infer() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -437,7 +437,7 @@ mod tests { #[test] fn test_uni() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -455,7 +455,7 @@ mod tests { #[test] fn test_ref() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -478,7 +478,7 @@ mod tests { #[test] fn test_ref_uni() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -501,7 +501,7 @@ mod tests { #[test] fn test_mut() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -524,7 +524,7 @@ mod tests { #[test] fn test_mut_uni() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); @@ -547,7 +547,7 @@ mod tests { #[test] fn test_placeholder() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let args = TypeArguments::new(); let bounds = TypeBounds::new(); let var1 = TypePlaceholder::alloc(&mut db, None); @@ -574,7 +574,7 @@ mod tests { #[test] fn test_type_parameter() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let param1 = new_parameter(&mut db, "A"); let param2 = new_parameter(&mut db, "B"); let args = type_arguments(vec![(param1, owned(instance(string)))]); @@ -614,7 +614,7 @@ mod tests { #[test] fn test_type_parameter_as_reference() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let param1 = new_parameter(&mut db, "A"); let param2 = new_parameter(&mut db, "B"); let args = type_arguments(vec![ @@ -657,7 +657,7 @@ mod tests { #[test] fn test_type_parameter_as_uni() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let param1 = new_parameter(&mut db, "A"); let param2 = new_parameter(&mut db, "B"); let args = type_arguments(vec![ @@ -700,7 +700,7 @@ mod tests { #[test] fn test_type_parameter_surrounding_trait() { let mut db = Database::new(); - let string = ClassId::string(); + let string = TypeId::string(); let to_foo = new_trait(&mut db, "ToFoo"); let to_bar = new_trait(&mut db, "ToBar"); let foo_param = to_foo.new_type_parameter(&mut db, "A".to_string()); @@ -730,10 +730,10 @@ mod tests { } #[test] - fn test_generic_class() { + fn test_generic_type() { let mut db = Database::new(); - let array = ClassId::array(); - let string = ClassId::string(); + let array = TypeId::array(); + let string = TypeId::string(); let param = new_parameter(&mut db, "A"); let array_param = array.new_type_parameter(&mut db, "T".to_string()); let args = type_arguments(vec![(param, owned(instance(string)))]); @@ -745,7 +745,7 @@ mod tests { )); let arg = match resolve(&mut db, &args, &bounds, input) { - TypeRef::Owned(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) => { ins.type_arguments(&db).unwrap().get(array_param).unwrap() } _ => TypeRef::Unknown, @@ -755,10 +755,10 @@ mod tests { } #[test] - fn test_generic_class_with_parameter_chain() { + fn test_generic_type_with_parameter_chain() { let mut db = Database::new(); - let array = ClassId::array(); - let string = ClassId::string(); + let array = TypeId::array(); + let string = TypeId::string(); let param1 = new_parameter(&mut db, "A"); let param2 = new_parameter(&mut db, "B"); let param3 = new_parameter(&mut db, "C"); @@ -776,7 +776,7 @@ mod tests { )); let arg = match resolve(&mut db, &args, &bounds, input) { - TypeRef::Owned(TypeId::ClassInstance(ins)) => { + TypeRef::Owned(TypeEnum::TypeInstance(ins)) => { ins.type_arguments(&db).unwrap().get(array_param).unwrap() } _ => TypeRef::Unknown, @@ -789,7 +789,7 @@ mod tests { fn test_generic_trait() { let mut db = Database::new(); let to_foo = new_trait(&mut db, "ToFoo"); - let string = ClassId::string(); + let string = TypeId::string(); let param = new_parameter(&mut db, "A"); let trait_param = to_foo.new_type_parameter(&mut db, "T".to_string()); let args = type_arguments(vec![(param, owned(instance(string)))]); @@ -801,7 +801,7 @@ mod tests { )); let arg = match resolve(&mut db, &args, &bounds, input) { - TypeRef::Owned(TypeId::TraitInstance(ins)) => { + TypeRef::Owned(TypeEnum::TraitInstance(ins)) => { ins.type_arguments(&db).unwrap().get(trait_param).unwrap() } _ => TypeRef::Unknown, @@ -830,7 +830,7 @@ mod tests { let bounds = TypeBounds::new(); let output = match resolve(&mut db, &args, &bounds, owned(closure(fun))) { - TypeRef::Owned(TypeId::Closure(id)) => id, + TypeRef::Owned(TypeEnum::Closure(id)) => id, _ => panic!("Expected the resolved value to be a closure"), }; diff --git a/types/src/specialize.rs b/types/src/specialize.rs index 619bb2dd2..9fe7901fd 100644 --- a/types/src/specialize.rs +++ b/types/src/specialize.rs @@ -1,6 +1,6 @@ use crate::{ - ClassId, ClassInstance, Database, InternedTypeArguments, Shape, - SpecializationKey, TypeId, TypeParameterId, TypeRef, + Database, InternedTypeArguments, Shape, SpecializationKey, TypeEnum, + TypeId, TypeInstance, TypeParameterId, TypeRef, }; use std::collections::HashMap; @@ -27,20 +27,20 @@ pub struct TypeSpecializer<'a, 'b, 'c> { db: &'a mut Database, interned: &'b mut InternedTypeArguments, - /// The list of classes created during type specialization. - classes: &'c mut Vec, + /// The list of types created during type specialization. + types: &'c mut Vec, /// A cache of existing shapes to use when encountering a type parameter. /// - /// When specializing a class, it may have fields or constructors that are + /// When specializing a type, it may have fields or constructors that are /// or contain its type parameter (e.g. `Array[T]` for a `Foo[T]`). When /// encountering such types, we need to reuse the shape of the type /// parameter as it was determined when creating the newly specialized - /// class. + /// type. shapes: &'b HashMap, /// The type `self` is an instance of. - self_type: ClassInstance, + self_type: TypeInstance, } impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { @@ -48,13 +48,13 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { db: &'a mut Database, interned: &'b mut InternedTypeArguments, shapes: &'b HashMap, - classes: &'c mut Vec, - self_type: ClassInstance, + types: &'c mut Vec, + self_type: TypeInstance, key: &mut Vec, ) { for shape in key { TypeSpecializer::specialize_shape( - db, interned, shapes, classes, self_type, shape, + db, interned, shapes, types, self_type, shape, ); } } @@ -63,8 +63,8 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { db: &'a mut Database, interned: &'b mut InternedTypeArguments, shapes: &'b HashMap, - classes: &'c mut Vec, - self_type: ClassInstance, + types: &'c mut Vec, + self_type: TypeInstance, shape: &mut Shape, ) { match shape { @@ -73,9 +73,9 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { | Shape::InlineRef(i) | Shape::InlineMut(i) => { *i = TypeSpecializer::new( - db, interned, shapes, classes, self_type, + db, interned, shapes, types, self_type, ) - .specialize_class_instance(*i); + .specialize_type_instance(*i); } _ => {} } @@ -85,10 +85,10 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { db: &'a mut Database, interned: &'b mut InternedTypeArguments, shapes: &'b HashMap, - classes: &'c mut Vec, - self_type: ClassInstance, + types: &'c mut Vec, + self_type: TypeInstance, ) -> TypeSpecializer<'a, 'b, 'c> { - TypeSpecializer { db, interned, shapes, classes, self_type } + TypeSpecializer { db, interned, shapes, types, self_type } } pub fn specialize(&mut self, value: TypeRef) -> TypeRef { @@ -98,30 +98,33 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { // whatever implements the trait. This is needed such that if e.g. a // closure captures `self` and `self` is a stack allocated type, the // closure is specialized correctly. - TypeRef::Owned(TypeId::TraitInstance(i)) if i.self_type => { - TypeRef::Owned(TypeId::ClassInstance(self.self_type)) + TypeRef::Owned(TypeEnum::TraitInstance(i)) if i.self_type => { + TypeRef::Owned(TypeEnum::TypeInstance(self.self_type)) } - TypeRef::Uni(TypeId::TraitInstance(i)) if i.self_type => { - TypeRef::Uni(TypeId::ClassInstance(self.self_type)) + TypeRef::Uni(TypeEnum::TraitInstance(i)) if i.self_type => { + TypeRef::Uni(TypeEnum::TypeInstance(self.self_type)) } - TypeRef::Ref(TypeId::TraitInstance(i)) if i.self_type => { - TypeRef::Ref(TypeId::ClassInstance(self.self_type)) + TypeRef::Ref(TypeEnum::TraitInstance(i)) if i.self_type => { + TypeRef::Ref(TypeEnum::TypeInstance(self.self_type)) } - TypeRef::Mut(TypeId::TraitInstance(i)) if i.self_type => { - TypeRef::Mut(TypeId::ClassInstance(self.self_type)) + TypeRef::Mut(TypeEnum::TraitInstance(i)) if i.self_type => { + TypeRef::Mut(TypeEnum::TypeInstance(self.self_type)) } // When specializing type parameters, we have to reuse existing // shapes if there are any. This leads to a bit of duplication, but // there's not really a way around that without making things more // complicated than they already are. TypeRef::Owned( - TypeId::TypeParameter(pid) | TypeId::RigidTypeParameter(pid), + TypeEnum::TypeParameter(pid) + | TypeEnum::RigidTypeParameter(pid), ) | TypeRef::Any( - TypeId::TypeParameter(pid) | TypeId::RigidTypeParameter(pid), + TypeEnum::TypeParameter(pid) + | TypeEnum::RigidTypeParameter(pid), ) | TypeRef::Uni( - TypeId::TypeParameter(pid) | TypeId::RigidTypeParameter(pid), + TypeEnum::TypeParameter(pid) + | TypeEnum::RigidTypeParameter(pid), ) => match self.shapes.get(&pid) { Some(&Shape::Int(size, sign)) => { TypeRef::int_with_sign(size, sign) @@ -133,24 +136,24 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { Some(Shape::Ref) => value.as_ref(self.db), Some(Shape::Mut) => value.force_as_mut(self.db), Some(Shape::Atomic) => { - TypeRef::Owned(TypeId::AtomicTypeParameter(pid)) + TypeRef::Owned(TypeEnum::AtomicTypeParameter(pid)) } Some(Shape::Inline(i) | Shape::Copy(i)) => TypeRef::Owned( - TypeId::ClassInstance(self.specialize_class_instance(*i)), + TypeEnum::TypeInstance(self.specialize_type_instance(*i)), ), Some(Shape::InlineRef(i)) => TypeRef::Ref( - TypeId::ClassInstance(self.specialize_class_instance(*i)), + TypeEnum::TypeInstance(self.specialize_type_instance(*i)), ), Some(Shape::InlineMut(i)) => TypeRef::Mut( - TypeId::ClassInstance(self.specialize_class_instance(*i)), + TypeEnum::TypeInstance(self.specialize_type_instance(*i)), ), _ => value, }, TypeRef::Ref( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) | TypeRef::UniRef( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) => match self.shapes.get(&id) { Some(&Shape::Int(size, sign)) => { TypeRef::int_with_sign(size, sign) @@ -160,25 +163,25 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { Some(Shape::String) => TypeRef::string(), Some(Shape::Nil) => TypeRef::nil(), Some(Shape::Atomic) => { - TypeRef::Ref(TypeId::AtomicTypeParameter(id)) + TypeRef::Ref(TypeEnum::AtomicTypeParameter(id)) } - Some(Shape::Copy(i)) => TypeRef::Owned(TypeId::ClassInstance( - self.specialize_class_instance(*i), + Some(Shape::Copy(i)) => TypeRef::Owned(TypeEnum::TypeInstance( + self.specialize_type_instance(*i), )), Some( Shape::Inline(i) | Shape::InlineRef(i) | Shape::InlineMut(i), - ) => TypeRef::Ref(TypeId::ClassInstance( - self.specialize_class_instance(*i), + ) => TypeRef::Ref(TypeEnum::TypeInstance( + self.specialize_type_instance(*i), )), _ => value.as_ref(self.db), }, TypeRef::Mut( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) | TypeRef::UniMut( - TypeId::TypeParameter(id) | TypeId::RigidTypeParameter(id), + TypeEnum::TypeParameter(id) | TypeEnum::RigidTypeParameter(id), ) => match self.shapes.get(&id) { Some(&Shape::Int(size, sign)) => { TypeRef::int_with_sign(size, sign) @@ -189,16 +192,16 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { Some(Shape::Nil) => TypeRef::nil(), Some(Shape::Ref) => value.as_ref(self.db), Some(Shape::Atomic) => { - TypeRef::Mut(TypeId::AtomicTypeParameter(id)) + TypeRef::Mut(TypeEnum::AtomicTypeParameter(id)) } - Some(Shape::Copy(i)) => TypeRef::Owned(TypeId::ClassInstance( - self.specialize_class_instance(*i), + Some(Shape::Copy(i)) => TypeRef::Owned(TypeEnum::TypeInstance( + self.specialize_type_instance(*i), )), Some(Shape::InlineRef(i)) => TypeRef::Ref( - TypeId::ClassInstance(self.specialize_class_instance(*i)), + TypeEnum::TypeInstance(self.specialize_type_instance(*i)), ), Some(Shape::Inline(i) | Shape::InlineMut(i)) => TypeRef::Mut( - TypeId::ClassInstance(self.specialize_class_instance(*i)), + TypeEnum::TypeInstance(self.specialize_type_instance(*i)), ), _ => value.force_as_mut(self.db), }, @@ -208,14 +211,14 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { TypeRef::Uni(id) => TypeRef::Uni(self.specialize_type_id(id)), // Value types should always be specialized as owned types, even // when using e.g. `ref Int`. - TypeRef::Ref(TypeId::ClassInstance(ins)) - | TypeRef::Mut(TypeId::ClassInstance(ins)) - | TypeRef::UniRef(TypeId::ClassInstance(ins)) - | TypeRef::UniMut(TypeId::ClassInstance(ins)) + TypeRef::Ref(TypeEnum::TypeInstance(ins)) + | TypeRef::Mut(TypeEnum::TypeInstance(ins)) + | TypeRef::UniRef(TypeEnum::TypeInstance(ins)) + | TypeRef::UniMut(TypeEnum::TypeInstance(ins)) if ins.instance_of().is_value_type(self.db) => { TypeRef::Owned( - self.specialize_type_id(TypeId::ClassInstance(ins)), + self.specialize_type_id(TypeEnum::TypeInstance(ins)), ) } TypeRef::Ref(id) => TypeRef::Ref(self.specialize_type_id(id)), @@ -232,21 +235,21 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { } } - fn specialize_type_id(&mut self, id: TypeId) -> TypeId { - if let TypeId::ClassInstance(ins) = id { - TypeId::ClassInstance(self.specialize_class_instance(ins)) + fn specialize_type_id(&mut self, id: TypeEnum) -> TypeEnum { + if let TypeEnum::TypeInstance(ins) = id { + TypeEnum::TypeInstance(self.specialize_type_instance(ins)) } else { id } } - pub fn specialize_class_instance( + pub fn specialize_type_instance( &mut self, - ins: ClassInstance, - ) -> ClassInstance { + ins: TypeInstance, + ) -> TypeInstance { let cls = ins.instance_of(); - // For closures we always specialize the classes, based on the + // For closures we always specialize the types, based on the // assumption that most (if not almost all closures) are likely to // capture generic types, and thus any "does this closure capture // generics?" check is likely to be true most of the time. Even if it's @@ -265,20 +268,20 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { #[allow(clippy::unnecessary_to_owned)] fn specialize_regular_instance( &mut self, - ins: ClassInstance, - ) -> ClassInstance { - let class = ins.instance_of(); + ins: TypeInstance, + ) -> TypeInstance { + let typ = ins.instance_of(); // For regular instances we only need to specialize the first reference. - if class.specialization_source(self.db).is_some() { + if typ.specialization_source(self.db).is_some() { return ins; } - class.set_specialization_source(self.db, class); - self.classes.push(class); + typ.set_specialization_source(self.db, typ); + self.types.push(typ); - if class.kind(self.db).is_enum() { - for var in class.constructors(self.db) { + if typ.kind(self.db).is_enum() { + for var in typ.constructors(self.db) { let args = var .arguments(self.db) .to_vec() @@ -288,7 +291,7 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { self.db, self.interned, self.shapes, - self.classes, + self.types, self.self_type, ) .specialize(v) @@ -299,13 +302,13 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { } } - for field in class.fields(self.db) { + for field in typ.fields(self.db) { let old = field.value_type(self.db); let new = TypeSpecializer::new( self.db, self.interned, self.shapes, - self.classes, + self.types, self.self_type, ) .specialize(old); @@ -318,16 +321,16 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { fn specialize_generic_instance( &mut self, - ins: ClassInstance, - ) -> ClassInstance { - let class = ins.instance_of; + ins: TypeInstance, + ) -> TypeInstance { + let typ = ins.instance_of; - if class.specialization_source(self.db).is_some() { + if typ.specialization_source(self.db).is_some() { return ins; } let mut args = ins.type_arguments(self.db).unwrap().clone(); - let mut shapes: Vec = class + let mut shapes: Vec = typ .type_parameters(self.db) .into_iter() .map(|p| { @@ -343,28 +346,28 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { self.db, self.interned, self.shapes, - self.classes, + self.types, self.self_type, &mut shapes, ); let key = SpecializationKey::new(shapes); - let new = class + let new = typ .specializations(self.db) .get(&key) .cloned() - .unwrap_or_else(|| self.specialize_class(class, key)); + .unwrap_or_else(|| self.specialize_type(typ, key)); // We keep the type arguments so we can perform type checking where // necessary during specialization (e.g. when checking if a stack type // implements a trait). - ClassInstance::generic(self.db, new, args) + TypeInstance::generic(self.db, new, args) } fn specialize_closure_instance( &mut self, - ins: ClassInstance, - ) -> ClassInstance { + ins: TypeInstance, + ) -> TypeInstance { // We don't check the specialization source for closures, as each // closure _always_ needs to be specialized, as its behaviour/layout may // change based on how the surrounding method is specialized. @@ -380,68 +383,68 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { self.db, self.interned, self.shapes, - self.classes, + self.types, self.self_type, &mut shapes, ); let key = SpecializationKey::for_closure(self.self_type, shapes); - let class = ins.instance_of; - let new = class + let typ = ins.instance_of; + let new = typ .specializations(self.db) .get(&key) .cloned() - .unwrap_or_else(|| self.specialize_class(class, key)); + .unwrap_or_else(|| self.specialize_type(typ, key)); - ClassInstance::new(new) + TypeInstance::new(new) } #[allow(clippy::unnecessary_to_owned)] - fn specialize_class( + fn specialize_type( &mut self, - class: ClassId, + type_id: TypeId, key: SpecializationKey, - ) -> ClassId { - let new = class.clone_for_specialization(self.db); + ) -> TypeId { + let new = type_id.clone_for_specialization(self.db); - self.classes.push(new); - new.set_specialization_source(self.db, class); + self.types.push(new); + new.set_specialization_source(self.db, type_id); // We just copy over the type parameters as-is, as there's nothing - // stored in them that we can't share between the different class + // stored in them that we can't share between the different type // specializations. - for param in class.type_parameters(self.db) { + for param in type_id.type_parameters(self.db) { let name = param.name(self.db).clone(); new.get_mut(self.db).type_parameters.insert(name, param); } - class.add_specialization(self.db, key, new); + type_id.add_specialization(self.db, key, new); // When specializing fields and constructors, we want them to reuse the // shapes we just created. - let mut class_mapping = HashMap::new(); + let mut type_mapping = HashMap::new(); // Closures may capture generic parameters from the outside, and the - // classes themselves aren't generic, so we reuse the outer shapes + // types themselves aren't generic, so we reuse the outer shapes // instead. - let kind = class.kind(self.db); + let kind = type_id.kind(self.db); let mapping = if kind.is_closure() { self.shapes } else { - for (param, &shape) in class + for (param, &shape) in type_id .type_parameters(self.db) .into_iter() .zip(new.shapes(self.db)) { - class_mapping.insert(param, shape); + type_mapping.insert(param, shape); } - &class_mapping + &type_mapping }; if kind.is_enum() { - for old_cons in class.constructors(self.db) { + for old_cons in type_id.constructors(self.db) { let name = old_cons.name(self.db).clone(); let loc = old_cons.location(self.db); let args = old_cons @@ -453,7 +456,7 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { self.db, self.interned, mapping, - self.classes, + self.types, self.self_type, ) .specialize(v) @@ -464,7 +467,8 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { } } - for (idx, old_field) in class.fields(self.db).into_iter().enumerate() { + for (idx, old_field) in type_id.fields(self.db).into_iter().enumerate() + { let (name, orig_typ, vis, module, loc) = { let field = old_field.get(self.db); @@ -481,7 +485,7 @@ impl<'a, 'b, 'c> TypeSpecializer<'a, 'b, 'c> { self.db, self.interned, mapping, - self.classes, + self.types, self.self_type, ) .specialize(orig_typ); @@ -498,30 +502,30 @@ mod tests { use super::*; use crate::format::format_type; use crate::test::{ - any, generic_instance_id, immutable, instance, mutable, new_class, - new_enum_class, new_parameter, new_trait, owned, parameter, rigid, uni, + any, generic_instance_id, immutable, instance, mutable, new_enum_type, + new_parameter, new_trait, new_type, owned, parameter, rigid, uni, }; - use crate::{ClassId, Location, ModuleId, TraitInstance, Visibility}; + use crate::{Location, ModuleId, TraitInstance, TypeId, Visibility}; #[test] fn test_specialize_type() { let mut db = Database::new(); let mut interned = InternedTypeArguments::new(); - let class = ClassId::array(); + let ary = TypeId::array(); let shapes = HashMap::new(); - class.new_type_parameter(&mut db, "T".to_string()); + ary.new_type_parameter(&mut db, "T".to_string()); let int = TypeRef::int(); - let raw1 = owned(generic_instance_id(&mut db, class, vec![int])); - let raw2 = owned(generic_instance_id(&mut db, class, vec![int])); - let mut classes = Vec::new(); - let stype = ClassInstance::new(ClassId::int()); + let raw1 = owned(generic_instance_id(&mut db, ary, vec![int])); + let raw2 = owned(generic_instance_id(&mut db, ary, vec![int])); + let mut types = Vec::new(); + let stype = TypeInstance::new(TypeId::int()); let spec1 = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(raw1); @@ -529,33 +533,33 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(raw2); assert_eq!(format_type(&db, spec1), "Array[Int]"); assert_eq!(format_type(&db, spec2), "Array[Int]"); - assert_eq!(class.specializations(&db).len(), 1); + assert_eq!(ary.specializations(&db).len(), 1); let key = SpecializationKey::new(vec![Shape::int()]); - let new_class = *class.specializations(&db).get(&key).unwrap(); + let new_type = *ary.specializations(&db).get(&key).unwrap(); - assert_eq!(classes, &[ClassId::int(), new_class]); - assert_eq!(new_class.specialization_source(&db), Some(class)); - assert_eq!(new_class.kind(&db), class.kind(&db)); - assert_eq!(new_class.get(&db).visibility, class.get(&db).visibility); - assert_eq!(new_class.module(&db), class.module(&db)); + assert_eq!(types, &[TypeId::int(), new_type]); + assert_eq!(new_type.specialization_source(&db), Some(ary)); + assert_eq!(new_type.kind(&db), ary.kind(&db)); + assert_eq!(new_type.get(&db).visibility, ary.get(&db).visibility); + assert_eq!(new_type.module(&db), ary.module(&db)); // This is to test if we reuse the cached results, instead of just - // creating a new specialized class every time. + // creating a new specialized type every time. assert!(matches!( spec1, - TypeRef::Owned(TypeId::ClassInstance(ins)) if ins.instance_of == new_class + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of == new_type )); assert!(matches!( spec2, - TypeRef::Owned(TypeId::ClassInstance(ins)) if ins.instance_of == new_class + TypeRef::Owned(TypeEnum::TypeInstance(ins)) if ins.instance_of == new_type )); } @@ -563,21 +567,21 @@ mod tests { fn test_specialize_pointer_type() { let mut db = Database::new(); let mut interned = InternedTypeArguments::new(); - let class = ClassId::array(); + let ary = TypeId::array(); let shapes = HashMap::new(); - class.new_type_parameter(&mut db, "T".to_string()); + ary.new_type_parameter(&mut db, "T".to_string()); let int = TypeRef::int(); let raw = - TypeRef::Pointer(generic_instance_id(&mut db, class, vec![int])); - let mut classes = Vec::new(); - let stype = ClassInstance::new(ClassId::int()); + TypeRef::Pointer(generic_instance_id(&mut db, ary, vec![int])); + let mut types = Vec::new(); + let stype = TypeInstance::new(TypeId::int()); let spec = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(raw); @@ -589,8 +593,8 @@ mod tests { fn test_specialize_type_with_ref_value_types() { let mut db = Database::new(); let mut interned = InternedTypeArguments::new(); - let foo = new_class(&mut db, "Foo"); - let ary = ClassId::array(); + let foo = new_type(&mut db, "Foo"); + let ary = TypeId::array(); let shapes = HashMap::new(); ary.new_type_parameter(&mut db, "T".to_string()); @@ -600,13 +604,13 @@ mod tests { ary, vec![immutable(instance(foo))], )); - let mut classes = Vec::new(); - let stype = ClassInstance::new(ClassId::int()); + let mut types = Vec::new(); + let stype = TypeInstance::new(TypeId::int()); let spec = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(raw); @@ -614,18 +618,18 @@ mod tests { assert_eq!(format_type(&db, spec), "Array[ref Foo]"); assert_eq!( spec, - TypeRef::Owned(TypeId::ClassInstance(ClassInstance { - instance_of: ClassId(db.number_of_classes() as u32 - 1), + TypeRef::Owned(TypeEnum::TypeInstance(TypeInstance { + instance_of: TypeId(db.number_of_types() as u32 - 1), type_arguments: 1, })) ); - assert_eq!(classes.len(), 2); + assert_eq!(types.len(), 2); } #[test] - fn test_specialize_class_with_fields() { + fn test_specialize_type_with_fields() { let mut db = Database::new(); - let tup = ClassId::tuple3(); + let tup = TypeId::tuple3(); let param1 = tup.new_type_parameter(&mut db, "A".to_string()); let param2 = tup.new_type_parameter(&mut db, "B".to_string()); let param3 = tup.new_type_parameter(&mut db, "C".to_string()); @@ -683,24 +687,24 @@ mod tests { )); let mut interned = InternedTypeArguments::new(); - let mut classes = Vec::new(); - let stype = ClassInstance::new(ClassId::int()); + let mut types = Vec::new(); + let stype = TypeInstance::new(TypeId::int()); let spec = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(raw); assert_eq!(format_type(&db, spec), "(Int, ref X, mut Y: mut)"); - assert_eq!(classes.len(), 2); + assert_eq!(types.len(), 2); - let ins = if let TypeRef::Owned(TypeId::ClassInstance(ins)) = spec { + let ins = if let TypeRef::Owned(TypeEnum::TypeInstance(ins)) = spec { ins } else { - panic!("Expected an owned class instance"); + panic!("Expected an owned type instance"); }; assert_ne!(ins.instance_of(), tup); @@ -722,9 +726,9 @@ mod tests { } #[test] - fn test_specialize_enum_class() { + fn test_specialize_enum_type() { let mut db = Database::new(); - let opt = new_enum_class(&mut db, "Option"); + let opt = new_enum_type(&mut db, "Option"); let opt_param = opt.new_type_parameter(&mut db, "T".to_string()); opt.new_constructor( @@ -742,28 +746,28 @@ mod tests { ); let mut interned = InternedTypeArguments::new(); - let mut classes = Vec::new(); + let mut types = Vec::new(); let shapes = HashMap::new(); let raw = owned(generic_instance_id(&mut db, opt, vec![TypeRef::int()])); - let stype = ClassInstance::new(ClassId::int()); + let stype = TypeInstance::new(TypeId::int()); let res = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(raw); - assert_eq!(classes.len(), 2); - assert!(classes[1].kind(&db).is_enum()); + assert_eq!(types.len(), 2); + assert!(types[1].kind(&db).is_enum()); - let ins = if let TypeRef::Owned(TypeId::ClassInstance(ins)) = res { + let ins = if let TypeRef::Owned(TypeEnum::TypeInstance(ins)) = res { ins } else { - panic!("Expected an owned class instance"); + panic!("Expected an owned type instance"); }; assert!(ins.instance_of().kind(&db).is_enum()); @@ -777,21 +781,21 @@ mod tests { #[test] fn test_specialize_already_specialized_type() { let mut db = Database::new(); - let class = ClassId::array(); + let ary = TypeId::array(); let shapes = HashMap::new(); - class.new_type_parameter(&mut db, "T".to_string()); + ary.new_type_parameter(&mut db, "T".to_string()); let int = TypeRef::int(); - let raw = owned(generic_instance_id(&mut db, class, vec![int])); - let mut classes = Vec::new(); + let raw = owned(generic_instance_id(&mut db, ary, vec![int])); + let mut types = Vec::new(); let mut interned = InternedTypeArguments::new(); - let stype = ClassInstance::new(ClassId::int()); + let stype = TypeInstance::new(TypeId::int()); let res1 = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(raw); @@ -800,31 +804,31 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(res1); assert_eq!(res1, res2); - assert_eq!(classes, &[ClassId::int(), res1.class_id(&db).unwrap()]); + assert_eq!(types, &[TypeId::int(), res1.type_id(&db).unwrap()]); } #[test] fn test_specialize_atomic_type_parameter() { let mut db = Database::new(); let mut shapes = HashMap::new(); - let mut classes = Vec::new(); + let mut types = Vec::new(); let mut interned = InternedTypeArguments::new(); let param = new_parameter(&mut db, "A"); shapes.insert(param, Shape::Atomic); - let stype = ClassInstance::new(ClassId::int()); + let stype = TypeInstance::new(TypeId::int()); let owned = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(owned(parameter(param))); @@ -833,7 +837,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(immutable(parameter(param))); @@ -842,32 +846,35 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(mutable(parameter(param))); - assert_eq!(owned, TypeRef::Owned(TypeId::AtomicTypeParameter(param))); - assert_eq!(immutable, TypeRef::Ref(TypeId::AtomicTypeParameter(param))); - assert_eq!(mutable, TypeRef::Mut(TypeId::AtomicTypeParameter(param))); + assert_eq!(owned, TypeRef::Owned(TypeEnum::AtomicTypeParameter(param))); + assert_eq!( + immutable, + TypeRef::Ref(TypeEnum::AtomicTypeParameter(param)) + ); + assert_eq!(mutable, TypeRef::Mut(TypeEnum::AtomicTypeParameter(param))); } #[test] fn test_specialize_mutable_type_parameter() { let mut db = Database::new(); let mut shapes = HashMap::new(); - let mut classes = Vec::new(); + let mut types = Vec::new(); let mut interned = InternedTypeArguments::new(); let param = new_parameter(&mut db, "A"); shapes.insert(param, Shape::Mut); - let stype = ClassInstance::new(ClassId::int()); + let stype = TypeInstance::new(TypeId::int()); let owned = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(owned(parameter(param))); @@ -876,7 +883,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(uni(parameter(param))); @@ -885,7 +892,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(immutable(parameter(param))); @@ -894,28 +901,28 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype, ) .specialize(mutable(parameter(param))); - assert_eq!(owned, TypeRef::Mut(TypeId::TypeParameter(param))); - assert_eq!(uni, TypeRef::UniMut(TypeId::TypeParameter(param))); - assert_eq!(immutable, TypeRef::Ref(TypeId::TypeParameter(param))); - assert_eq!(mutable, TypeRef::Mut(TypeId::TypeParameter(param))); + assert_eq!(owned, TypeRef::Mut(TypeEnum::TypeParameter(param))); + assert_eq!(uni, TypeRef::UniMut(TypeEnum::TypeParameter(param))); + assert_eq!(immutable, TypeRef::Ref(TypeEnum::TypeParameter(param))); + assert_eq!(mutable, TypeRef::Mut(TypeEnum::TypeParameter(param))); } #[test] fn test_specialize_borrow_inline_type_parameter() { let mut db = Database::new(); let mut shapes = HashMap::new(); - let mut classes = Vec::new(); + let mut types = Vec::new(); let mut interned = InternedTypeArguments::new(); - let cls = new_class(&mut db, "A"); - let ins = ClassInstance::new(cls); + let cls = new_type(&mut db, "A"); + let ins = TypeInstance::new(cls); let p1 = new_parameter(&mut db, "X"); let p2 = new_parameter(&mut db, "Y"); - let stype = ClassInstance::new(ClassId::int()); + let stype = TypeInstance::new(TypeId::int()); shapes.insert(p1, Shape::Inline(ins)); shapes.insert(p2, Shape::Copy(ins)); @@ -925,7 +932,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(owned(parameter(p1))), @@ -936,7 +943,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(uni(parameter(p1))), @@ -947,7 +954,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(mutable(parameter(p1))), @@ -958,7 +965,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(immutable(parameter(p1))), @@ -970,7 +977,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(owned(parameter(p2))), @@ -981,7 +988,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(owned(parameter(p2))), @@ -992,7 +999,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(mutable(parameter(p2))), @@ -1003,7 +1010,7 @@ mod tests { &mut db, &mut interned, &shapes, - &mut classes, + &mut types, stype ) .specialize(immutable(parameter(p2))), @@ -1015,38 +1022,38 @@ mod tests { fn test_specialize_trait_self_type() { let mut db = Database::new(); let shapes = HashMap::new(); - let mut classes = Vec::new(); + let mut types = Vec::new(); let mut interned = InternedTypeArguments::new(); let trt = new_trait(&mut db, "ToThing"); - let cls = new_class(&mut db, "Thing"); + let cls = new_type(&mut db, "Thing"); let mut old_self = TraitInstance::new(trt); old_self.self_type = true; - let new_self = ClassInstance::new(cls); + let new_self = TypeInstance::new(cls); let mut spec = TypeSpecializer::new( &mut db, &mut interned, &shapes, - &mut classes, + &mut types, new_self, ); assert_eq!( - spec.specialize(owned(TypeId::TraitInstance(old_self))), - owned(TypeId::ClassInstance(new_self)) + spec.specialize(owned(TypeEnum::TraitInstance(old_self))), + owned(TypeEnum::TypeInstance(new_self)) ); assert_eq!( - spec.specialize(immutable(TypeId::TraitInstance(old_self))), - immutable(TypeId::ClassInstance(new_self)) + spec.specialize(immutable(TypeEnum::TraitInstance(old_self))), + immutable(TypeEnum::TypeInstance(new_self)) ); assert_eq!( - spec.specialize(mutable(TypeId::TraitInstance(old_self))), - mutable(TypeId::ClassInstance(new_self)) + spec.specialize(mutable(TypeEnum::TraitInstance(old_self))), + mutable(TypeEnum::TypeInstance(new_self)) ); assert_eq!( - spec.specialize(uni(TypeId::TraitInstance(old_self))), - uni(TypeId::ClassInstance(new_self)) + spec.specialize(uni(TypeEnum::TraitInstance(old_self))), + uni(TypeEnum::TypeInstance(new_self)) ); } } diff --git a/types/src/test.rs b/types/src/test.rs index 405f38791..2b40169ac 100644 --- a/types/src/test.rs +++ b/types/src/test.rs @@ -1,7 +1,7 @@ use crate::{ - Class, ClassId, ClassInstance, ClassKind, ClosureId, Database, Location, - Module, ModuleId, ModuleName, Trait, TraitId, TraitImplementation, - TraitInstance, TypeArguments, TypeBounds, TypeId, TypeParameter, + ClosureId, Database, Location, Module, ModuleId, ModuleName, Trait, + TraitId, TraitImplementation, TraitInstance, Type, TypeArguments, + TypeBounds, TypeEnum, TypeId, TypeInstance, TypeKind, TypeParameter, TypeParameterId, TypePlaceholderId, TypeRef, Visibility, }; use std::path::PathBuf; @@ -10,44 +10,44 @@ pub(crate) fn new_module(db: &mut Database, name: &str) -> ModuleId { Module::alloc(db, ModuleName::new(name), PathBuf::from("foo.inko")) } -pub(crate) fn new_class(db: &mut Database, name: &str) -> ClassId { - Class::alloc( +pub(crate) fn new_type(db: &mut Database, name: &str) -> TypeId { + Type::alloc( db, name.to_string(), - ClassKind::Regular, + TypeKind::Regular, Visibility::Public, ModuleId(0), Location::default(), ) } -pub(crate) fn new_async_class(db: &mut Database, name: &str) -> ClassId { - Class::alloc( +pub(crate) fn new_async_type(db: &mut Database, name: &str) -> TypeId { + Type::alloc( db, name.to_string(), - ClassKind::Async, + TypeKind::Async, Visibility::Public, ModuleId(0), Location::default(), ) } -pub(crate) fn new_enum_class(db: &mut Database, name: &str) -> ClassId { - Class::alloc( +pub(crate) fn new_enum_type(db: &mut Database, name: &str) -> TypeId { + Type::alloc( db, name.to_string(), - ClassKind::Enum, + TypeKind::Enum, Visibility::Public, ModuleId(0), Location::default(), ) } -pub(crate) fn new_extern_class(db: &mut Database, name: &str) -> ClassId { - Class::alloc( +pub(crate) fn new_extern_type(db: &mut Database, name: &str) -> TypeId { + Type::alloc( db, name.to_string(), - ClassKind::Extern, + TypeKind::Extern, Visibility::Public, ModuleId(0), Location::default(), @@ -71,39 +71,39 @@ pub(crate) fn new_parameter(db: &mut Database, name: &str) -> TypeParameterId { pub(crate) fn implement( db: &mut Database, instance: TraitInstance, - class: ClassId, + type_id: TypeId, ) { - class.add_trait_implementation( + type_id.add_trait_implementation( db, TraitImplementation { instance, bounds: TypeBounds::new() }, ); } -pub(crate) fn owned(id: TypeId) -> TypeRef { +pub(crate) fn owned(id: TypeEnum) -> TypeRef { TypeRef::Owned(id) } -pub(crate) fn uni(id: TypeId) -> TypeRef { +pub(crate) fn uni(id: TypeEnum) -> TypeRef { TypeRef::Uni(id) } -pub(crate) fn immutable_uni(id: TypeId) -> TypeRef { +pub(crate) fn immutable_uni(id: TypeEnum) -> TypeRef { TypeRef::UniRef(id) } -pub(crate) fn mutable_uni(id: TypeId) -> TypeRef { +pub(crate) fn mutable_uni(id: TypeEnum) -> TypeRef { TypeRef::UniMut(id) } -pub(crate) fn any(id: TypeId) -> TypeRef { +pub(crate) fn any(id: TypeEnum) -> TypeRef { TypeRef::Any(id) } -pub(crate) fn immutable(id: TypeId) -> TypeRef { +pub(crate) fn immutable(id: TypeEnum) -> TypeRef { TypeRef::Ref(id) } -pub(crate) fn mutable(id: TypeId) -> TypeRef { +pub(crate) fn mutable(id: TypeEnum) -> TypeRef { TypeRef::Mut(id) } @@ -111,48 +111,48 @@ pub(crate) fn placeholder(id: TypePlaceholderId) -> TypeRef { TypeRef::Placeholder(id) } -pub(crate) fn pointer(id: TypeId) -> TypeRef { +pub(crate) fn pointer(id: TypeEnum) -> TypeRef { TypeRef::Pointer(id) } -pub(crate) fn instance(class: ClassId) -> TypeId { - TypeId::ClassInstance(ClassInstance::new(class)) +pub(crate) fn instance(type_id: TypeId) -> TypeEnum { + TypeEnum::TypeInstance(TypeInstance::new(type_id)) } -pub(crate) fn parameter(id: TypeParameterId) -> TypeId { - TypeId::TypeParameter(id) +pub(crate) fn parameter(id: TypeParameterId) -> TypeEnum { + TypeEnum::TypeParameter(id) } -pub(crate) fn rigid(id: TypeParameterId) -> TypeId { - TypeId::RigidTypeParameter(id) +pub(crate) fn rigid(id: TypeParameterId) -> TypeEnum { + TypeEnum::RigidTypeParameter(id) } -pub(crate) fn closure(id: ClosureId) -> TypeId { - TypeId::Closure(id) +pub(crate) fn closure(id: ClosureId) -> TypeEnum { + TypeEnum::Closure(id) } pub(crate) fn generic_instance_id( db: &mut Database, - class: ClassId, + type_id: TypeId, arguments: Vec, -) -> TypeId { +) -> TypeEnum { let mut args = TypeArguments::new(); for (param, arg) in - class.type_parameters(db).into_iter().zip(arguments.into_iter()) + type_id.type_parameters(db).into_iter().zip(arguments.into_iter()) { args.assign(param, arg); } - TypeId::ClassInstance(ClassInstance::generic(db, class, args)) + TypeEnum::TypeInstance(TypeInstance::generic(db, type_id, args)) } pub(crate) fn generic_trait_instance_id( db: &mut Database, trait_id: TraitId, arguments: Vec, -) -> TypeId { - TypeId::TraitInstance(generic_trait_instance(db, trait_id, arguments)) +) -> TypeEnum { + TypeEnum::TraitInstance(generic_trait_instance(db, trait_id, arguments)) } pub(crate) fn generic_trait_instance( @@ -175,8 +175,8 @@ pub(crate) fn trait_instance(trait_id: TraitId) -> TraitInstance { TraitInstance::new(trait_id) } -pub(crate) fn trait_instance_id(trait_id: TraitId) -> TypeId { - TypeId::TraitInstance(trait_instance(trait_id)) +pub(crate) fn trait_instance_id(trait_id: TraitId) -> TypeEnum { + TypeEnum::TraitInstance(trait_instance(trait_id)) } pub(crate) fn type_arguments(