Skip to content

String.slice(str, 0, -1) raises FunctionClauseError #496

Open

Description

@beadsland

This snippet of Elixir:

String.slice(str, 0, -1)

Started with slice/2 form of this call, but swapped to slice/3 to confirm the error wasn't being generated by the Elixir range.

Raises the following exception

** (EXIT from #PID<0.95.0>) an exception was raised:
** (FunctionClauseError) no function clause matching in ElixirScript.Translate.Form.compile/2
lib/elixir_script/passes/translate/form.ex:28: ElixirScript.Translate.Form.compile(&Inspect.inspect/2, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.200.0>, vars: %{}})
lib/elixir_script/passes/translate/form.ex:16: ElixirScript.Translate.Form.compile!/2
lib/elixir_script/passes/translate/forms/map.ex:37: anonymous fn/2 in ElixirScript.Translate.Forms.Map.compile/2
(elixir 1.10.4) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
(elixir 1.10.4) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
lib/elixir_script/passes/translate/forms/map.ex:32: ElixirScript.Translate.Forms.Map.compile/2
lib/elixir_script/passes/translate/form.ex:16: ElixirScript.Translate.Form.compile!/2
lib/elixir_script/passes/translate/function.ex:170: ElixirScript.Translate.Function.compile_block/2

Modified Transcript.Form.compile! as follows:

  @spec compile!(any, map) :: ESTree.Node.t()
  def compile!(ast, state) do
    {js_ast, _} = compile(ast, state)
    js_ast
  rescue
    e -> Logger.debug inspect({:compile!, ast, state})
         raise RuntimeError, message: inspect({"compile!/2", e})
  end

Which revealed the following debugging info:

03:45:21.580 [debug] {:compile!, &Inspect.inspect/2, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.200.0>, vars: %{}}}

03:45:21.696 [debug] {:compile!, {:%{}, [line: 74], [struct: Inspect.Opts, base: :decimal, binaries: :infer, char_lists: :infer, charlists: :infer, custom_options: [], inspect_fun: &Inspect.inspect/2, limit: 50, pretty: false, printable_limit: 4096, safe: true, structs: true, syntax_colors: [], width: 80]}, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.200.0>, vars: %{}}}

Thoughts

Not too familiar with this codebase, but I'm working from the premise that inspect_fun: &Inspect.inspect/2 might be malformed, for it to be promoted into the ast parameter of compile!.

Activity

  1. beadsland commented on Aug 1, 2020

    @beadsland
    Author

    Trying to build out same functionality without library function String.slice/2:

    path = to_charlist str

    Hit same error condition:

    ** (EXIT from #PID<0.95.0>) an exception was raised:
    ** (RuntimeError) {"compile!/2", %RuntimeError{message: "{"compile!/2", %FunctionClauseError{args: nil, arity: 2, clauses: nil, function: :compile, kind: nil, module: ElixirScript.Translate.Form}}"}}
    lib/elixir_script/passes/translate/form.ex:19: ElixirScript.Translate.Form.compile!/2
    lib/elixir_script/passes/translate/function.ex:170: ElixirScript.Translate.Function.compile_block/2
    lib/elixir_script/passes/translate/function.ex:138: ElixirScript.Translate.Function.compile_clause/2
    (elixir 1.10.4) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
    lib/elixir_script/passes/translate/function.ex:100: ElixirScript.Translate.Function.compile_clauses/2
    lib/elixir_script/passes/translate/function.ex:60: ElixirScript.Translate.Function.compile/2
    (elixir 1.10.4) lib/enum.ex:1520: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    lib/elixir_script/passes/translate/module.ex:98: ElixirScript.Translate.Module.compile/3

    With similar debug values:

    06:15:24.282 [debug] {:compile!, &Inspect.inspect/2, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.166.0>, vars: %{}}}

    06:15:24.336 [debug] {:compile!, {:%{}, [line: 74], [struct: Inspect.Opts, base: :decimal, binaries: :infer, char_lists: :infer, charlists: :infer, custom_options: [], inspect_fun: &Inspect.inspect/2, limit: 50, pretty: false, printable_limit: 4096, safe: true, structs: true, syntax_colors: [], width: 80]}, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.166.0>, vars: %{}}}

    Breaking it down:

    So, reducing it to bare necessary expression to break ElixirScript:

    to_charlist "abc"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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