mirror of
https://github.com/vlang/v.git
synced 2025-09-14 09:56:16 -04:00
checker: simplify unwrap nested selector fix (#23526)
This commit is contained in:
parent
facee322fc
commit
27f637a8dc
@ -926,7 +926,6 @@ pub:
|
|||||||
pos token.Pos
|
pos token.Pos
|
||||||
typ Type
|
typ Type
|
||||||
orig_type Type // original sumtype type; 0 if it's not a sumtype
|
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
|
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
|
// TODO: move this to a real docs site later
|
||||||
// 10 <- original type (orig_type)
|
// 10 <- original type (orig_type)
|
||||||
|
@ -157,16 +157,6 @@ pub fn (mut s Scope) register_struct_field(name string, field ScopeStructField)
|
|||||||
s.struct_fields[name] = field
|
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) {
|
pub fn (mut s Scope) register(obj ScopeObject) {
|
||||||
if !(obj.name == '_' || obj.name in s.objects) {
|
if !(obj.name == '_' || obj.name in s.objects) {
|
||||||
s.objects[obj.name] = obj
|
s.objects[obj.name] = obj
|
||||||
|
@ -4286,16 +4286,14 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast.
|
|||||||
orig_type = field.typ
|
orig_type = field.typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut nested_unwrap := false
|
expr_str := expr.expr.str()
|
||||||
if mut field := scope.find_struct_field(expr.expr.str(), expr.expr_type, expr.field_name) {
|
if mut field := scope.find_struct_field(expr_str, expr.expr_type, expr.field_name) {
|
||||||
smartcasts << field.smartcasts
|
smartcasts << field.smartcasts
|
||||||
nested_unwrap = smartcasts.len > 1
|
|
||||||
}
|
}
|
||||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
// 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) {
|
if !is_mut || expr.is_mut || is_option_unwrap || orig_type.has_flag(.option) {
|
||||||
smartcasts << to_type
|
smartcasts << to_type
|
||||||
if nested_unwrap {
|
scope.register_struct_field(expr_str, ast.ScopeStructField{
|
||||||
scope.register_or_update_struct_field(expr.expr.str(), ast.ScopeStructField{
|
|
||||||
struct_type: expr.expr_type
|
struct_type: expr.expr_type
|
||||||
name: expr.field_name
|
name: expr.field_name
|
||||||
typ: cur_type
|
typ: cur_type
|
||||||
@ -4303,16 +4301,6 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast.
|
|||||||
pos: expr.pos
|
pos: expr.pos
|
||||||
orig_type: orig_type
|
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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
c.smartcast_mut_pos = expr.pos
|
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