Crystal: Wrong "see" URL in compiler error message

Created on 25 Mar 2020  Â·  7Comments  Â·  Source: crystal-lang/crystal

Compiler error message:

Error: can't infer block return type, try to cast the block body with `as`. See: https://github.com/crystal-lang/crystal/wiki/Compiler-error-messages#cant-infer-block-return-type

URL does not exist.

➤  crystal --version
Crystal 0.33.0 [612825a53] (2020-02-14)

LLVM: 8.0.0
Default target: x86_64-unknown-linux-gnu
bug docs

All 7 comments

I have no idea where did that page go... :-(

@straight-shoota the content from that wiki page was migrated somewhere? I could not find it.

The removal was announced in https://forum.crystal-lang.org/t/overhauling-the-github-wiki/1303 and nobody objected. I found the example code doesn't reproduce anymore, so it didn't seem worth moving the content somewhere else. But I might have been mistaken about that, the example seems to be still valid.

I also didn't realize it was referenced in an error message. Judging by the number of entries on that wiki page, this doesn't seem to be a very frequent feature 🤣

We can probably reinstate the wiki page as a short-term fix to the broken reference. But I don't think the wiki is the right place for that and we should probably have a talk about this practice. It doesn't seem particularly valuable for only a single instance. We should either drop it or consider adding more references for other language errors, too.

I don't think the wiki is the right place either. In the crystal-book I thought of having a section for describing compiler errors beyond the message shown by the compiler.

I was trying to gather some info for when this happen.

Here's a way to reproduce it:

class Tree
  def initialize
    @children = [] of Tree
  end

  def sum
    1 + @children.map(&.sum).first
  end
end

Tree.new.sum

The problem is that to compute map(&.sum) the compiler needs to infer the type of sum, because map is defined like map(&block : T -> U) forall U. However, to compute the type of sum we need to know the type of sum, so the compiler can't do anything.

I improved the situation a bit in #7161

The issue is fixed if instead of defining Array#map like this:

  def map(&block : T -> U) forall U
    Array(U).new(size) { |i| yield @buffer[i] }
  end

we define it like this:

  def map
    Array(typeof(yield @buffer[0])).new(size) { |i| yield @buffer[i] }
  end

The reason is that the compiler will bind all types together and when sum's type is determined, it will propagate to everything else. But in the case of &block : T -> U forall U the type is checked immediately. It's definitely something to improve...

For error messages, I think we should have an error code like E123 next to a basic explanation from the compiler (like now), and an index page with complete explanation + example solutions in a website (in the language reference for exemple)

I've just noticed this specific link was fixed by #8869 .

Was this page helpful?
0 / 5 - 0 ratings

Related issues

asterite picture asterite  Â·  3Comments

Papierkorb picture Papierkorb  Â·  3Comments

oprypin picture oprypin  Â·  3Comments

cjgajard picture cjgajard  Â·  3Comments

Sija picture Sija  Â·  3Comments