Skip to content

Commit 69b9ad7

Browse files
committed
Allow the use of 'Self' for creating instances
This (re)adds support for using 'Self' to create instances of types when used inside static or instance methods defined on a type. For example, you can now do this: type User { let @name: String fn static new(name: String) -> User { Self(name: name) } } This fixes #821. Changelog: added
1 parent 96d87f9 commit 69b9ad7

File tree

5 files changed

+66
-11
lines changed

5 files changed

+66
-11
lines changed

compiler/src/type_check/expressions.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use types::{
1717
IdentifierKind, IntrinsicCall, MethodId, MethodLookup, ModuleId, Receiver,
1818
Sign, Symbol, ThrowKind, TraitId, TraitInstance, TypeArguments, TypeBounds,
1919
TypeEnum, TypeId, TypeInstance, TypeRef, Variable, VariableId, CALL_METHOD,
20-
DEREF_POINTER_FIELD,
20+
DEREF_POINTER_FIELD, SELF_TYPE,
2121
};
2222

2323
const IGNORE_VARIABLE: &str = "_";
@@ -3788,6 +3788,20 @@ impl<'a> CheckMethodBody<'a> {
37883788
return TypeRef::Error;
37893789
}
37903790
MethodLookup::None => {
3791+
if name == SELF_TYPE {
3792+
match self.self_type {
3793+
TypeEnum::TypeInstance(ins) => {
3794+
let id = ins.instance_of();
3795+
3796+
return self.new_type_instance(node, scope, id);
3797+
}
3798+
TypeEnum::Type(id) => {
3799+
return self.new_type_instance(node, scope, id);
3800+
}
3801+
_ => {}
3802+
}
3803+
}
3804+
37913805
match self.module.use_symbol(self.db_mut(), name) {
37923806
Some(Symbol::Method(method)) => {
37933807
// The receiver of imported module methods is the

compiler/src/type_check/mod.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use types::format::format_type;
99
use types::{
1010
Block, Closure, Database, MethodId, ModuleId, Symbol, TraitId,
1111
TraitInstance, TypeArguments, TypeBounds, TypeEnum, TypeId, TypeInstance,
12-
TypeParameterId, TypeRef,
12+
TypeParameterId, TypeRef, NEVER_TYPE, SELF_TYPE,
1313
};
1414

1515
pub(crate) mod define_types;
@@ -333,35 +333,41 @@ impl<'a> DefineTypeSignature<'a> {
333333
// compared to physical types, so we handle them here rather than
334334
// handling them first.
335335
match name.as_str() {
336-
"Never" if !self.rules.allow_never => {
336+
NEVER_TYPE if !self.rules.allow_never => {
337337
self.state.diagnostics.error(
338338
DiagnosticId::InvalidType,
339-
"the 'Never' type can't be used in this context",
339+
format!(
340+
"the '{}' type can't be used in this context",
341+
NEVER_TYPE
342+
),
340343
self.file(),
341344
node.location,
342345
);
343346

344347
return TypeRef::Error;
345348
}
346-
"Never" => {
349+
NEVER_TYPE => {
347350
if kind == RefKind::Default {
348351
TypeRef::Never
349352
} else {
350353
self.state.diagnostics.error(
351354
DiagnosticId::InvalidType,
352-
"'Never' can't be borrowed",
355+
format!("'{}' can't be borrowed", NEVER_TYPE),
353356
self.file(),
354357
node.location,
355358
);
356359

357360
return TypeRef::Error;
358361
}
359362
}
360-
"Self" => {
363+
SELF_TYPE => {
361364
if !self.rules.allow_self {
362365
self.state.diagnostics.error(
363366
DiagnosticId::InvalidType,
364-
"the 'Self' type can't be used in this context",
367+
format!(
368+
"the '{}' type can't be used in this context",
369+
SELF_TYPE
370+
),
365371
self.file(),
366372
node.location,
367373
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
trait Trait {
2+
fn required -> Self
3+
4+
fn default -> Self
5+
}
6+
7+
type User {
8+
let @name: String
9+
10+
fn static example1 -> Self {
11+
Self(name: 'Alice')
12+
}
13+
14+
fn example2 -> Self {
15+
Self(name: 'Alice')
16+
}
17+
}
18+
19+
impl Trait for User {
20+
fn required -> Self {
21+
Self(name: 'Alice')
22+
}
23+
24+
fn default -> Self {
25+
Self(name: 'Alice')
26+
}
27+
}
28+
29+
fn example1 {
30+
Self(name: 'Alice')
31+
}
32+
33+
# new_instance_using_self_name.inko:30:3 error(invalid-symbol): the symbol 'Self' is undefined

types/src/format.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
Arguments, ClosureId, Database, ForeignType, Inline, MethodId, MethodKind,
44
ModuleId, Ownership, Sign, TraitId, TraitInstance, TypeArguments, TypeEnum,
55
TypeId, TypeInstance, TypeKind, TypeParameterId, TypePlaceholderId,
6-
TypeRef, Visibility,
6+
TypeRef, Visibility, NEVER_TYPE, SELF_TYPE,
77
};
88

99
const MAX_FORMATTING_DEPTH: usize = 8;
@@ -317,7 +317,7 @@ impl FormatType for TraitInstance {
317317
if self.self_type {
318318
match buffer.self_type {
319319
Some(TypeEnum::TraitInstance(_)) | None => {
320-
buffer.write("Self");
320+
buffer.write(SELF_TYPE);
321321
return;
322322
}
323323
Some(e) => return e.format_type(buffer),
@@ -487,7 +487,7 @@ impl FormatType for TypeRef {
487487

488488
id.format_type(buffer);
489489
}
490-
TypeRef::Never => buffer.write("Never"),
490+
TypeRef::Never => buffer.write(NEVER_TYPE),
491491
TypeRef::Error => buffer.write("<error>"),
492492
TypeRef::Unknown => buffer.write("<unknown>"),
493493
TypeRef::Placeholder(id) => id.format_type(buffer),

types/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ pub const RESULT_ERROR: &str = "Error";
9191
pub const ARRAY_WITH_CAPACITY: &str = "with_capacity";
9292
pub const ARRAY_PUSH: &str = "push";
9393
pub const ARRAY_INTERNAL_NAME: &str = "$Array";
94+
pub const SELF_TYPE: &str = "Self";
95+
pub const NEVER_TYPE: &str = "Never";
9496

9597
/// The name of the pseudo field used to deference a pointer.
9698
pub const DEREF_POINTER_FIELD: &str = "0";

0 commit comments

Comments
 (0)