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

rustc "file:line-num" output has become incompatible with emacs' default compilation-mode #6887

Closed
pnkfelix opened this issue Jun 1, 2013 · 20 comments

Comments

@pnkfelix
Copy link
Member

pnkfelix commented Jun 1, 2013

The output from rustc used to be compatible with emacs compilation-mode's regexp, so that I could immediately visit the point of error via generated links in a compile-mode buffer.

But now it products output where, at least on my emacs install, the compilation mode gets confused.

As a concrete example, it interprets this output:

llist2.rs:9:0: 12:1 error: not all control paths return a value
llist2.rs:9 fn place_top(pile: Option<~card>, newcard: ~card) -> ~card
llist2.rs:10 {
llist2.rs:11 
llist2.rs:12 }

where it sees the first line as the place to find the link to the error (and the subsequent lines are not linked), but when I click, it thinks the error is in a file named 9:0 at line 12, column 1.

(I can probably figure this out sometime in the next week, so I am going to assign this to myself; I just wanted to file it away now.)

@ghost ghost assigned pnkfelix Jun 1, 2013
@pnkfelix
Copy link
Member Author

pnkfelix commented Jun 1, 2013

Potential fixes:

  • massage rustc's output
  • an alternative would be to change rust-mode.el to extend the compilation-error-regexp-alist
  • or to change rust-mode.el to add an entry for 'rust to compilation-error-regexp-alist-alist

@pnkfelix
Copy link
Member Author

pnkfelix commented Jun 1, 2013

Here's something that might do the job:

(setq compilation-error-regexp-alist-alist
      (cons '(rustc "^\\([^ \n]+\\):\\([0-9]+\\):\\([0-9]+\\): \\([0-9]+\\):\\([0-9]+\\) \\(?:[Ee]rror\\|\\([Ww]arning\\)\\):" 1 (2 . 4) (3 . 5) (6))
        compilation-error-regexp-alist-alist))

(and then add 'rust to compilation-error-regexp-alist.

Not sure if this is really the right way to go about modularly extending that list, though.

@msullivan
Copy link
Contributor

So, using "M-x compile", and building, I seem to be able to jump to errors just fine. Are you talking about something different, or has it gotten fixed?

@msullivan
Copy link
Contributor

I'm going to close this, since it seems to work.

@pnkfelix
Copy link
Member Author

@msullivan okay. Just to fill me in for when I look at this again, what version of Emacs (host OS and version number) were you using?

@pnkfelix pnkfelix reopened this Aug 10, 2013
@pnkfelix
Copy link
Member Author

On Emacs Version 24.2 (9.0), for the following test program, I see the reported problem still:

Makefile:

run-ne: nonexhaust.bin
    ./$<

%.bin: %.rs
    rustc -o $@ $<

nonexhaust.rs:

fn foo(x: Option<Option<int>>) -> int {
    match x {
        Some(Some(n)) => n,
        Some(None) => 3
    }
}

fn main() {
    println(fmt!("%d", foo(Some(Some(4)))));
}

*compilation* output:

-*- mode: compilation; default-directory: "/tmp/show-el-fail/" -*-
Compilation started at Sat Aug 10 13:35:58

make
rustc -o nonexhaust.bin nonexhaust.rs
nonexhaust.rs:2:4: 5:5 error: non-exhaustive patterns: None not covered
nonexhaust.rs:2     match x {
nonexhaust.rs:3         Some(Some(n)) => n,
nonexhaust.rs:4         Some(None) => 3
nonexhaust.rs:5     }
error: aborting due to previous error
make: *** [nonexhaust.bin] Error 101

Compilation exited abnormally with code 2 at Sat Aug 10 13:35:59

When I try to follow the hyperlink presented by emacs at the line with 2:4: 5:5 error, it prompts me with:
Find this error in (default 2:4): /tmp/show-el-fail/ (where /tmp/show-el-fail is the current working directory).

Reopening ticket, leaving assigned to self for further investigation. (Perhaps I need to upgrade my emacs on this machine, not sure yet.)

@pnkfelix
Copy link
Member Author

  1. Upgraded to Emacs 24.3. (It supports Mac OS X full screen mode, woo). But the problem of this ticket continues to arise there.
  2. If I inject a new different error earlier in that same file, the compilation mode correctly extracts the file name:
-*- mode: compilation; default-directory: "/tmp/show-el-fail/" -*-
Compilation started at Sat Aug 10 13:52:17

make
rustc -o nonexhaust.bin nonexhaust.rs
nonexhaust.rs:2:10: 2:17 error: expected `;` or `}` after expression but found `problem`
nonexhaust.rs:2     other problem here
                          ^~~~~~~
make: *** [nonexhaust.bin] Error 101

Compilation exited abnormally with code 2 at Sat Aug 10 13:52:17

So this is not a problem uniformly across the board for all of our error message output.

@pnkfelix
Copy link
Member Author

(I wonder if this is happening because its misinterpreting the colon in the middle of the message, in non-exhaustive patterns: None, and incorrectly backtracking to match 2:4 as the file name.)

@pnkfelix
Copy link
Member Author

I determined, via bisection of compilation-error-regexp-alist, that we are probably relying on the gnu compilation error regexp.

If you paste the following into an Emacs *scratch* buffer, you can interactively see how the regexp is getting confused in some way by the different outputs:

(re-search-forward
 (cadr (assq 'gnu compilation-error-regexp-alist-alist)))   ;; CASE 1

nonexhaust.rs:2:4: 4:5 error: non-exhaustive patterns: None not covered

(re-search-forward
 (cadr (assq 'gnu compilation-error-regexp-alist-alist)))   ;; CASE 2

nonexhaust.rs:2:10: 2:15 error: expected `;` or `}` after expression but found `stuff`

Namely, if you put the cursor at the end of the expression marked "CASE 1" and hit C-x C-e, the cursor will jump to the point between 4:5 and error:. If you do the same for "CASE 2", the cursor jumps between 2:10 and 2:15. (The latter is what we want, in terms of Emacs then extracting the correct substrings for filenames and line numbers.

@pnkfelix
Copy link
Member Author

bizarre:

This line works: nonexhaust.rs:2:10: 2:5 error: message

This line does not: nonexhaust.rs:2:10: 2:15 error: message

(That's assuming my earlier analysis of what "correct" and "incorrect" behavior are when experimenting in the scratch buffer.)

Surely the number of digits in the column specification should not cause the regexp matching behavior to change so radically? This is looking more and more to me like an Emacs deficiency, not a Rust one.

@pnkfelix
Copy link
Member Author

(It seems like one potential (and simple) fix on the Emacs side would be to change the 'gnu regexp to filter out not just "filenames" composed solely of digits, but also "filenames" composed solely of digits and colon characters. I might submit that over there. But it would be good for us to have a fix in rust-mode.el in the meantime on our end.)

@graydon
Copy link
Contributor

graydon commented Aug 26, 2013

In case anyone has the brainpower to debug the gnu regexp, here it is in all its majesty:

   (gnu
     ;; The first line matches the program name for

     ;;     PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE

     ;; format, which is used for non-interactive programs other than
     ;; compilers (e.g. the "jade:" entry in compilation.txt).

     ;; This first line makes things ambiguous with output such as
     ;; "foo:344:50:blabla" since the "foo" part can match this first
     ;; line (in which case the file name as "344").  To avoid this,
     ;; the second line disallows filenames exclusively composed of
     ;; digits.

     ;; Similarly, we get lots of false positives with messages including
     ;; times of the form "HH:MM:SS" where MM is taken as a line number, so
     ;; the last line tries to rule out message where the info after the
     ;; line number starts with "SS".  --Stef

     ;; The core of the regexp is the one with *?.  It says that a file name
     ;; can be composed of any non-newline char, but it also rules out some
     ;; valid but unlikely cases, such as a trailing space or a space
     ;; followed by a -, or a colon followed by a space.

     ;; The "in \\|from " exception was added to handle messages from Ruby.
     "^\\(?:[[:alpha:]][-[:alnum:].]+: ?\\|[ \t]+\\(?:in \\|from \\)\\)?\
\\([0-9]*[^0-9\n]\\(?:[^\n :]\\| [^-/\n]\\|:[^ \n]\\)*?\\): ?\
\\([0-9]+\\)\\(?:[.:]\\([0-9]+\\)\\)?\
\\(?:-\\([0-9]+\\)?\\(?:\\.\\([0-9]+\\)\\)?\\)?:\
\\(?: *\\(\\(?:Future\\|Runtime\\)?[Ww]arning\\|W:\\)\\|\
 *\\([Ii]nfo\\(?:\\>\\|rmationa?l?\\)\\|I:\\|instantiated from\\|[Nn]ote\\)\\|\
 *[Ee]rror\\|\[0-9]?\\(?:[^0-9\n]\\|$\\)\\|[0-9][0-9][0-9]\\)"
     1 (2 . 4) (3 . 5) (6 . 7))

Meanwhile I am happy taking the improvement here, if it does indeed fix the bug.

bors added a commit that referenced this issue Aug 27, 2013
@pnkfelix
Copy link
Member Author

�Argh, it did fix the bug before I revised it in response to a review comment and accidentally added a second ^ at the start of the regexp . Will fix.

@pnkfelix
Copy link
Member Author

part of #8793

@helinwang
Copy link

helinwang commented Mar 28, 2020

The problem still exist for me when using M-x compile with cargo build, or with M-x cargo-process-build.

@helinwang
Copy link

Adding these lines to init.el fixed for me:

    ;; Issue #6887: Rather than inheriting the 'gnu compilation error
    ;; regexp (which is broken on a few edge cases), add our own 'rust
    ;; compilation error regexp and use it instead.
    (defvar rustc-compilation-regexps
      (let ((file "\\([^\n]+\\)")
            (start-line "\\([0-9]+\\)")
            (start-col  "\\([0-9]+\\)")
            (end-line   "\\([0-9]+\\)")
            (end-col    "\\([0-9]+\\)")
            (msg-type   "\\(?:[Ee]rror\\|\\([Ww]arning\\)\\|\\([Nn]ote\\|[Hh]elp\\)\\)"))
        (let ((re (concat "^" file ":" start-line ":" start-col
                          ": " end-line ":" end-col
                          " " msg-type ":")))
          (cons re '(1 (2 . 4) (3 . 5) (6 . 7)))))
      "Specifications for matching errors in rustc invocations.
    See `compilation-error-regexp-alist' for help on their format.")

    (defvar rustc-new-compilation-regexps
      (let ((file "\\([^\n]+\\)")
            (start-line "\\([0-9]+\\)")
            (start-col  "\\([0-9]+\\)"))
        (let ((re (concat "^ *--> " file ":" start-line ":" start-col ; --> 1:2:3
                          )))
          (cons re '(1 2 3))))
      "Specifications for matching errors in rustc invocations (new style).
    See `compilation-error-regexp-alist' for help on their format.")

    ;; Match test run failures and panics during compilation as
    ;; compilation warnings
    (defvar cargo-compilation-regexps
      '("^\\s-+thread '[^']+' panicked at \\('[^']+', \\([^:]+\\):\\([0-9]+\\)\\)" 2 3 nil nil 1)
      "Specifications for matching panics in cargo test invocations.
    See `compilation-error-regexp-alist' for help on their format.")

    (defun rustc-scroll-down-after-next-error ()
      "In the new style error messages, the regular expression
       matches on the file name (which appears after `-->`), but the
       start of the error appears a few lines earlier. This hook runs
       after `M-x next-error`; it simply scrolls down a few lines in
       the compilation window until the top of the error is visible."
      (save-selected-window
        (when (eq major-mode 'rust-mode)
          (select-window (get-buffer-window next-error-last-buffer 'visible))
          (when (save-excursion
                  (beginning-of-line)
                  (looking-at " *-->"))
            (let ((start-of-error
                   (save-excursion
                     (beginning-of-line)
                     (while (not (looking-at "^[a-z]+:\\|^[a-z]+\\[E[0-9]+\\]:"))
                       (forward-line -1))
                     (point))))
              (set-window-start (selected-window) start-of-error))))))

    (eval-after-load 'compile
      '(progn
         (add-to-list 'compilation-error-regexp-alist-alist
                      (cons 'rustc-new rustc-new-compilation-regexps))
         (add-to-list 'compilation-error-regexp-alist 'rustc-new)
         (add-hook 'next-error-hook 'rustc-scroll-down-after-next-error)
         (add-to-list 'compilation-error-regexp-alist-alist
                      (cons 'rustc rustc-compilation-regexps))
         (add-to-list 'compilation-error-regexp-alist 'rustc)
         (add-to-list 'compilation-error-regexp-alist-alist
                      (cons 'cargo cargo-compilation-regexps))
         (add-to-list 'compilation-error-regexp-alist 'cargo)))

https://github.com/fschutt/.emacs/blob/master/.emacs#L1574-L1639

@flajann2
Copy link

flajann2 commented Apr 9, 2020

Alas, didn't work for me at all. I am using the lastest nightly build. That is to say, it always prompts me for locating the file.

flip1995 pushed a commit to flip1995/rust that referenced this issue May 6, 2021
…tion-lint, r=xFrednet

A metadata collection monster

This PR introduces a metadata collection lint as discussed in rust-lang#4310. It currently collects:
* The lint ID
* The lint declaration file and location (for rust-lang#1303)
* The lint group
* The documentation
* The applicability (if resolvable)
* If the suggestion is a multi-part-suggestion

This data has a slightly different structure than the current [lints.json](https://github.com/rust-lang/rust-clippy/blob/gh-pages/master/lints.json) and doesn't include depreciated lints yet. I plan to adapt the website to the new format and include depreciated lints in a follow-up PR :). The current collected json looks like this: [metadata_collection.json](https://gist.github.com/xFrednet/6b9e2c3f725f476ba88db9563f67e119)

The entire implementation is guarded behind the `metadata-collector-lint` feature and the `ENABLE_METADATA_COLLECTION` environment value to prevent default collection. You can test the implementation via:
```sh
$ ENABLE_METADATA_COLLECTION=1 cargo test --test dogfood --all-features
```

changelog: none

---

The size of this PR sadly also grew into a small monster, sorry! I definitely plan to improve on this! And it's totally okay if you take your time with this :)

r? `@phansch`
cc: `@flip1995`
@fencekicker
Copy link

Hi helinwang,

Adding these lines to init.el fixed for me:
[...]
https://github.com/fschutt/.emacs/blob/master/.emacs#L1574-L1639

I've added these lines to my .emacs and I'm still getting prompted to find the file when middle-clicking on errors. Is this what your changes were trying to fix? I have emacs 26.03 on Ubuntu 20.04.

It looks to me like Emacs is having problem with the relative paths. Not sure how to teach it to look for files under the project root (and 'cd && make ...' does not work; yes, we build with make, which calls cargo etc). As far as I understand the original report, it's about Emacs not being able to parse the cargo output, not specifically about finding files.

@helinwang
Copy link

Hi @fencekicker yes these lines tell emacs to parse the rust output file correctly, not sure why it does not work for you. I guess somehow the command does not activate for you.

@fencekicker
Copy link

@helinwang what version of emacs are you using?

At least in my case, I see the error messages refer to relative paths:

Compiling foobar v0.1.0 (/<full/path/to/foobar>)
error[XXX]: ....
--> <relative/path/to/foobar>/mod.rs:85:5

When I click the mouse on the file, Emacs opens a different folder. I can see the file names highlighted properly, it's just that clicking on them opens a file picker. Is that the issue you were seeing before the changes to init.el?

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.

6 participants