diff --git a/src/julec/opt/nil.jule b/src/julec/opt/nil.jule index 793e9cf33..863d49c87 100644 --- a/src/julec/opt/nil.jule +++ b/src/julec/opt/nil.jule @@ -3,7 +3,14 @@ // license that can be found in the LICENSE file. use std::jule::lex::{TokenId} -use std::jule::sema::{Var, StructSubIdentExprModel, UnaryExprModel, ExprModel, TypeKind} +use std::jule::sema::{ + Var, + TypeKind, + ExprModel, + StructSubIdentExprModel, + UnaryExprModel, + BuiltinNewCallExprModel, +} const invalidNil = 0x0 @@ -75,6 +82,14 @@ fn possibleNilRemove(mut &n: &nils, m: ExprModel) { } } +fn isGuaranteedNonNilExpr(mut &n: &nils, m: ExprModel): bool { + match type m { + | &BuiltinNewCallExprModel: + ret true + } + ret n != nil && n.isSafe(getNilVar(m)) +} + fn isNilValidType(mut t: &TypeKind): bool { ret t.Sptr() != nil } fn getNilVar(m: ExprModel): uintptr { diff --git a/src/julec/opt/scope.jule b/src/julec/opt/scope.jule index 8c5fea6d3..14866464c 100644 --- a/src/julec/opt/scope.jule +++ b/src/julec/opt/scope.jule @@ -118,6 +118,12 @@ impl scopeOptimizer { fn optimizeVar(mut &self, mut v: &Var) { if v.Value != nil { + if self.data.nils != nil && + isNilValidType(v.Kind.Kind) && + isGuaranteedNonNilExpr(self.data.nils, v.Value.Data.Model) { + const safe = true + self.data.nils.pushVar(getNilVar(v), safe) + } exprOptimizer.optimizeData(v.Value.Data.Model, self.data) } } @@ -390,7 +396,14 @@ impl scopeOptimizer { possibleBoundaryRemove(self.data.boundary, assign.L.Model) } if self.data.nils != nil { - possibleNilRemove(self.data.nils, assign.L.Model) + if isGuaranteedNonNilExpr(self.data.nils, assign.R.Model) { + if isNilValidType(assign.L.Kind) { + const safe = true + self.data.nils.pushVar(getNilVar(assign.L.Model), safe) + } + } else { + possibleNilRemove(self.data.nils, assign.L.Model) + } } match { @@ -505,11 +518,26 @@ impl scopeOptimizer { ret } - for (_, mut l) in assign.L { + mut tup := (&TupleExprModel)(nil) + match type assign.R { + | &TupleExprModel: + tup = (&TupleExprModel)(assign.R) + } + for (i, mut l) in assign.L { if l != nil { if self.data.boundary != nil { possibleBoundaryRemove(self.data.boundary, l.Model) } + if self.data.nils != nil { + if tup != nil && isGuaranteedNonNilExpr(self.data.nils, tup.Datas[i].Model) { + if isNilValidType(l.Kind) { + const safe = true + self.data.nils.pushVar(getNilVar(l.Model), safe) + } + } else { + possibleNilRemove(self.data.nils, l.Model) + } + } exprOptimizer.optimizeData(l.Model, self.data) } } diff --git a/std/jule/sema/scope.jule b/std/jule/sema/scope.jule index adb1a0b9b..844fd7d66 100644 --- a/std/jule/sema/scope.jule +++ b/std/jule/sema/scope.jule @@ -1425,15 +1425,6 @@ impl scopeChecker { }, } self.s.checkVarValue(v) - // Set value to nil. - // Because this variable should be uninitialized declaration. - // Otherwise, code generation needs more analysis. - // For references, leave values. References always should be initialized. - // So, some optimizations and utilities may use this rule. - if !v.Reference { - v.Value = nil - } - st.L = append(st.L, &Data{ Lvalue: !v.Constant, Mutable: v.Mutable,