Dialyzer errors with new opaque typespecs
doorgan opened this issue · 1 comments
doorgan commented
It seems the commit a2f7128 introduced new options structs and typespecs. Unfortunately, dialyzer doesn't seem to be happy about it
In a module with just the following code:
defmodule MyAppWeb.CORS do
use Corsica.Router
resource("/path/*", origins: "*")
end
I'm getting the following dialyzer error reports:
lib/my_app_web/cors.ex:1:call_without_opaque
Function call without opaqueness type mismatch.
Call does not have expected term of type Keyword.t() | Corsica.sanitized_options() (with opaque subterms) in the 2nd position.
Corsica.put_cors_simple_resp_headers(
_ :: %Plug.Conn{
:adapter => {atom(), _},
:assigns => %{atom() => _},
:body_params => %Plug.Conn.Unfetched{:aspect => atom(), binary() => _},
:cookies => %Plug.Conn.Unfetched{:aspect => atom(), binary() => _},
:halted => boolean(),
:host => binary(),
:method => binary(),
:owner => pid(),
:params => %Plug.Conn.Unfetched{:aspect => atom(), binary() => _},
:path_info => [binary()],
:path_params => %{
binary() =>
binary()
| [binary() | [any()] | %{binary() => _}]
| %{binary() => binary() | [any()] | %{binary() => _}}
},
:port => char(),
:private => %{atom() => _},
:query_params => %Plug.Conn.Unfetched{
:aspect => atom(),
binary() =>
binary()
| [binary() | [any()] | %{binary() => _}]
| %{binary() => binary() | [any()] | %{binary() => _}}
},
:query_string => binary(),
:remote_ip =>
{byte(), byte(), byte(), byte()}
| {char(), char(), char(), char(), char(), char(), char(), char()},
:req_cookies => %Plug.Conn.Unfetched{:aspect => atom(), binary() => binary()},
:req_headers => [{binary(), binary()}],
:request_path => binary(),
:resp_body =>
nil
| binary()
| maybe_improper_list(
binary() | maybe_improper_list(any(), binary() | []) | byte(),
binary() | []
),
:resp_cookies => %{binary() => map()},
:resp_headers => [{binary(), binary()}],
:scheme => :http | :https,
:script_name => [binary()],
:secret_key_base => nil | binary(),
:state =>
:chunked | :file | :sent | :set | :set_chunked | :set_file | :unset | :upgraded,
:status => nil | non_neg_integer()
},
%Corsica.Options{
:allow_credentials => false,
:allow_headers => [],
:allow_methods => [<<_::24, _::size(8)>>, ...],
:allow_private_network => false,
:expose_headers => nil,
:max_age => nil,
:origins => <<_::8>>,
:passthrough_non_cors_requests => false,
:telemetry_metadata => %{}
}
)
________________________________________________________________________________
lib/my_app_web/cors.ex:1:call_without_opaque
Function call without opaqueness type mismatch.
Call does not have expected term of type Keyword.t() | Corsica.sanitized_options() (with opaque subterms) in the 2nd position.
Corsica.send_preflight_resp(
_ :: %Plug.Conn{
:adapter => {atom(), _},
:assigns => %{atom() => _},
:body_params => %Plug.Conn.Unfetched{:aspect => atom(), binary() => _},
:cookies => %Plug.Conn.Unfetched{:aspect => atom(), binary() => _},
:halted => boolean(),
:host => binary(),
:method => binary(),
:owner => pid(),
:params => %Plug.Conn.Unfetched{:aspect => atom(), binary() => _},
:path_info => [binary()],
:path_params => %{
binary() =>
binary()
| [binary() | [any()] | %{binary() => _}]
| %{binary() => binary() | [any()] | %{binary() => _}}
},
:port => char(),
:private => %{atom() => _},
:query_params => %Plug.Conn.Unfetched{
:aspect => atom(),
binary() =>
binary()
| [binary() | [any()] | %{binary() => _}]
| %{binary() => binary() | [any()] | %{binary() => _}}
},
:query_string => binary(),
:remote_ip =>
{byte(), byte(), byte(), byte()}
| {char(), char(), char(), char(), char(), char(), char(), char()},
:req_cookies => %Plug.Conn.Unfetched{:aspect => atom(), binary() => binary()},
:req_headers => [{binary(), binary()}],
:request_path => binary(),
:resp_body =>
nil
| binary()
| maybe_improper_list(
binary() | maybe_improper_list(any(), binary() | []) | byte(),
binary() | []
),
:resp_cookies => %{binary() => map()},
:resp_headers => [{binary(), binary()}],
:scheme => :http | :https,
:script_name => [binary()],
:secret_key_base => nil | binary(),
:state =>
:chunked | :file | :sent | :set | :set_chunked | :set_file | :unset | :upgraded,
:status => nil | non_neg_integer()
},
%Corsica.Options{
:allow_credentials => false,
:allow_headers => [],
:allow_methods => [<<_::24, _::size(8)>>, ...],
:allow_private_network => false,
:expose_headers => nil,
:max_age => nil,
:origins => <<_::8>>,
:passthrough_non_cors_requests => false,
:telemetry_metadata => %{}
}
)
From what I understand by briefly looking at the report and following the code, the line
use Corsica.Router
is injecting code that makes use of the Options struct in these two places:
Line 135 in 1857c34
Line 145 in 1857c34
I haven't worked with opaque types and macros enough to suggest a solution or PR but hopefully this is enough context :D
whatyouhide commented
Nice find! Closed by 1560dcc. 🙃