I’m getting the following warning when compiling my project and I’m not sure how to resolve it, because from what I see there is a proper pattern match
Warning
warning: a struct for Plug.Upload is expected on struct update:
%Plug.Upload{image | filename: random_filename(name)}
but got type:
dynamic()
where "image" was given the type:
# type: dynamic()
# from: my_file.ex:95:79
%{"image" => %Plug.Upload{filename: name} = image} = params
when defining the variable "image", you must also pattern match on "%Plug.Upload{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
96 │ image = %Plug.Upload{image | filename: random_filename(name)}
│ ~
│
└─ my_file.ex:96:13: MyModule.put_random_filename/1
Maybe I’m missing something but that doesn’t seem right to me. There was a lot of back-and-forth on what to do with the “struct update” syntax and I’m not sure what the final decision was there, but I feel like those examples should work, right?
Is there an official statement on that somewhere? I haven’t tried out 1.19 yet but this doesn’t match my understanding of either of the possibilities that were being considered. If it is the struct update syntax itself being deprecated shouldn’t the warning specifically say that rather than missing pattern match? Or what could be the point of warning about it if it’s not deprecated?
[Kernel] The struct update syntax, such as %URI{uri | path: "/foo/bar"}, now requires the given variable (or expression) to explicitly pattern match on the struct before it can be updated. This is because, thanks to the type system, pattern matching on structs can find more errors, more reliably, and we want to promote its usage. Once pattern matching is added, you may optionally convert the struct update syntax into the map update syntax %{uri | path: "/foo/bar"} with no less of typing guarantees
The syntax was going to be deprecated but that decision changed. In this commit the changelog was updated to suggest that the syntax is allowed but you must pattern match on the struct first. Which is what all of the examples in this thread are doing.
Personally I stopped using the struct update syntax in anticipation of this change several months ago, but that doesn’t mean the compiler should be spitting out nonsensical warnings! I think this is just a bug.