As part of #20432, upvar checking is now moved out of regionck to its
own pass and before regionck. But regionck has some type resolution of
its own. Without them, now separated upvar checking may be tripped over
by residue `ty_infer`.
Closes#21306
Two minor improvements that have been on my TODO list for a while:
* Clang uses a size of `-1` for arrays of unknown size and we should do that too as it will tell LLVM to omit the size information in debuginfo.
* There was no LLDB test case for handling the optimized enum representation introduced by @luqmana. This PR finally adds one.
Before:
```
error: invalid operand for inline asm constraint 'i' at line 11
```
Note that 11 is not the line the inline assembly appears in.
After:
```
src/arch/x64/multiboot/bootstrap.rs:203:5: 209:9 error: invalid operand for inline asm constraint 'i'
src/arch/x64/multiboot/bootstrap.rs:203 asm! {
src/arch/x64/multiboot/bootstrap.rs:204 [multiboot => %ecx, mod attsyntax]
src/arch/x64/multiboot/bootstrap.rs:205
src/arch/x64/multiboot/bootstrap.rs:206 ljmp {size_of::<Descriptor>() => %i}, $bootstrap.64
src/arch/x64/multiboot/bootstrap.rs:207 }
src/arch/x64/multiboot/bootstrap.rs:208
...
error: aborting due to previous error
```
E.g. `fn foo() { foo() }`, or, more subtlely
impl Foo for Box<Foo+'static> {
fn bar(&self) {
self.bar();
}
}
The compiler will warn and point out the points where recursion occurs,
if it determines that the function cannot return without calling itself.
Closes#17899.
---
This is highly non-perfect, in particular, my wording above is quite precise, and I have some unresolved questions: This currently will warn about
```rust
fn foo() {
if bar { loop {} }
foo()
}
```
even though `foo` may never be called (i.e. our apparent "unconditional" recursion is actually conditional). I don't know if we should handle this case, and ones like it with `panic!()` instead of `loop` (or anything else that "returns" `!`).
However, strictly speaking, it seems to me that changing the above to not warn will require changing
```rust
fn foo() {
while bar {}
foo()
}
```
to also not warn since it could be that the `while` is an infinite loop and doesn't ever hit the `foo`.
I'm inclined to think we let these cases warn since true edge cases like the first one seem rare, and if they do occur they seem like they would usually be typos in the function call. (I could imagine someone accidentally having code like `fn foo() { assert!(bar()); foo() /* meant to be boo() */ }` which won't warn if the `loop` case is "fixed".)
(Part of the reason this is unresolved is wanting feedback, part of the reason is I couldn't devise a strategy that worked in all cases.)
---
The name `unconditional_self_calls` is kinda clunky; and this reconstructs the CFG for each function that is linted which may or may not be very expensive, I don't know.
This commit relaxes the bound on `Result::unwrap` and `Result::unwrap_err` from
the `Display` trait to the `Debug` trait for generating an error message about
the unwrapping operation.
This commit is a breaking change and any breakage should be mitigated by
ensuring that `Debug` is implemented on the relevant type.
[breaking-change]
This adds a new lexer/parser combo for the entire Rust language can be generated with with flex and bison, taken from my project at https://github.com/bleibig/rust-grammar. There is also a testing script that runs the generated parser with all *.rs files in the repository (except for tests in compile-fail or ones that marked as "ignore-test" or "ignore-lexer-test"). If you have flex and bison installed, you can run these tests using the new "check-grammar" make target.
This does not depend on or interact with the existing testing code in the grammar, which only provides and tests a lexer specification.
OS X users should take note that the version of bison that comes with the Xcode toolchain (2.3) is too old to work with this grammar, they need to download and install version 3.0 or later.
The parser builds up an S-expression-based AST, which can be displayed by giving the "-v" argument to parser-lalr (normally it only gives output on error). It is only a rough approximation of what is parsed and doesn't capture every detail and nuance of the program.
Hopefully this should be sufficient for issue #2234, or at least a good starting point.
Per [RFC 517](https://github.com/rust-lang/rfcs/pull/575/), this commit introduces platform-native strings. The API is essentially as described in the RFC.
The WTF-8 implementation is adapted from @SimonSapin's [implementation](https://github.com/SimonSapin/rust-wtf8). To make this work, some encodign and decoding functionality in `libcore` is now exported in a "raw" fashion reusable for WTF-8. These exports are *not* reexported in `std`, nor are they stable.
Per [RFC 517](https://github.com/rust-lang/rfcs/pull/575/), this commit
introduces platform-native strings. The API is essentially as described
in the RFC.
The WTF-8 implementation is adapted from @SimonSapin's
[implementation](https://github.com/SimonSapin/rust-wtf8). To make this
work, some encodign and decoding functionality in `libcore` is now
exported in a "raw" fashion reusable for WTF-8. These exports are *not*
reexported in `std`, nor are they stable.
E.g. `fn foo() { foo() }`, or, more subtlely
impl Foo for Box<Foo+'static> {
fn bar(&self) {
self.bar();
}
}
The compiler will warn and point out the points where recursion occurs,
if it determines that the function cannot return without calling itself.
Closes#17899.
Fixes#19759
I'm not going to bother to do more than this, as it'll end up getting re-done as part of the reference work, but at least it's correct now.
Fix for `error: functions used as tests must have signature fn() -> ()` and `error: functions used as benches must have signature `fn(&mut Bencher) -> ()` in case of explicit return type declaration.
While trying to experiment with changes for some other issues, I noticed that the test for #15149 was failing because I have `/tmp` mounted as `noexec` on my Linux box, and that test tries to run out of a temporary directory. This may not be the most common case, but it's not rare by any means, because executing from a world-writable directory is a security problem. (For this reason, some kernel options/mods such as grsecurity also can prevent this on Linux.) I instead copy the executable to a directory created in the build tree, following the example of the `process-spawn-with-unicode-params` test.
After I made that change, I noticed that I'd made a mistake, but the test was still passing, because the "parent" process was not actually checking the status of the "child" process, meaning that the assertion in the child could never cause the overall test to fail. (I don't know if this has always been the case, or if it has something to do with either Windows or a change in the semantics of `spawn`.) So I fixed the test so that it would fail correctly, then fixed my original mistake so that it would pass again.
The one big problem with this is that I haven't set up any machines of my own so that I can build on Windows, which is the platform this test was targeted at in the first place! That might take a while to address on my end. So I need someone else to check this on Windows.
The base64 support can be trivially removed (there are no in-tree users) and the regex support is a whopping 4k lines of code to maintain for a few non-critical uses in-tree. This commit migrates all current users in-tree away from regexes to custom matching code.
The most critical application affected by this migration is that the testing framework no longer considers filter arguments as regexes, but rather just a substring matching. It is expected that more featureful testing frameworks can evolve outside of the in-tree libtest version over time which can properly depend on libregex from crates.io.
[breaking-change]
The regex library was largely used for non-critical aspects of the compiler and
various external tooling. The library at this point is duplicated with its
out-of-tree counterpart and as such imposes a bit of a maintenance overhead as
well as compile time hit for the compiler itself.
The last major user of the regex library is the libtest library, using regexes
for filters when running tests. This removal means that the filtering has gone
back to substring matching rather than using regexes.
This allows one to look at an `ExprMethodCall` `foo.bar()` where `bar`
is a method in some trait and (sometimes) extract the `impl` that `bar`
is defined in, e.g.
trait Foo {
fn bar(&self);
}
impl Foo for uint { // <A>
fn bar(&self) {}
}
fn main() {
1u.bar(); // impl_def_id == Some(<A>)
}
This definitely doesn't handle all cases, but is correct when it is
known, meaning it should only be used for certain linting/heuristic
purposes; no safety analysis.