purpleidea / mgmt

Next generation distributed, event-driven, parallel config management!
https://purpleidea.com/tags/mgmtconfig/
GNU General Public License v3.0
3.65k stars 314 forks source link

Unify nested maps #778

Open purpleidea opened 5 days ago

purpleidea commented 5 days ago

Versions:

Current git master of: 43bd847badc134e9ba0a5ca8d3895735d523efa1

go version go1.22.7 linux/amd64

Description:

I'd expect the following code to unify automatically, but it does not. If we specify the type (as shown) then it works.

$bigmap = {
    "key1" => {
        "foo" => "thing1a",
        "bar" => "thing1b",
    },
    "key2" => {
        "foo" => "thing2a", # pull out this!
        "bar" => "thing2b",
    },
}

$key = "key2"

#$inner map{str: str} = $bigmap[$key] # does unify with the type hint!
$inner = $bigmap[$key] # doesn't unify!

print "debug" {
    msg => $inner["foo"],
}

You can easily run this with:

./mgmt run --tmp-prefix lang unify-bug-or-not.mcl

I also tried applying this patch in case, but it did not change the result:

diff --git lang/ast/structs.go lang/ast/structs.go
index a8b844bc6..f0d80447e 100644
--- lang/ast/structs.go
+++ lang/ast/structs.go
@@ -7689,6 +7689,15 @@ func (obj *ExprFunc) Infer() (*types.Type, []*interfaces.UnificationInvariant, e
                }
                invariants = append(invariants, invars...)

+               // XXX >>>
+               invarFoo := &interfaces.UnificationInvariant{
+                       Expr:   obj.params[i],
+                       Expect: typArg,
+                       Actual: typArg,
+               }
+               invariants = append(invariants, invarFoo)
+               // <<< XXX
+
                m[arg.Name] = typArg
                ord = append(ord, arg.Name)
        }
purpleidea commented 5 days ago

Btw, the error we get is:

cli parse error: could not unify types: expr: call:_lookup(var(bigmap), var(key)) is ambiguous: ?1