Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Norm onboarding requires uneasy co-existence with Dialyzer #53

Open
garthk opened this issue Mar 18, 2020 · 5 comments · May be fixed by #82
Open

Norm onboarding requires uneasy co-existence with Dialyzer #53

garthk opened this issue Mar 18, 2020 · 5 comments · May be fixed by #82

Comments

@garthk
Copy link
Contributor

garthk commented Mar 18, 2020

You want to add some Norm for that with_gen/2 goodness, but Dialyzer got there first. The first argument of with_gen/2 isn't opaque, t:StreamData.t/0 is, and your console is all red:

The call Norm.with_gen(#{'__struct__':='Elixir.Norm.Core.Spec', 'f':=fun((_) -> boolean()), 'generator':='is_atom', 'predicate':=<<_:72>>},'Elixir.StreamData':t(_)) contains an opaque term in 2nd argument when terms of different types are expected in these positions}.

If it wouldn't make @keathley break out in a rash, maybe an @opaque of our own and a sprinkling of @spec would make it easier?

@garthk
Copy link
Contributor Author

garthk commented Mar 18, 2020

If you're here because you're searching for this problem, I guess we never did make Norm compatible with Dialyzer. Here are some workaround for the errors:

Unknown types: run mix dialyzer --format dialyzer to get the long form and add it to your dialyzer.ignore-warnings eg.:

:0: Unknown type 'Elixir.Norm.Core.AnyOf':t/0

call_with_opaque: add :no_opaque to your flags (documented under Dialyxir's paths heading):

def project do
  [
    dialyzer: [
      ignore_warnings: "dialyzer.ignore-warnings",
      flags: [:no_opaque],
      # ...
end

If you're using ElixirLS you'll need to add the same flag to its options, e.g. in your VS Code settings.json:

{ "elixirLS.dialyzerWarnOpts": [ "no_opaque" ] }

Still feeling too brutal? Need those warnings elsewhere? Add a dialyzer module attribute to suppress those specific warnings:

@dialyzer {:no_opaque, module: 0, function: 0, term: 0}

defguard(is_term(_) when true)

def module, do: with_gen(spec(is_atom()), StreamData.atom(:alias))
def function, do: with_gen(spec(is_atom()), StreamData.atom(:alphanumeric))
def term, do: with_gen(spec(is_term), StreamData.term())
def mfa, do: {module(), function(), coll_of(term(), into: [])}

@keathley
Copy link
Member

Maybe I'm missing something but this seems like a pretty innocuous change. So I'm happy to add it if. My main concern is just that we don't run dialyzer in Norm's CI suite. Which means it wouldn't be enforced atm.

@garthk
Copy link
Contributor Author

garthk commented May 24, 2020

I'm pretty comfortable with @dialyzer {:no_opaque, my_spec: 0} now; how about I summarise the @dialyzer module attribute trick under an ## Interoperability with Dialyzer heading in README.md?

@keathley
Copy link
Member

That seems great. Feel free to submit a PR.

@garthk garthk linked a pull request May 24, 2020 that will close this issue
@keathley
Copy link
Member

I've been looking into this more. From what I can tell this is actually a stream_data issue and doesn't have anything to do with Norm. Its also possible that I'm reading this wrong. I added dialyzer to Norm, and added a new module like so:

defmodule Norm.Test do                                                                                                      
  import Norm                                                                                                               
                                                                                                                            
  def foo do                                                                                                                
    with_gen(spec(is_atom), StreamData.atom(:alphanumeric))                                                                 
  end                                                                                                                       
end

After 10,000 years waiting for dialyzer to build a PLT, realizing that stream_data wasn't included in the PLT, reconfiguring and waiting another 10,000 years, dialyzer eventually spits out this error:

lib/norm/core/spec.ex:122:call_without_opaque
Function call without opaqueness type mismatch.

Call does not have expected opaque term of type StreamData.t(_) in the 1st position.

StreamData.map(%StreamData{:generator => (_, _ -> map())}, (_ -> any()))

We're not actually doing anything wrong here. We're just using stream_data's API. I think the issue is that stream_data hasn't added explicit type specs to it's APIs, which it has to do if StreamData.t is opaque.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants