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

Better error messages for top level declarations (module, import) #545

Open
scarf005 opened this issue Jul 11, 2023 · 1 comment
Open

Better error messages for top level declarations (module, import) #545

scarf005 opened this issue Jul 11, 2023 · 1 comment

Comments

@scarf005
Copy link

scarf005 commented Jul 11, 2023

Summary

I think there's some room for improvement for error messages on top level declarations1 (module, import).

Typos

Reproduction

improt Data.List
main = putStrLn "Hello, World"
main = putStrLn "Hello, World"
improt Data.List
modul main
main = putStrLn "Hello, World"

Current Message

test.hs:1:1: error:
    Parse error: module header, import declaration
    or top-level declaration expected.
  |
1 | improt Data.List
  | ^^^^^^^^^^^^^^^^

Suggestion

test.hs:1:1: 

error:
    Parse error: module header, import declaration
    or top-level declaration expected.

  |
1 | improt Data.List
  | ^^^^^^^^^^^^^^^^

hint: 
	Perhaps you meant import (typo of improt) to import a module?

  |
1 | import Data.List
  | ~~~~~~

https://github.com/ghc/ghc/blob/4926af7b018212356e9966685717c24a8da04030/compiler/GHC/Tc/Errors/Ppr.hs#L5989-L5991
Addressing it might be more complicated than I've anticipated as the error is actually from template haskell type checker...

Non-top-level imports

main = putStrLn "Hello, World"

import Data.List

Current Message

test.hs:3:1: error: parse error on input import
  |
3 | import Data.List
  | ^^^^^^

Suggestion

test.hs:3:1: 

error: 
	Import statement must be placed at the top of the source code.

  |
3 | import Data.List
  | ^^^^^^

hint:
	Moving it to the top of the file will make the statement valid.

1 | import Data.List
  | ~~~~~~~~~~~~~~~~
2 | main = putStrLn "Hello, World"
  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Missing where in modules

module Foo
main = putStrLn "Hello, World"

Current Message

test.hs:2:1: error: parse error on input main
  |
2 | main = putStrLn "Hello, World"
  | 

Suggestion

test.hs:1:8: 

error: 
	Module declaration must end with where’.

  |
1 | module Foo
  | ^^^^^^^^^^

hint:
	Adding where at the end of module statement will finish it.

  |
1 | module Foo where
  |            ~~~~~

Module names in lowercase

module foo where
main = putStrLn "Hello, World"

Current Message

test.hs:1:8: error: parse error on input foo
  |
1 | module foo where
  |    

Suggestion

test.hs:1:8: 

error: 
	module name ‘foo’ must be in PascalCase.
  |
1 | module foo where
  |        ^^^

hint:
	Perhaps you wanted to capitalize the first letter?

  |
1 | module Foo where
  |        ~~~

Import statement before module statement

Reproduction

import Data.List
module Foo where
main = putStrLn "Hello, World"

Current Message

test.hs:2:1: error: parse error on input ‘module’
  |
2 | module Foo where
  | ^^^^^^

Suggestion

test.hs:2:1: 

error: 
	module statement must be the first statement of the program.

1 | import Data.List
2 | module Foo where
  | ^^^^^^

hint:
	Move the module statement to the top of file.

1 | module Foo where
  | ~~~~~~~~~~~~~~~~
2 | import Data.List
  | ~~~~~~~~~~~~~~~~

Top-level declarations

Reproduction

foo

Current Message

test.hs:1:1: error:
    Parse error: module header, import declaration
    or top-level declaration expected.
  |
1 | foo
  | ^^^

Suggestion

test.hs:1:1: 

error:
	Sorry, I can't figure out what foo is.
	Only following declarations are allowed on top level:
		- module header (e.g: module Main where)
		- import declaration (e.g: import Data.List)
		- top-level declaration (e.g: myvalue = 4)
	And foo is not one of them.
  |
1 | foo
  | ^^^

hint:
	I wasn't able to find anything about foo’.
 	Perhaps you wanted to write a top-level declaration for foo’? 
	For example, if you wanted to declare
	foo to be equivalent to number 3’:
  |
1 | foo = 3
  | ~~~~~~~

	...Or perhaps your cat ran over the keyboard?
	Then you may want to delete foo’.
  |
1 | 
  | ~~~

Top-level declaration and a typo

Reproduction

foo = 4
fooo

Current Message

test.hs:2:1: error:
    Parse error: module header, import declaration
    or top-level declaration expected.
  |
2 | foo
  | ^^^

Suggestion

test.hs:2:1:

error:
	fooo (possible typo of foo) is an expression,
	However only following declarations are allowed on top level:
		- module header (e.g: module Main where)
		- import declaration (e.g: import Data.List)
		- top-level declaration (e.g: myvalue = 4)

2 | fooo
  | ^^^

hint:
	Found similar declaration foo on line 1:

1 | foo = 4
  | ~~~~~~~

	Perhaps you meant to add a type declaration to foo’?

1 | foo = 4
  | 
2 | foo :: Integer
  |     ~~~~~~~~~~ (type inferred from context)

	...Or perhaps your cat ran over the keyboard?
	Then you may want to delete fooo’.
  |
2 | 
  | ~~~

System Info

  • Kubuntu 23.04
  • GHC 9.4.5 (confirmed source code hasn't changed on master)

Others

The list got a bit long, maybe i should separate them to separate issues with tasklist?

Footnotes

  1. Also the word 'top level declaration' could be made more helpful by giving some detailed explanation. Because I didn't know what does that mean and had to stackoverflow it and got 'gatekeeped'.

@cbrt-x
Copy link

cbrt-x commented May 20, 2024

This is a subset of what https://gitlab.haskell.org/ghc/ghc/-/issues/24351 would provide.

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

No branches or pull requests

2 participants