mirror of
https://github.com/vlang/v.git
synced 2025-09-13 17:36:52 -04:00
checker: simplify unwrap nested selector fix (#23526)
This commit is contained in:
parent
facee322fc
commit
27f637a8dc
@ -925,9 +925,8 @@ pub:
|
||||
name string
|
||||
pos token.Pos
|
||||
typ Type
|
||||
orig_type Type // original sumtype type; 0 if it's not a sumtype
|
||||
pub mut:
|
||||
smartcasts []Type // nested sum types require nested smart casting, for that a list of types is needed
|
||||
orig_type Type // original sumtype type; 0 if it's not a sumtype
|
||||
smartcasts []Type // nested sum types require nested smart casting, for that a list of types is needed
|
||||
// TODO: move this to a real docs site later
|
||||
// 10 <- original type (orig_type)
|
||||
// [11, 12, 13] <- cast order (smartcasts)
|
||||
|
@ -157,16 +157,6 @@ pub fn (mut s Scope) register_struct_field(name string, field ScopeStructField)
|
||||
s.struct_fields[name] = field
|
||||
}
|
||||
|
||||
pub fn (mut s Scope) register_or_update_struct_field(name string, field ScopeStructField) {
|
||||
if mut f := s.struct_fields[name] {
|
||||
if f.struct_type == field.struct_type && f.name == field.name {
|
||||
s.struct_fields[name].smartcasts = field.smartcasts
|
||||
return
|
||||
}
|
||||
}
|
||||
s.struct_fields[name] = field
|
||||
}
|
||||
|
||||
pub fn (mut s Scope) register(obj ScopeObject) {
|
||||
if !(obj.name == '_' || obj.name in s.objects) {
|
||||
s.objects[obj.name] = obj
|
||||
|
@ -4286,33 +4286,21 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast.
|
||||
orig_type = field.typ
|
||||
}
|
||||
}
|
||||
mut nested_unwrap := false
|
||||
if mut field := scope.find_struct_field(expr.expr.str(), expr.expr_type, expr.field_name) {
|
||||
expr_str := expr.expr.str()
|
||||
if mut field := scope.find_struct_field(expr_str, expr.expr_type, expr.field_name) {
|
||||
smartcasts << field.smartcasts
|
||||
nested_unwrap = smartcasts.len > 1
|
||||
}
|
||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||
if !is_mut || expr.is_mut || is_option_unwrap || orig_type.has_flag(.option) {
|
||||
smartcasts << to_type
|
||||
if nested_unwrap {
|
||||
scope.register_or_update_struct_field(expr.expr.str(), ast.ScopeStructField{
|
||||
struct_type: expr.expr_type
|
||||
name: expr.field_name
|
||||
typ: cur_type
|
||||
smartcasts: smartcasts
|
||||
pos: expr.pos
|
||||
orig_type: orig_type
|
||||
})
|
||||
} else {
|
||||
scope.register_struct_field(expr.expr.str(), ast.ScopeStructField{
|
||||
struct_type: expr.expr_type
|
||||
name: expr.field_name
|
||||
typ: cur_type
|
||||
smartcasts: smartcasts
|
||||
pos: expr.pos
|
||||
orig_type: orig_type
|
||||
})
|
||||
}
|
||||
scope.register_struct_field(expr_str, ast.ScopeStructField{
|
||||
struct_type: expr.expr_type
|
||||
name: expr.field_name
|
||||
typ: cur_type
|
||||
smartcasts: smartcasts
|
||||
pos: expr.pos
|
||||
orig_type: orig_type
|
||||
})
|
||||
} else {
|
||||
c.smartcast_mut_pos = expr.pos
|
||||
}
|
||||
|
33
vlib/v/tests/options/option_generic_selector_unwrap_test.v
Normal file
33
vlib/v/tests/options/option_generic_selector_unwrap_test.v
Normal file
@ -0,0 +1,33 @@
|
||||
type SumType = int | string | f64
|
||||
|
||||
struct Foo[T] {
|
||||
field ?SumType
|
||||
}
|
||||
|
||||
fn t[T](val Foo[T]) {
|
||||
if val.field != none {
|
||||
if val.field is string {
|
||||
dump(val.field)
|
||||
assert val.field == 'foo'
|
||||
} else if val.field is int {
|
||||
dump(val.field)
|
||||
assert val.field == 1
|
||||
} else if val.field is f64 {
|
||||
dump(val.field)
|
||||
assert val.field == 1.23
|
||||
}
|
||||
} else {
|
||||
dump(val.field)
|
||||
assert val.field == none
|
||||
}
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
t(Foo[int]{})
|
||||
t(Foo[string]{})
|
||||
t(Foo[f64]{})
|
||||
|
||||
t(Foo[int]{ field: 1 })
|
||||
t(Foo[string]{ field: 'foo' })
|
||||
t(Foo[f64]{ field: 1.23 })
|
||||
}
|
46
vlib/v/tests/options/option_selector_nested_unwrap_test.v
Normal file
46
vlib/v/tests/options/option_selector_nested_unwrap_test.v
Normal file
@ -0,0 +1,46 @@
|
||||
module main
|
||||
|
||||
type Foo = string | int | f32
|
||||
|
||||
struct Svc {
|
||||
mut:
|
||||
log ?Foo
|
||||
}
|
||||
|
||||
fn t(v string) !string {
|
||||
return v
|
||||
}
|
||||
|
||||
fn Svc.init(log ?Foo) Svc {
|
||||
mut svc := Svc{
|
||||
log: log
|
||||
}
|
||||
if svc.log != none {
|
||||
if svc.log is string {
|
||||
assert svc.log.str() == 'foo'
|
||||
_ := t(svc.log) or { panic(err) }
|
||||
} else {
|
||||
assert false
|
||||
}
|
||||
assert true
|
||||
}
|
||||
return svc
|
||||
}
|
||||
|
||||
struct CSvc {
|
||||
Svc
|
||||
pub mut:
|
||||
log ?Foo
|
||||
}
|
||||
|
||||
pub fn CSvc.init(log ?Foo) CSvc {
|
||||
mut c := CSvc{
|
||||
log: log
|
||||
}
|
||||
c.Svc = Svc.init(log)
|
||||
return c
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
CSvc.init('foo')
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user