Currently if a print happens while a thread is being torn down it may cause a
panic if the LOCAL_STDOUT TLS slot has been destroyed by that point. This adds a
guard to check and prints to the process stdout if that's the case (as we do for
if the slot is already borrowed).
Closes#29488
If you try to put something that's bigger than a char into a char
literal, you get an error:
fn main() {
let c = 'ஶ்ரீ';
}
error: unterminated character constant:
This is a very compiler-centric message. Yes, it's technically
'unterminated', but that's not what you, the user did wrong.
Instead, this commit changes it to
error: character literal that's larger than a char:
As this actually tells you what went wrong.
Fixes#28851
If you try to put something that's bigger than a char into a char
literal, you get an error:
fn main() {
let c = 'ஶ்ரீ';
}
error: unterminated character constant:
This is a very compiler-centric message. Yes, it's technically
'unterminated', but that's not what you, the user did wrong.
Instead, this commit changes it to
error: character literal may only contain one codepoint
As this actually tells you what went wrong.
Fixes#28851
The "m" memory constraint in inline assembly is broken (generates incorrect code or triggers LLVM asserts) and should not be used. Instead, indirect memory operands should be used with "\*m", "=\*m" and "+\*m".
Clang does this transparently by transforming "m" constraints into "\*m" indirect constraints, but for now just being able to use "\*m" directly is enough since asm! isn't stable.
While "\*m" works fine as an input operand, "=\*m" and "+\*m" need to be specified as input operands because they take a pointer value as an input. This PR relaxes the constraint checker to allow constraints starting with "=" or "+" if the constraint string contains a "\*", which indicates an indirect operand.
This (indirectly) fixes these issues: #29382, #16383 and #13366. The code will need to be changed to use "\*m" instead of "m".
Function arguments that are small aggregates get passed as integer types
instead. To correctly handle that, we need to use store_ty instead of
plain Store.
This branch implements a variant of trans that is based on MIR. It is very incomplete (intentionally), and had only the goal of laying out enough work to enable more incremental follow-on patches. Currently, only fns tagged with `#[rustc_mir]` use the new trans code. I plan to build up a meta-issue as well that tracks the various "not-yet-implemented" points. The only fn that has been tested so far is this amazingly complex "spike" fn:
```rust
#[rustc_mir]
fn sum(x: i32, y: i32) -> i32 {
x + y
}
```
In general, the most interesting commit is the last one. There are some points on which I would like feedback from @rust-lang/compiler:
- I did not use `Datum`. Originally, I thought that maybe just a `ValueRef` would be enough but I wound up with two very simple structures, `LvalueRef` and `OperandRef`, that just package up a `ValueRef` and a type. Because of MIR's structure, you don't wind up mixing by-ref and by-value so much, and I tend to think that a thinner abstraction layer is better here, but I'm not sure.
- Related to the above, I expect that sooner or later we will analyze temps (and maybe variables too) to find those whose address is never taken and which are word-sized and which perhaps meet a few other criteria. For those, we'll probably want to avoid the alloca, just because it means prettier code.
- I generally tried to re-use data structures from elsewhere in trans, though I'm sure we can trim these down.
- I didn't do any debuginfo primarily because it seems to want node-ids and we have only spans. I haven't really read into that code so I don't know what's going on there.
r? @nrc
`resolve_identifier` used to mark a variable as an upvar when used within a closure. However, the function is also used for the "unnecessary qualification" lint, which would mark paths whose last component had the same name as a local as upvars.
Fixes#29522
r? @eddyb
The public set is expanded with trait items, impls and their items, foreign items, exported macros, variant fields, i.e. all the missing parts. Now it's a subset of the exported set.
This is needed for https://github.com/rust-lang/rust/pull/29083 because stability annotation pass uses the public set and all things listed above need to be annotated.
Rustdoc can now be migrated to the public set as well, I guess.
Exported set is now slightly more correct with regard to exported items in blocks - 1) blocks in foreign items are considered and 2) publicity is not inherited from the block's parent - if a function is public it doesn't mean structures defined in its body are public.
r? @alexcrichton or maybe someone else
Note: for now, this change only affects `-windows-gnu` builds.
So why was this `libgcc` dylib dependency needed in the first place?
The stack unwinder needs to know about locations of unwind tables of all the modules loaded in the current process. The easiest portable way of achieving this is to have each module register itself with the unwinder when loaded into the process. All modules compiled by GCC do this by calling the __register_frame_info() in their startup code (that's `crtbegin.o` and `crtend.o`, which are automatically linked into any gcc output).
Another important piece is that there should be only one copy of the unwinder (and thus unwind tables registry) in the process. This pretty much means that the unwinder must be in a shared library (unless everything is statically linked).
Now, Rust compiler tries very hard to make sure that any given Rust crate appears in the final output just once. So if we link the unwinder statically to one of Rust's crates, everything should be fine.
Unfortunately, GCC startup objects are built under assumption that `libgcc` is the one true place for the unwind info registry, so I couldn't find any better way than to replace them. So out go `crtbegin`/`crtend`, in come `rsbegin`/`rsend`!
A side benefit of this change is that rustc is now more in control of the command line that goes to the linker, so we could stop using `gcc` as the linker driver and just invoke `ld` directly.
Motivation:
- It is not actually a pattern
- It is not actually needed, except for...
Drawback:
- Slice patterns like `[a, _.., b]` are pretty-printed as `[a, .., b]`. Great loss :(
plugin-[breaking-change], as always
Similarly to the simd intrinsics. I believe this is a better solution than #29288, and I could implement it as well for overflowing_add/sub/mul. Also rename from udiv/sdiv to div, and same for rem.
Currently if a print happens while a thread is being torn down it may cause a
panic if the LOCAL_STDOUT TLS slot has been destroyed by that point. This adds a
guard to check and prints to the process stdout if that's the case (as we do for
if the slot is already borrowed).
Closes#29488
This fixes#29048 (though I think adding better transactional support would be a better fix for that issue, but that is more difficult). It also simplifies region inference and changes the model to a pure data flow one, as discussed in [this internals thread](https://internals.rust-lang.org/t/rough-thoughts-on-the-impl-of-region-inference-mir-etc/2800). I am not 100% sure though if this PR is the right thing to do -- or at least maybe not at this moment, so thoughts on that would be appreciated.
r? @pnkfelix
cc @arielb1
This helps for the case where a match, such as below:
```rust
let foo = match foo {
Some(x) => x,
None => 0
};
```
gets refactored to no longer need the match, but the match keyword has been left accidentally:
```rust
let foo = match foo.unwrap_or(0);
```
This can be hard to spot as the expression grows more complex.
r? @alexcrichton
expansion already by growing the RHS to be bigger than LHS (all the way
to `'static` if necessary). This is needed because contraction doesn't
handle givens. Fixes#28934.
Fix corner case in privacy that was causing ICEs when the `source_did` was not crate-local.
Full confession: I only kinda sorta understand this code, but afaict it's legit for `source_did` to be from another crate.
r? @alexcrichton
when evaluating a recursive type, the `type_of` of the interior could be
still in progress, so trying to get its size would cause an ICE.
Fixes#19001
r? @eddyb
Closes#29314
The code from #29314:
```rust
fn main() {
if let Some(b) = None {
()
} else {
1
};
}
```
now prints this:
```
test.rs:2:5: 6:6 error: `if let` arms have incompatible types: expected `()`, found `_` (expected (), found integral variable) [E0308]
test.rs:2 if let Some(b) = None {
test.rs:3 ()
test.rs:4 } else {
test.rs:5 1
test.rs:6 };
test.rs:2:5: 6:6 help: run `rustc --explain E0308` to see a detailed explanation
test.rs:4:12: 6:6 note: `if let` arm with an incompatible type
test.rs:4 } else {
test.rs:5 1
test.rs:6 };
error: aborting due to previous error
```