This new variant introduces finer-grain code extents, i.e. we now
track that a binding lives only for a suffix of a block, and
(importantly) will be dropped when it goes out of scope *before* the
bindings that occurred earlier in the block.
Both of these notions are neatly captured by marking the block (and
each suffix) as an enclosing scope of the next suffix beneath it.
This is work that is part of the foundation for issue #8861.
(It actually has been seen in earlier posted pull requests; I have
just factored it out into its own PR to ease my own rebasing.)
----
These finer grained scopes do mean that some code is newly rejected by
`rustc`; for example:
```rust
let mut map : HashMap<u8, &u8> = HashMap::new();
let tmp = Box::new(2);
map.insert(43, &*tmp);
```
This will now fail to compile with a message that `*tmp` does not live
long enough, because the scope of `tmp` is now strictly smaller than
that of `map`, and the use of `&u8` in map's type requires that the
borrowed references are all to data that live at least as long as the
map.
The usual fix for a case like this is to move the binding for `tmp`
up above that of `map`; note that you can still leave the initialization
in the original spot, like so:
```rust
let tmp;
let mut map : HashMap<u8, &u8> = HashMap::new();
tmp = box 2;
map.insert(43, &*tmp);
```
Similarly, one can encounter an analogous situation with `Vec`: one
would need to rewrite:
```rust
let mut vec = Vec::new();
let tmp = 'c';
vec.push(&tmp);
```
as:
```
let tmp;
let mut vec = Vec::new();
tmp = 'c';
vec.push(&tmp);
```
----
In some corner cases, it does not suffice to reorder the bindings; in
particular, when the types for both bindings need to reflect exactly
the *same* code extent, and a parent/child relationship between them
does not work.
In pnkfelix's experience this has arisen most often when mixing uses
of cyclic data structures while also allowing a lifetime parameter
`'a` to flow into a type parameter context where the type is
*invariant* with respect to the type parameter. An important instance
of this is `arena::TypedArena<T>`, which is invariant with respect
to `T`.
(The reason that variance is relevant is this: *if* `TypedArena` were
covariant with respect to its type parameter, then we could assign it
the longer lifetime when it is initialized, and then convert it to a
subtype (via covariance) with a shorter lifetime when necessary. But
`TypedArena` is invariant with respect to its type parameter, and thus
if `S` is a subtype of `T` (in particular, if `S` has a lifetime
parameter that is shorter than that of `T`), then a `TypedArena<S>` is
unrelated to `TypedArena<T>`.)
Concretely, consider code like this:
```rust
struct Node<'a> { sibling: Option<&'a Node<'a>> }
struct Context<'a> {
// because of this field, `Context<'a>` is invariant with respect to `'a`.
arena: &'a TypedArena<Node<'a>>,
...
}
fn new_ctxt<'a>(arena: &'a TypedArena<Node<'a>>) -> Context<'a> { ... }
fn use_ctxt<'a>(fcx: &'a Context<'a>) { ... }
let arena = TypedArena::new();
let ctxt = new_ctxt(&arena);
use_ctxt(&ctxt);
```
In these situations, if you try to introduce two bindings via two
distinct `let` statements, each is (with this commit) assigned a
distinct extent, and the region inference system cannot find a single
region to assign to the lifetime `'a` that works for both of the
bindings. So you get an error that `ctxt` does not live long enough;
but moving its binding up above that of `arena` just shifts the error
so now the compiler complains that `arena` does not live long enough.
SO: What to do? The easiest fix in this case is to ensure that the two
bindings *do* get assigned the same static extent, by stuffing both
bindings into the same let statement, like so:
```rust
let (arena, ctxt): (TypedArena, Context);
arena = TypedArena::new();
ctxt = new_ctxt(&arena);
use_ctxt(&ctxt);
```
Due to the new code rejections outlined above, this is a ...
[breaking-change]
In preparation for the I/O rejuvination of the standard library, this commit
renames the current `io` module to `old_io` in order to make room for the new
I/O modules. It is expected that the I/O RFCs will land incrementally over time
instead of all at once, and this provides a fresh clean path for new modules to
enter into as well as guaranteeing that all old infrastructure will remain in
place for some time.
As each `old_io` module is replaced it will be deprecated in-place for new
structures in `std::{io, fs, net}` (as appropriate).
This commit does *not* leave a reexport of `old_io as io` as the deprecation
lint does not currently warn on this form of use. This is quite a large breaking
change for all imports in existing code, but all functionality is retained
precisely as-is and path statements simply need to be renamed from `io` to
`old_io`.
[breaking-change]
I'm beginning to suspect it's impossible to avoid accidentally writing
`#[deriving]` at least once in every program, and it results in
non-intuitive error messages: "Foo doesn't have any method in scope
`clone`" despite there being a `#[deriv...(Clone)]` attribute!
Also, lots of documentation around the internet uses `#[deriving]` so
providing this guidance is very helpful (lots of people ask in #rust
about this 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.
I'm beginning to suspect it's impossible to avoid accidentally writing
`#[deriving]` at least once in every program, and it results in
non-intuitive error messages: "Foo doesn't have any method in scope
`clone`" despite there being a `#[deriv...(Clone)]` attribute!
Also, lots of documentation around the internet uses `#[deriving]` so
providing this guidance is very helpful (lots of people ask in #rust
about this error).
Fixes#21166.
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.
Grammar changes:
* allow 'for _ in 1..i {}' (fixes#20241)
* allow 'for _ in 1.. {}' as infinite loop
* prevent use of range notation in contexts where only operators of high
precedence are expected (fixes#20811)
Parser code cleanup:
* remove RESTRICTION_NO_DOTS
* make AS_PREC const and follow naming convention
* make min_prec inclusive
This is a bit of cleanup work to clean out some old deprecated flags and deprecated lint names from the compiler (they've been deprecated for quite awhile now).
This also notably puts `--pretty` behind the `-Z unstable-options` flag (where it was supposed to be previously).
This is little clean code of this PR: #21366. I patched the same thing as aochagavia but too slowly obviously. This is a merge of our two codes, more "rust-like".
This commit is an implementation of [RFC 565][rfc] which is a stabilization of
the `std::fmt` module and the implementations of various formatting traits.
Specifically, the following changes were performed:
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0565-show-string-guidelines.md
* The `Show` trait is now deprecated, it was renamed to `Debug`
* The `String` trait is now deprecated, it was renamed to `Display`
* Many `Debug` and `Display` implementations were audited in accordance with the
RFC and audited implementations now have the `#[stable]` attribute
* Integers and floats no longer print a suffix
* Smart pointers no longer print details that they are a smart pointer
* Paths with `Debug` are now quoted and escape characters
* The `unwrap` methods on `Result` now require `Display` instead of `Debug`
* The `Error` trait no longer has a `detail` method and now requires that
`Display` must be implemented. With the loss of `String`, this has moved into
libcore.
* `impl<E: Error> FromError<E> for Box<Error>` now exists
* `derive(Show)` has been renamed to `derive(Debug)`. This is not currently
warned about due to warnings being emitted on stage1+
While backwards compatibility is attempted to be maintained with a blanket
implementation of `Display` for the old `String` trait (and the same for
`Show`/`Debug`) this is still a breaking change due to primitives no longer
implementing `String` as well as modifications such as `unwrap` and the `Error`
trait. Most code is fairly straightforward to update with a rename or tweaks of
method calls.
[breaking-change]
Closes#21436
These two attributes are used to change the entry point into a Rust program, but
for now they're being put behind feature gates until we have a chance to think
about them a little more. The #[start] attribute specifically may have its
signature changed.
This is a breaking change to due the usage of these attributes generating errors
by default now. If your crate is using these attributes, add this to your crate
root:
#![feature(start)] // if you're using the #[start] attribute
#![feature(main)] // if you're using the #[main] attribute
cc #20064