Overhaul borrowck error messages and compiler error formatting generally
This is a major overhaul of how the compiler reports errors. The primary goal is to be able to give many spans within the same overall context, such as this:
```
./borrow-errors.rs:73:17: 73:20: error: cannot borrow `*vec` as immutable because previous closure requires unique access [E0501]
70 let append = |e| {
~~~ closure construction occurs here
71 vec.push(e)
~~~ previous borrow occurs due to use of `vec` in closure
72 };
73 let data = &vec[3];
~~~ borrow occurs here
74 }
~ borrow from closure ends here
```
However, in the process we made a number of other changes:
- Removed the repetitive filenames from snippets and just give the line number.
- Color the line numbers blue so they "fade away"
- Remove the file name and line number from the error code suggestions since they don't seem to fit anymore. (This should probably happen in more places, like existing notes.)
- Newlines in between errors to help group them better.
This PR is not quite ready to land, but we thought it made sense to stop here and get some feedback from people at large. It'd be great if people can check out the branch and play with it. We'd be especially interested in hearing about cases that don't look good with the new formatting (I suspect they exist).
Here is a checklist of some pending work items for this PR. Some of them may be best left for follow-up PRs:
- [x] Accommodate multiple files in a `MultiSpan` (this should be easy)
- In this case, we want to print filenames though.
- [x] Remove duplicate E0500 code.
- [x] Make the header message bold, rather than current hack that makes all errors/warnings bold
- [x] Update warning text color (yellow is hard to read w/ a white background)
Moved numerous follow-ups to: https://github.com/rust-lang/rust/issues/33240
Joint work with @jonathandturner.
Fixes https://github.com/rust-lang/rust/issues/3533
There is now a CoreEmitter that everything desugars to, but without
losing any information. Also remove RenderSpan::FileLine. This lets the
rustc_driver tests build.
Major changes:
- Remove old snippet rendering code and use the new stuff.
- Introduce `span_label` method to add a label
- Remove EndSpan mode and replace with a fn to get the last
character of a span.
- Stop using `Option<MultiSpan>` and just use an empty `MultiSpan`
- and probably a bunch of other stuff :)
Extract the code that performs the initialization of the LLVM backend
and invoke it before computing the available features. The
initialization is required to happen before the features are added to
the configuration, because they are computed by LLVM, therefore is is
now performed when creating the `Session` object.
As discussed in
https://github.com/rust-lang/rust/pull/32293#issuecomment-200597130,
adding link guards are a heuristic that is causing undue complications:
- the link guards inject extra public symbols, which is not always OK.
- link guards as implemented could be a non-trivial performance hit,
because no attempt is made to "de-duplicate" the dependency graph,
so at worst you have O(N!) calls to the link guard functions.
Nonetheless, link guards are very helpful in detecting errors, so it may
be worth adding them back in some modified form in the future.
This change has a few parts. We introduce a new `item_path` module for
constructing item paths. The job of this module is basically to make
nice, user-readable paths -- but these paths are not necessarily 100%
unique. They meant to help a *human* find code, but not necessarily a
compute. These paths are used to drive `item_path_str` but also symbol
names.
Because the paths are not unique, we also modify the symbol name hash to
include the full `DefPath`, whereas before it included only those
aspects of the def-path that were not included in the "informative"
symbol name.
Eventually, I'd like to make the item-path infrastructure a bit more
declarative. Right now it's based purely on strings. In particular, for
impls, we should supply the raw types to the `ItemPathBuffer`, so that
symbol names can be encoded using the C++ encoding scheme for better
integration with tooling.
We want to prevent compiling something against one version
of a dynamic library and then, at runtime accidentally
using a different version of the dynamic library. With the
old symbol-naming scheme this could not happen because every
symbol had the SVH in it and you'd get an error by the
dynamic linker when using the wrong version of a dylib. With
the new naming scheme this isn't the case any more, so this
patch adds the "link-guard" to prevent this error case.
This is implemented as follows:
- In every crate that we compile, we emit a function called
"__rustc_link_guard_<crate-name>_<crate-svh>"
- The body of this function contains calls to the
"__rustc_link_guard" functions of all dependencies.
- An executable contains a call to it's own
"__rustc_link_guard" function.
As a consequence the "__rustc_link_guard" function call graph
mirrors the crate graph and the dynamic linker will fail if a
wrong dylib is loaded somewhere because its
"__rustc_link_guard" function will contain a different SVH in
its name.
Automated conversion using the untry tool [1] and the following command:
```
$ find -name '*.rs' -type f | xargs untry
```
at the root of the Rust repo.
[1]: https://github.com/japaric/untry
Back in 9bc8e6d14 the linking of rlibs changed to using the `link_whole_rlib`
function. This change, however was only intended to affect dylibs, not
executables. For executables we don't actually want to link entire rlibs because
we want the linker to strip out as much as possible.
This commit adds a conditional to this logic to only link entire rlibs if we're
creating a dylib, and otherwise an executable just links an rlib as usual. A
test is included which will fail to link if this behavior is reverted.
Turning gc-sections off improves code coverage based for tools which
use DWARF debugging information (like kcov). Otherwise dead code is
stripped and kcov returns a coverage percentage that doesn't reflect
reality.
This tells trans:🔙:write not to LLVM codegen to create .o
files but to put LLMV bitcode in .o files.
Emscripten's emcc supports .o in this format, and this is,
I think, slightly easier than making rlibs work without .o
files.
This commit transitions the compiler to using the new exception handling
instructions in LLVM for implementing unwinding for MSVC. This affects both 32
and 64-bit MSVC as they're both now using SEH-based strategies. In terms of
standard library support, lots more details about how SEH unwinding is
implemented can be found in the commits.
In terms of trans, this change necessitated a few modifications:
* Branches were added to detect when the old landingpad instruction is used or
the new cleanuppad instruction is used to `trans::cleanup`.
* The return value from `cleanuppad` is not stored in an `alloca` (because it
cannot be).
* Each block in trans now has an `Option<LandingPad>` instead of `is_lpad: bool`
for indicating whether it's in a landing pad or not. The new exception
handling intrinsics require that on MSVC each `call` inside of a landing pad
is annotated with which landing pad that it's in. This change to the basic
block means that whenever a `call` or `invoke` instruction is generated we
know whether to annotate it as part of a cleanuppad or not.
* Lots of modifications were made to the instruction builders to construct the
new instructions as well as pass the tagging information for the call/invoke
instructions.
* The translation of the `try` intrinsics for MSVC has been overhauled to use
the new `catchpad` instruction. The filter function is now also a
rustc-generated function instead of a purely libstd-defined function. The
libstd definition still exists, it just has a stable ABI across architectures
and leaves some of the really weird implementation details to the compiler
(e.g. the `localescape` and `localrecover` intrinsics).
This brings some routine upgrades to the bundled LLVM that we're using, the most
notable of which is a bug fix to the way we handle range asserts when loading
the discriminant of an enum. This fix ended up being very similar to f9d4149c
where we basically can't have a range assert when loading a discriminant due to
filling drop, and appropriate flags were added to communicate this to
`trans::adt`.
LLVM was upgraded to a new version in this commit:
f9d4149c29
which was part of this pull request:
https://github.com/rust-lang/rust/issues/26025
Consider the following two lines from that commit:
f9d4149c29 (diff-a3b24dbe2ea7c1981f9ac79f9745f40aL462)f9d4149c29 (diff-a3b24dbe2ea7c1981f9ac79f9745f40aL469)
The purpose of these lines is to register LLVM passes. Prior to the that
commit, the passes being handled were assumed to be ModulePasses (a
specific type of LLVM pass) since they were being added to a ModulePass
manager. After that commit, both lines were refactored (presumably in an
attempt to DRY out the code), but the ModulePasses were changed to be
registered to a FunctionPass manager. This change resulted in
ModulePasses being run, but a Function object was being passed as a
parameter to the pass instead of a Module, which resulted in
segmentation faults.
In this commit, I changed relevant sections of the code to check the
type of the passes being added and register them to the appropriate pass
manager.
Closes https://github.com/rust-lang/rust/issues/31067
libfoo.a -> foo.lib
In order to not cause conflicts, changes the DLL import library name
foo.lib -> foo.dll.lib
Fixes https://github.com/rust-lang/rust/issues/29508
Because this changes output filenames this is a [breaking-change]
Signed-off-by: Peter Atashian <retep998@gmail.com>
The compiler can emit errors and warning in JSON format. This is a more easily machine readable form then the usual error output.
Closes#10492, closes#14863.