Skip to content

Could not call defguard check inside defguard. #7147

@Eiji7

Description

@Eiji7

Origin

Talk begins in Elixir v1.6.0-rc.0 released news thread.
Here are links for most important posts (from begin to José example):

  1. Original question
  2. Ask again but with old version that uses macros
  3. José Valim response

Environment

$ asdf current
asdf current
elixir ref-v1.6.0-rc.0 (set by /home/eiji/.tool-versions)
erlang 20.2 (set by /home/eiji/.tool-versions)

Funtoo Linux current x86-64bit on intel64-ivybridge

Example code from José Valim

defmodule Example do
  defguard is_rgb_integer(integer) when integer in 0..255

  defguard is_rgb_strict(rgb)
           when is_rgb_integer(elem(rgb, 0)) and
                  is_rgb_integer(elem(rgb, 1)) and
                  is_rgb_integer(elem(rgb, 2))

  defguard is_css_alpha(alpha) when alpha >= 0 and alpha <= 1
    
  defguard is_rgba(rgba)
           when tuple_size(rgba) == 4 and is_rgb_strict(rgba) and is_css_alpha(elem(rgba, 3))

  defguard is_rgb(rgba)
           when (tuple_size(rgba) == 3 and is_rgb_strict(rgba)) or
                (tuple_size(rgba) == 4 and is_rgb_strict(rgba))
end

Steps to reproduce

  1. Ensure you have dependencies for compile sources
  2. Install asdf
  3. Add asdf Erlang plug-in
  4. Install latest available Erlang (asdf list-all erlang to see all versions)
  5. Add asdf Elixir plug-in
  6. Set Erlang version
  7. Install Elixir v1.6.0 RC 0 or master (I have checked both):
  8. Copy example code to at least one of them:
    a) iex session
    b) lib/example.ex in new Elixir project (mix new example)
  9. Require Example module (require Example)
  10. Try to call Example.is_rgb/1 or Example.is_rgba/1 guard checks

Reproduce script:

# File: "reproduce.sh"

#!/bin/bash

# asdf
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.4.0

# Erlang
asdf plugin-add erlang https://github.com/asdf-vm/asdf-erlang.git
asdf install erlang 20.2
asdf global erlang 20.2

# Elixir
asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git
asdf install elixir ref:v1.6.0-rc.0
asdf global elixir ref-v1.6.0-rc.0
# or:
# asdf install elixir ref:master

# Create example project
mix new example
cd example

# Add José Valim code:
cat >lib/example.ex <<EOL
defmodule Example do
  defguard is_rgb_integer(integer) when integer in 0..255

  defguard is_rgb_strict(rgb)
           when is_rgb_integer(elem(rgb, 0)) and
                  is_rgb_integer(elem(rgb, 1)) and
                  is_rgb_integer(elem(rgb, 2))

  defguard is_css_alpha(alpha) when alpha >= 0 and alpha <= 1
    
  defguard is_rgba(rgba)
           when tuple_size(rgba) == 4 and is_rgb_strict(rgba) and is_css_alpha(elem(rgba, 3))

  defguard is_rgb(rgba)
           when (tuple_size(rgba) == 3 and is_rgb_strict(rgba)) or
                (tuple_size(rgba) == 4 and is_rgb_strict(rgba))
end
EOL

# Add extra file for calling guards:
mkdir lib/example
cat >lib/example/sample.ex <<EOL
require Example

# should return false:
Example.is_rgb({255, 255})

# should return true
Example.is_rgb({255, 255, 255})
EOL

# Finally compile project
mix compile

Note: Reproduce script does not contain any solution for step 0.
Note 2: It will not work if you have example directory in current working directory

Current behavior

When compiling (last script line) I got:

== Compilation error in file lib/example/sample.ex ==
** (CompileError) lib/example/sample.ex:3: undefined function is_rgb_strict/1
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (elixir) expanding macro: Kernel.and/2

Expected behavior

Code should compile.

TODO

Based on José Valim response:

Can you please open up a bug report? I am almost sure we have a test case for this, so I need to investigate exactly what is happening here.

  • 1. Check why current tests does not fails
  • 2. Add tests for remote calls
  • 3. Find and fix issue with call guards in guards (defguard and defguardp)

cc @christhekeele and @josevalim

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions