lang: funcs: Catch non-specific type build error

If you had ambiguous code, and specified an invalid type, this could
sneak through and become a runtime error, instead of a compile-time
error. We fix this and add a test.
This commit is contained in:
James Shubin
2024-07-31 16:01:27 -04:00
parent bfb5d983c1
commit 6de7d8b254
4 changed files with 23 additions and 2 deletions

View File

@@ -8,7 +8,7 @@ $ayear = 60 * 60 * 24 * 365 # is a year in seconds (31536000)
$tmplvalues = struct{year => $secplusone, load => $theload,}
$theload = sys.load()->x1
$theload float = sys.load()->x1 # ambiguous so we specify the type!
if 5 > 3 {
file "/tmp/mgmt/datetime" {

View File

@@ -9,7 +9,7 @@ $ayear = 60 * 60 * 24 * 365 # is a year in seconds (31536000)
$tmplvalues = struct{year => $secplusone, load => $theload, vumeter => $vumeter,}
$theload = sys.load()->x1
$theload float = sys.load()->x1 # ambiguous so we specify the type!
$vumeter = example.vumeter("====", 10, 0.9)

View File

@@ -193,6 +193,14 @@ func (obj *StructLookupFunc) Build(typ *types.Type) (*types.Type, error) {
if ix == -1 {
return nil, fmt.Errorf("field %s was not found in struct", obj.field)
}
tF, exists := tStruct.Map[tStruct.Ord[ix]]
if !exists {
return nil, fmt.Errorf("field %s was not found in struct", obj.field)
}
// The return value must match the type of the field we're pulling out!
if err := typ.Out.Cmp(tF); err != nil {
return nil, fmt.Errorf("field %s type error: %+v", obj.field, err)
}
obj.Type = tStruct // struct type
obj.Out = typ.Out // type of return value

View File

@@ -0,0 +1,13 @@
-- main.mcl --
import "sys"
$tmplvalues = struct{num => 42, load => $theload,}
$theload bool = sys.load()->x1 # wrong type, make sure the compiler catches it!
file "/tmp/datetime" {
state => $const.res.file.state.exists,
content => template("num: {{ .num }} seconds\nload average: {{ .load }}\n", $tmplvalues),
}
-- OUTPUT --
# err: errUnify: error setting type: func() { <built-in:_struct_lookup> }, error: field x1 type error: base kind does not match (bool != float)