Skip to content

Commit

Permalink
sema: fix strict type alias source type analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Jan 13, 2025
1 parent 194e67b commit 555e6ca
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 20 deletions.
1 change: 1 addition & 0 deletions std/jule/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Typical uses are things like capturing or tracing private behavior. For example,
**(10)** The `Scope` field of iteration or match expressions must be the first one. Accordingly, coverage data of the relevant type can be obtained by reinterpreting types such as `uintptr` with Unsafe Jule.
**(11)** Strict type aliases behave very similar to structs. For this reason, they are treated as a struct on CAST. They always have an instance. The data structure that represents a structure instance provides source type data that essentially contains what type it refers to. This data is only set if the structure was created by a strict type alias.
- **(11.1)** If a struct instance is created by a strict type alias (easily identified by looking at the source type data) and declared binded, the binded indicates that it was created by a strict type alias defined for a type. If a structure does not have source type data and the declaration is described as binded, this is a ordinary binded struct declaration.
- **(11.2)** To ensure that the created structure instance can be used consistently, the type should be checked using a type alias for the instance's type. If a strict type alias is used in the type check, the source type of the created structure instance should be assigned as the source to the structure instance encapsulated by the type alias. While this type alias is being checked, it provides the same struct instance to those referencing it, even though the analysis has not yet been completed. The type is distributed consistently, duplication is prevented, and type errors are avoided.

### Implicit Imports

Expand Down
44 changes: 28 additions & 16 deletions std/jule/sema/sema.jule
Original file line number Diff line number Diff line change
Expand Up @@ -629,12 +629,25 @@ impl sema {

// Checks TypeSYm, builds result as Type and collects referred type aliases.
// Skips already checked types.
// See also developer reference (11).
fn checkTypeSymWithRefers(mut &self, mut &t: &TypeSym, mut l: Lookup,
mut generics: []&TypeAlias, mut referencer: &referencer): (ok: bool) {
mut ta := false // Referencer owner is type alias.
if t.checked() {
ret true
match type referencer.owner {
| &TypeAlias:
ta = true
}
if !ta {
ret true
}
}
mut tt := self.buildTypeWithRefers(t.Decl, l, generics, referencer)
if tt == nil || !ta {
t.Type = tt
} else {
(&StructIns)(t.Type.Kind).setSource(tt)
}
t.Type = self.buildTypeWithRefers(t.Decl, l, generics, referencer)
ret t.checked()
}

Expand Down Expand Up @@ -1093,25 +1106,24 @@ impl sema {
// already checked
ret true
}
// Type alias is strict, make strict type alias analysis.
// See developer reference (11).
if ta.Strict {
mut s := initNewStructType(ta.Ident, nil)
s.Decl.sema = self
s.Decl.Binded = ta.Binded
s.Decl.Token = ta.Token
s.Decl.Public = ta.Public
ta.TypeSym.Type = &Type{Kind: s}
}
ok = self.checkTypeAliasDeclKind(ta, l)
if !ok {
ret false
}
if !ta.Strict {
if ta.Binded {
self.pushErr(ta.Token, build::LogMsg.BindedAsSoftType)
self.pushSuggestion(build::LogMsg.DefineAsStrictAlias, ta.Ident)
}
ret true
if !ta.Strict && ta.Binded {
self.pushErr(ta.Token, build::LogMsg.BindedAsSoftType)
self.pushSuggestion(build::LogMsg.DefineAsStrictAlias, ta.Ident)
}
// Type alias is strict, make strict type alias analysis.
// See developer reference (11).
mut s := initNewStructType(ta.Ident, ta.TypeSym.Type)
s.Decl.sema = self
s.Decl.Binded = ta.Binded
s.Decl.Token = ta.Token
s.Decl.Public = ta.Public
ta.TypeSym.Type = &Type{Kind: s}
ret true
}

Expand Down
10 changes: 10 additions & 0 deletions std/jule/sema/struct.jule
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,16 @@ impl Kind for StructIns {
}

impl StructIns {
// Sets source type.
fn setSource(mut self, mut t: &Type) {
if t == nil {
ret
}
self.Source = t
self.Comparable = t.Comparable()
self.Mutable = t.Mutable()
}

// Reports whether instances are same.
// Returns true if declarations and generics are same.
fn Same(self, s: &StructIns): bool {
Expand Down
7 changes: 3 additions & 4 deletions std/jule/sema/type.jule
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,8 @@ impl typeChecker {
}

// Build kind if not builded already.
if ta.TypeSym.Type == nil {
// If this type alias is checking now, do not check again.
if ta.TypeSym.Type == nil && self.ownerAlias != ta {
ok := self.s.checkTypeAliasDecl(ta, self.lookup)
if !ok {
ret nil
Expand Down Expand Up @@ -2019,8 +2020,6 @@ fn initNewStructType(ident: str, mut source: &Type): &StructIns {
s.Ident = ident
mut ins := s.instance()
s.appendInstance(ins)
ins.Source = source
ins.Comparable = source.Comparable()
ins.Mutable = source.Mutable()
ins.setSource(source)
ret ins
}

0 comments on commit 555e6ca

Please sign in to comment.