When generating a unique symbol for things like closures or glue_drop,
we call token::gensym() to create a crate-unique Name. Recently, Name
changed its Show impl so it no longer prints as a number. This caused
symbols like glue_drop:1542 to become glue_drop:"glue_drop"(1542), or in
mangled form, glue_drop.$x22glue_drop$x22$LP$1542$RP$.
Our implementation of ebml has diverged from the standard in order
to better serve the needs of the compiler, so it doesn't make much
sense to call what we have ebml anyore. Furthermore, our implementation
is pretty crufty, and should eventually be rewritten into a format
that better suits the needs of the compiler. This patch factors out
serialize::ebml into librbml, otherwise known as the Really Bad
Markup Language. This is a stopgap library that shouldn't be used
by end users, and will eventually be replaced by something better.
[breaking-change]
Currently, each time a function is monomorphized, all items within that function are translated. This is unnecessary work because the inner items already get translated when the function declaration is visited by `trans_item`. This patch adds a flag to the `FunctionContext` to prevent translation of items during monomorphization.
Remove the ability of the borrow checker to determine that repeated
dereferences of a Box<T> refer to the same memory object. This will
usually require one of two workarounds:
1) The interior of a Box<T> will sometimes need to be moved / borrowed
into a temporary before moving / borrowing individual derived paths.
2) A `ref x` pattern will have to be replaced with a `box ref x`
pattern.
Fixes#16094.
[breaking-change]
the CFG for match statements.
There were two bugs in issue #14684. One was simply that the borrow
check didn't know about the correct CFG for match statements: the
pattern must be a predecessor of the guard. This disallows the bad
behavior if there are bindings in the pattern. But it isn't enough to
prevent the memory safety problem, because of wildcards; thus, this
patch introduces a more restrictive rule, which disallows assignments
and mutable borrows inside guards outright.
I discussed this with Niko and we decided this was the best plan of
action.
This breaks code that performs mutable borrows in pattern guards. Most
commonly, the code looks like this:
impl Foo {
fn f(&mut self, ...) {}
fn g(&mut self, ...) {
match bar {
Baz if self.f(...) => { ... }
_ => { ... }
}
}
}
Change this code to not use a guard. For example:
impl Foo {
fn f(&mut self, ...) {}
fn g(&mut self, ...) {
match bar {
Baz => {
if self.f(...) {
...
} else {
...
}
}
_ => { ... }
}
}
}
Sometimes this can result in code duplication, but often it illustrates
a hidden memory safety problem.
Closes#14684.
[breaking-change]
r? @pnkfelix
Some minor changes to the compiler to expose this information. Very
inconvenient since struct fields aren't an item. Adds (yet another) table to
metadata.
Closes#15739
This commit applies stability attributes to the contents of these modules,
summarized here:
* The `unit` and `bool` modules have become #[unstable] as they are purely meant
for documentation purposes and are candidates for removal.
* The `ty` module has been deprecated, and the inner `Unsafe` type has been
renamed to `UnsafeCell` and moved to the `cell` module. The `marker1` field
has been removed as the compiler now always infers `UnsafeCell` to be
invariant. The `new` method i stable, but the `value` field, `get` and
`unwrap` methods are all unstable.
* The `tuple` module has its name as stable, the naming of the `TupleN` traits
as stable while the methods are all #[unstable]. The other impls in the module
have appropriate stability for the corresponding trait.
* The `arc` module has received the exact same treatment as the `rc` module
previously did.
* The `any` module has its name as stable. The `Any` trait is also stable, with
a new private supertrait which now contains the `get_type_id` method. This is
to make the method a private implementation detail rather than a public-facing
detail.
The two extension traits in the module are marked #[unstable] as they will not
be necessary with DST. The `is` method is #[stable], the as_{mut,ref} methods
have been renamed to downcast_{mut,ref} and are #[unstable].
The extension trait `BoxAny` has been clarified as to why it is unstable as it
will not be necessary with DST.
This is a breaking change because the `marker1` field was removed from the
`UnsafeCell` type. To deal with this change, you can simply delete the field and
only specify the value of the `data` field in static initializers.
[breaking-change]
Currently we don't emit lifetime end markers when translating the
unwinding code. I omitted that when I added the support for lifetime
intrinsics, because I initially made the mistake of just returning true
in clean_on_unwind(). That caused almost all calls to be translated as
invokes, leading to quite awful results.
To correctly emit the lifetime end markers, we must differentiate
between cleanup that requires unwinding and such cleanup that just wants
to emit code during unwinding.
the CFG for match statements.
There were two bugs in issue #14684. One was simply that the borrow
check didn't know about the correct CFG for match statements: the
pattern must be a predecessor of the guard. This disallows the bad
behavior if there are bindings in the pattern. But it isn't enough to
prevent the memory safety problem, because of wildcards; thus, this
patch introduces a more restrictive rule, which disallows assignments
and mutable borrows inside guards outright.
I discussed this with Niko and we decided this was the best plan of
action.
This breaks code that performs mutable borrows in pattern guards. Most
commonly, the code looks like this:
impl Foo {
fn f(&mut self, ...) {}
fn g(&mut self, ...) {
match bar {
Baz if self.f(...) => { ... }
_ => { ... }
}
}
}
Change this code to not use a guard. For example:
impl Foo {
fn f(&mut self, ...) {}
fn g(&mut self, ...) {
match bar {
Baz => {
if self.f(...) {
...
} else {
...
}
}
_ => { ... }
}
}
}
Sometimes this can result in code duplication, but often it illustrates
a hidden memory safety problem.
Closes#14684.
[breaking-change]
Currently we don't emit lifetime end markers when translating the
unwinding code. I omitted that when I added the support for lifetime
intrinsics, because I initially made the mistake of just returning true
in clean_on_unwind(). That caused almost all calls to be translated as
invokes, leading to quite awful results.
To correctly emit the lifetime end markers, we must differentiate
between cleanup that requires unwinding and such cleanup that just wants
to emit code during unwinding.
method calls are involved.
This breaks code like:
impl<T:Copy> Foo for T { ... }
fn take_param<T:Foo>(foo: &T) { ... }
fn main() {
let x = box 3i; // note no `Copy` bound
take_param(&x);
}
Change this code to not contain a type error. For example:
impl<T:Copy> Foo for T { ... }
fn take_param<T:Foo>(foo: &T) { ... }
fn main() {
let x = 3i; // satisfies `Copy` bound
take_param(&x);
}
Closes#15860.
[breaking-change]
r? @alexcrichton
method calls are involved.
This breaks code like:
impl<T:Copy> Foo for T { ... }
fn take_param<T:Foo>(foo: &T) { ... }
fn main() {
let x = box 3i; // note no `Copy` bound
take_param(&x);
}
Change this code to not contain a type error. For example:
impl<T:Copy> Foo for T { ... }
fn take_param<T:Foo>(foo: &T) { ... }
fn main() {
let x = 3i; // satisfies `Copy` bound
take_param(&x);
}
Closes#15860.
[breaking-change]
librustc: Stop desugaring `for` expressions and translate them directly.
This makes edge cases in which the `Iterator` trait was not in scope
and/or `Option` or its variants were not in scope work properly.
This breaks code that looks like:
struct MyStruct { ... }
impl MyStruct {
fn next(&mut self) -> Option<int> { ... }
}
for x in MyStruct { ... } { ... }
Change ad-hoc `next` methods like the above to implementations of the
`Iterator` trait. For example:
impl Iterator<int> for MyStruct {
fn next(&mut self) -> Option<int> { ... }
}
Closes#15392.
[breaking-change]
This makes edge cases in which the `Iterator` trait was not in scope
and/or `Option` or its variants were not in scope work properly.
This breaks code that looks like:
struct MyStruct { ... }
impl MyStruct {
fn next(&mut self) -> Option<int> { ... }
}
for x in MyStruct { ... } { ... }
Change ad-hoc `next` methods like the above to implementations of the
`Iterator` trait. For example:
impl Iterator<int> for MyStruct {
fn next(&mut self) -> Option<int> { ... }
}
Closes#15392.
[breaking-change]
This is done entirely in the libraries for functions up to 16 arguments.
A macro is used so that more arguments can be easily added if we need.
Note that I had to adjust the overloaded call algorithm to not try
calling the overloaded call operator if the callee is a built-in
function type, to prevent loops.
Closes#15448.
This eliminates the last vestige of the `~` syntax.
Instead of `~self`, write `self: Box<TypeOfSelf>`; instead of `mut
~self`, write `mut self: Box<TypeOfSelf>`, replacing `TypeOfSelf` with
the self-type parameter as specified in the implementation.
Closes#13885.
[breaking-change]
The allocas used in match expression currently don't get good lifetime
markers, in fact they only get lifetime start markers, because their
lifetimes don't match to cleanup scopes.
While the bindings themselves are bog standard and just need a matching
pair of start and end markers, they might need them twice, once for a
guard clause and once for the match body.
The __llmatch alloca OTOH needs a single lifetime start marker, but
when there's a guard clause, it needs two end markers, because its
lifetime ends either when the guard doesn't match or after the match
body.
With these intrinsics in place, LLVM can now, for example, optimize
code like this:
````rust
enum E {
A1(int),
A2(int),
A3(int),
A4(int),
}
pub fn variants(x: E) {
match x {
A1(m) => bar(&m),
A2(m) => bar(&m),
A3(m) => bar(&m),
A4(m) => bar(&m),
}
}
````
To a single call to bar, using only a single stack slot. It still fails
to eliminate some of checks.
````gas
.Ltmp5:
.cfi_def_cfa_offset 16
movb (%rdi), %al
testb %al, %al
je .LBB3_5
movzbl %al, %eax
cmpl $1, %eax
je .LBB3_5
cmpl $2, %eax
.LBB3_5:
movq 8(%rdi), %rax
movq %rax, (%rsp)
leaq (%rsp), %rdi
callq _ZN3bar20hcb7a0d8be8e17e37daaE@PLT
popq %rax
retq
````
Lifetime intrinsics help to reduce stack usage, because LLVM can apply
stack coloring to reuse the stack slots of dead allocas for new ones.
For example these functions now both use the same amount of stack, while
previous `bar()` used five times as much as `foo()`:
````rust
fn foo() {
println("{}", 5);
}
fn bar() {
println("{}", 5);
println("{}", 5);
println("{}", 5);
println("{}", 5);
println("{}", 5);
}
````
On top of that, LLVM can also optimize out certain operations when it
knows that memory is dead after a certain point. For example, it can
sometimes remove the zeroing used to cancel the drop glue. This is
possible when the glue drop itself was already removed because the
zeroing dominated the drop glue call. For example in:
````rust
pub fn bar(x: (Box<int>, int)) -> (Box<int>, int) {
x
}
````
With optimizations, this currently results in:
````llvm
define void @_ZN3bar20h330fa42547df8179niaE({ i64*, i64 }* noalias nocapture nonnull sret, { i64*, i64 }* noalias nocapture nonnull) unnamed_addr #0 {
"_ZN29_$LP$Box$LT$int$GT$$C$int$RP$39glue_drop.$x22glue_drop$x22$LP$1347$RP$17h88cf42702e5a322aE.exit":
%2 = bitcast { i64*, i64 }* %1 to i8*
%3 = bitcast { i64*, i64 }* %0 to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 16, i32 8, i1 false)
tail call void @llvm.memset.p0i8.i64(i8* %2, i8 0, i64 16, i32 8, i1 false)
ret void
}
````
But with lifetime intrinsics we get:
````llvm
define void @_ZN3bar20h330fa42547df8179niaE({ i64*, i64 }* noalias nocapture nonnull sret, { i64*, i64 }* noalias nocapture nonnull) unnamed_addr #0 {
"_ZN29_$LP$Box$LT$int$GT$$C$int$RP$39glue_drop.$x22glue_drop$x22$LP$1347$RP$17h88cf42702e5a322aE.exit":
%2 = bitcast { i64*, i64 }* %1 to i8*
%3 = bitcast { i64*, i64 }* %0 to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 16, i32 8, i1 false)
tail call void @llvm.lifetime.end(i64 16, i8* %2)
ret void
}
````
Fixes#15665
Lifetime intrinsics help to reduce stack usage, because LLVM can apply
stack coloring to reuse the stack slots of dead allocas for new ones.
For example these functions now both use the same amount of stack, while
previous `bar()` used five times as much as `foo()`:
````rust
fn foo() {
println("{}", 5);
}
fn bar() {
println("{}", 5);
println("{}", 5);
println("{}", 5);
println("{}", 5);
println("{}", 5);
}
````
On top of that, LLVM can also optimize out certain operations when it
knows that memory is dead after a certain point. For example, it can
sometimes remove the zeroing used to cancel the drop glue. This is
possible when the glue drop itself was already removed because the
zeroing dominated the drop glue call. For example in:
````rust
pub fn bar(x: (Box<int>, int)) -> (Box<int>, int) {
x
}
````
With optimizations, this currently results in:
````llvm
define void @_ZN3bar20h330fa42547df8179niaE({ i64*, i64 }* noalias nocapture nonnull sret, { i64*, i64 }* noalias nocapture nonnull) unnamed_addr #0 {
"_ZN29_$LP$Box$LT$int$GT$$C$int$RP$39glue_drop.$x22glue_drop$x22$LP$1347$RP$17h88cf42702e5a322aE.exit":
%2 = bitcast { i64*, i64 }* %1 to i8*
%3 = bitcast { i64*, i64 }* %0 to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 16, i32 8, i1 false)
tail call void @llvm.memset.p0i8.i64(i8* %2, i8 0, i64 16, i32 8, i1 false)
ret void
}
````
But with lifetime intrinsics we get:
````llvm
define void @_ZN3bar20h330fa42547df8179niaE({ i64*, i64 }* noalias nocapture nonnull sret, { i64*, i64 }* noalias nocapture nonnull) unnamed_addr #0 {
"_ZN29_$LP$Box$LT$int$GT$$C$int$RP$39glue_drop.$x22glue_drop$x22$LP$1347$RP$17h88cf42702e5a322aE.exit":
%2 = bitcast { i64*, i64 }* %1 to i8*
%3 = bitcast { i64*, i64 }* %0 to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %2, i64 16, i32 8, i1 false)
tail call void @llvm.lifetime.end(i64 16, i8* %2)
ret void
}
````
Fixes#15665
`call_visit_glue` is only ever called from trans_intrinsic, and the
block won't be unreachable there. Also, the comment doesn't make sense
anymore. When the code was introduced in 38fee9526a the function was
also responsible for the cleanup glue, which is no longer the case.
While we're at it, also fixed the debug message to output the right
function name.
This implements RFC 39. Omitted lifetimes in return values will now be
inferred to more useful defaults, and an error is reported if a lifetime
in a return type is omitted and one of the two lifetime elision rules
does not specify what it should be.
This primarily breaks two uncommon code patterns. The first is this:
unsafe fn get_foo_out_of_thin_air() -> &Foo {
...
}
This should be changed to:
unsafe fn get_foo_out_of_thin_air() -> &'static Foo {
...
}
The second pattern that needs to be changed is this:
enum MaybeBorrowed<'a> {
Borrowed(&'a str),
Owned(String),
}
fn foo() -> MaybeBorrowed {
Owned(format!("hello world"))
}
Change code like this to:
enum MaybeBorrowed<'a> {
Borrowed(&'a str),
Owned(String),
}
fn foo() -> MaybeBorrowed<'static> {
Owned(format!("hello world"))
}
Closes#15552.
[breaking-change]
r? @nick29581
This is accomplished by rewriting static expressions into equivalent patterns.
This way, patterns referencing static variables can both participate
in exhaustiveness analysis as well as be compiled down into the appropriate
branch of the decision trees that match expressions are codegened to.
Fixes#6533.
Fixes#13626.
Fixes#13731.
Fixes#14576.
Fixes#15393.
This implements RFC 39. Omitted lifetimes in return values will now be
inferred to more useful defaults, and an error is reported if a lifetime
in a return type is omitted and one of the two lifetime elision rules
does not specify what it should be.
This primarily breaks two uncommon code patterns. The first is this:
unsafe fn get_foo_out_of_thin_air() -> &Foo {
...
}
This should be changed to:
unsafe fn get_foo_out_of_thin_air() -> &'static Foo {
...
}
The second pattern that needs to be changed is this:
enum MaybeBorrowed<'a> {
Borrowed(&'a str),
Owned(String),
}
fn foo() -> MaybeBorrowed {
Owned(format!("hello world"))
}
Change code like this to:
enum MaybeBorrowed<'a> {
Borrowed(&'a str),
Owned(String),
}
fn foo() -> MaybeBorrowed<'static> {
Owned(format!("hello world"))
}
Closes#15552.
[breaking-change]
This is accomplished by rewriting static expressions into equivalent patterns.
This way, patterns referencing static variables can both participate
in exhaustiveness analysis as well as be compiled down into the appropriate
branch of the decision trees that match expressions are codegened to.
Fixes#6533.
Fixes#13626.
Fixes#13731.
Fixes#14576.
Fixes#15393.
Removed `index_to_bitset` field and `_frozen` methods.
Drive-by: Added some missing docs on the `each_bit` method.
Drive-by: Put in a regular pattern: when calling `compute_id_range`, ensure `words_per_id > 0` by either asserting it or checking and returning early. (The prior code did the latter in a few cases where necessary, but debugging is much aided by the asserts.)
Fix#15019.
`call_visit_glue` is only ever called from trans_intrinsic, and the
block won't be unreachable there. Also, the comment doesn't make sense
anymore. When the code was introduced in 38fee9526a the function was
also responsible for the cleanup glue, which is no longer the case.
While we're at it, also fixed the debug message to output the right
function name.
Importing from types was disallowed in #6462. Flag was set for paths whether it is a module or a type. Type flag was set when impl was seen. The problem is, for cross-crate situations, when reexport is involved, it is possible that impl is seen too late because metadata is loaded lazily.
Fix#15664.
This should fix issue #15541. It would be good to have an test case for this would also be nice but I haven't had the time to write one. The change is very small though and it doesn't break anything in the existing test suite, so I guess we can add it without test for now.
except where trait objects are involved.
Part of issue #15349, though I'm leaving it open for trait objects.
Cross borrowing for trait objects remains because it is needed until we
have DST.
This will break code like:
fn foo(x: &int) { ... }
let a = box 3i;
foo(a);
Change this code to:
fn foo(x: &int) { ... }
let a = box 3i;
foo(&*a);
[breaking-change]
This makes two changes to region inference: (1) it allows region
inference to relate early-bound regions; and (2) it allows regions to be
related before variance runs. The former is needed because there is no
relation between the two regions before region substitution happens,
while the latter is needed because type collection has to run before
variance. We assume that, before variance is inferred, that lifetimes
are invariant. This is a conservative overapproximation.
This relates to #13885. This does not remove `~self` from the language
yet, however.
[breaking-change]
Disabling the redzone is required in x86-64's kernel mode to avoid interrupts trashing the stack.
I'm not sure if decl_fn is the right place to tag all functions with noredzone. It might have interactions with external functions when linking with bitcode built without -C no-redzone although I see no reason to do that.
I'm not sure how to write a test inspecting the bitcode output for noredzone attributes on all functions either.
This patch applies the excellent suggestion of @pnkfelix to group the helper methods for method field access into a Trait, making the code much more readable, and much more similar to the way it was before.
Closes#15525
The important bit of this are the changes from line 445 in mem_categorization.rs. Most of the other changes are about adding an Implicit PointerKind, and this is only necessary for getting a decent error message :-s An alternative would have been to add an implciti/explicit flag to cat_deref, which could be mostly ignored and so would mean much fewer changes. However, the implicit state would only be valid if the PointerKind was BorrowedPtr, so it felt like it ought to be another kind of PointerKind. I still don't know which is the better design.
To verify that a type can satisfy Send
`check_struct_safe_for_destructor` attempts to construct a new `ty::t`
an empty substitution list.
Previously the function would verify that the function has no type
parameters before attempting this. Unfortunately this check would not
catch functions with only regions parameters. In this case, the type
would eventually find its way to the substition engine which would
attempt to perform a substitution on the region parameters. As the
constructed substitution list is empty, this would fail, leading to a
compiler crash.
We fix this by verifying that types have both no type and region
parameters.
Previously this was an Option::unwrap() which failed for me.
Unfortunately I've since inadvertently worked around the bug and have
been unable to reproduce it. With this patch hopefully the next person
to encounter this will be in a slightly better position to debug it.
Per @pnkfelix 's suggestion, using a trait to make these
field accesses more readable (and vastly more similar
to the original code.
oops fix new ast_map fix
Use one or more of the following `-Z` flag options to tell the
graphviz renderer to include the corresponding dataflow sets (after
the iterative constraint propagation reaches a fixed-point solution):
* `-Z flowgraph-print-loans` : loans computed via middle::borrowck
* `-Z flowgraph-print-moves` : moves computed via middle::borrowck::move_data
* `-Z flowgraph-print-assigns` : assignments, via middle::borrowck::move_data
* `-Z flowgraph-print-all` : all of the available sets are included.
Fix#15016.
Use one or more of the following `-Z` flag options to tell the
graphviz renderer to include the corresponding dataflow sets (after
the iterative constraint propagation reaches a fixed-point solution):
* `-Z flowgraph-print-loans` : loans computed via middle::borrowck
* `-Z flowgraph-print-moves` : moves computed via middle::borrowck::move_data
* `-Z flowgraph-print-assigns` : assignments, via middle::borrowck::move_data
* `-Z flowgraph-print-all` : all of the available sets are included.
Fix#15016.
----
This also adds a module, `syntax::ast_map::blocks`, that captures a
common abstraction shared amongst code blocks and procedure-like
things. As part of this, moved `ast_map.rs` to subdir
`ast_map/mod.rs`, to follow our directory layout conventions.
(incorporated review feedback from huon, acrichto.)