Port erased cleanup
Just realised that the changes I made in #65965 were removed after the move of all error codes so here it is. I made them into separate commits to make the history look better this time.
r? @Mark-Simulacrum
Push `ast::{ItemKind, ImplItemKind}::OpaqueTy` hack down into lowering
We currently have a hack in the form of `ast::{ItemKind, ImplItemKind}::OpaqueTy` which is constructed literally when you write `type Alias = impl Trait;` but not e.g. `type Alias = Vec<impl Trait>;`. Per https://github.com/rust-lang/rfcs/pull/2515, this needs to change to allow `impl Trait` in nested positions. This PR achieves this change for the syntactic aspect but not the semantic one, which will require changes in lowering and def collection. In the interim, `TyKind::opaque_top_hack` is introduced to avoid knock-on changes in lowering, collection, and resolve. These hacks can then be removed and fixed one by one until the desired semantics are supported.
r? @varkor
Rollup of 12 pull requests
Successful merges:
- #65557 (rename Error::iter_chain() and remove Error::iter_sources())
- #66013 (Avoid hashing the key twice in `get_query()`.)
- #66306 (Remove cannot mutate statics in initializer of another static error)
- #66338 (Update mdbook.)
- #66388 (Do not ICE on recovery from unmet associated type bound obligation)
- #66390 (Fix ICE when trying to suggest `Type<>` instead of `Type()`)
- #66391 (Do not ICE in `if` without `else` in `async fn`)
- #66398 (Remove some stack frames from `.async` calls)
- #66410 (miri: helper methods for max values of machine's usize/isize)
- #66418 (Link to tracking issue in HIR const-check error code description)
- #66419 (Don't warn labels beginning with `_` on unused_labels lint)
- #66428 (Cleanup unused function)
Failed merges:
r? @ghost
Link to tracking issue in HIR const-check error code description
This is a follow up to #66170 that addresses [this comment](https://github.com/rust-lang/rust/pull/66170#discussion_r344021268).
As an aside, the only other error code whose description uses the phrase "tracking issue" is `E0202`. We may want to come up with standards around this, especially since error codes are now centralized and easier to keep track of (thanks @GuillaumeGomez).
r? @estebank (since they +1'ed the comment)
Remove some stack frames from `.async` calls
The `Context` argument is currently smuggled through TLS for
async-generated futures. The current infrastructure is closure-based,
and results in an extra 6 stack frames when .awaiting an async-generated
future!
```
12: foo::async_b::{{closure}}
at src/main.rs:10
13: <std::future::GenFuture<T> as core::future::future::Future>::poll::{{closure}}
at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/future.rs:43
14: std::future::set_task_context
at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/future.rs:79
15: <std::future::GenFuture<T> as core::future::future::Future>::poll
at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/future.rs:43
16: std::future::poll_with_tls_context::{{closure}}
at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/future.rs:121
17: std::future::get_task_context
at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/future.rs:111
18: std::future::poll_with_tls_context
at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/future.rs:121
19: foo::async_a::{{closure}}
at src/main.rs:6
```
While the long (medium?) term solution is to remove the use of TLS
entirely, we can improve things a bit in the meantime. In particular,
this commit does 2 things:
1. `get_task_context` has been inlined into `poll_with_tls_context`,
removing 2 frames (16 and 17 above).
2. `set_task_context` now returns a guard type that resets the TLS
rather than taking a closure, removing 2 frames (13 and 14 above).
We can also remove frame 18 by removing `poll_with_tls_context` in favor
of a `get_task_context` function which returns a guard, but that
requires adjusting the code generated for .await, so I've left that off
for now.
Fix ICE when trying to suggest `Type<>` instead of `Type()`
Fixes#66286, but the output has no span:
```
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
error: aborting due to previous error
For more information about this error, try `rustc --explain E0214`.
```
Update mdbook.
This brings in some important updates to fix some rendering issues in the books. In particular fixing hidden lines in code blocks, and some escaping issues. More details at https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md
This also requires updating mdbook-linkcheck.
Remove cannot mutate statics in initializer of another static error
r? @oli-obk
This is just a refactoring. As the removed code itself said, it only a heuristic catching a few cases early instead of leaving it all to const eval. It's easy to work around the static check and then run into the miri-engine check.
Avoid hashing the key twice in `get_query()`.
For a single-threaded parallel compiler, this reduces instruction counts
across several benchmarks, by up to 2.8%.
The commit also adds documentation about `Sharded`'s use of `FxHasher`.
r? @Zoxc
rename Error::iter_chain() and remove Error::iter_sources()
~~Rename~~
* ~~Error::iter_chain() -> Error::chained()~~
* ~~Error::iter_sources() -> Error::ancestors()~~
* ~~ErrorIter -> Chained and Ancestors~~
according to
https://github.com/rust-lang/rust/issues/58520#issuecomment-527704110
Tracker:
https://github.com/rust-lang/rust/issues/58520
Edit:
Rename
* Error::iter_chain() -> Error::chained()
* ErrorIter -> Chain
So, it seems, that even Path::ancestors() includes itself. So, to avoid confusion and simplify it more, I reduced PR #65557 to only have `chained` and `Chain`.
Rationale:
1. Such iterators are helpful. They should better be stabilized sooner than later.
1. self should be included. It is easy to .skip(1) it. Not including self is harmful because it is harder to add self to the iterator than to remove it.
1. The chosen name should be telling and reflect the fact that self is included. `.chained()` was chosen in honor of error-chain and because the iterator iterates over the chain of errors that is somehow included in self.
1. The resulting iterator is named `Chain` because the `error::Chain` is what we want to have.
Make the semantics of Vec::truncate(N) consistent with slices.
This commit simplifies the implementation of `Vec::truncate(N)` and
makes its semantics identical to dropping the `[vec.len() - N..]`
sub-slice tail of the vector, which is the same behavior as dropping a
vector containing the same sub-slice.
This changes two unspecified aspects of `Vec::truncate` behavior:
* the drop order, from back-to-front to front-to-back,
* the behavior of `Vec::truncate` on panics: if dropping one element of
the tail panics, currently, `Vec::truncate` panics, but with this PR all other
elements are still dropped, and if dropping a second element of the tail
panics, with this PR, the program aborts.
Programs can trivially observe both changes. For example
([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7bef575b83b06e82b3e3529e4edbcac7)):
```rust
fn main() {
struct Bomb(usize);
impl Drop for Bomb {
fn drop(&mut self) {
panic!(format!("{}", self.0));
}
}
let mut v = vec![Bomb(0), Bomb(1)];
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
v.truncate(0);
}));
assert_eq!(v.len(), 1);
std::mem::forget(v);
}
```
panics printing `1` today and succeeds. With this change, it panics
printing `0` first (due to the drop order change), and then aborts
with a double-panic printing `1`, just like dropping the
`[Bomb(0), Bomb(1)]` slice does, or dropping
`vec![Bomb(0), Bomb(1)]` does.
This needs to go through a crater run.
r? @SimonSapin
Move error codes
Works towards #66210.
r? @Centril
Oh btw, for the ones interested, I used this python script to get all error codes content sorted into one final file:
<details>
```python
from os import listdir
from os.path import isdir, isfile, join
def get_error_codes(error_codes, f_path):
with open(f_path) as f:
short_mode = False
lines = f.read().split("\n")
i = 0
while i < len(lines):
line = lines[i]
if not short_mode and line.startswith("E0") and line.endswith(": r##\""):
error = line
error += "\n"
i += 1
while i < len(lines):
line = lines[i]
error += line
if line.endswith("\"##,"):
break
error += "\n"
i += 1
error_codes["long"].append(error)
elif line == ';':
short_mode = True
elif short_mode is True and len(line) > 0 and line != "}":
error_codes["short"].append(line)
while i + 1 < len(lines):
line = lines[i + 1].strip()
if not line.startswith("//"):
break
parts = line.split("//")
if len(parts) < 2:
break
if parts[1].strip().startswith("E0"):
break
error_codes["short"][-1] += "\n"
error_codes["short"][-1] += lines[i + 1]
i += 1
i += 1
def loop_dirs(error_codes, cur_dir):
for entry in listdir(cur_dir):
f = join(cur_dir, entry)
if isfile(f) and entry == "error_codes.rs":
get_error_codes(error_codes, f)
elif isdir(f) and not entry.startswith("librustc_error_codes"):
loop_dirs(error_codes, f)
def get_error_code(err):
x = err.split(",")
if len(x) < 2:
return err
x = x[0]
if x.strip().startswith("//"):
x = x.split("//")[1].strip()
return x.strip()
def write_into_file(error_codes, f_path):
with open(f_path, "w") as f:
f.write("// Error messages for EXXXX errors. Each message should start and end with a\n")
f.write("// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and\n")
f.write("// use `gq` to wrap paragraphs. Use `:set tw=0` to disable.\n\n")
f.write("syntax::register_diagnostics! {\n\n")
error_codes["long"].sort()
for i in error_codes["long"]:
f.write(i)
f.write("\n\n")
f.write(";\n")
error_codes["short"] = sorted(error_codes["short"], key=lambda err: get_error_code(err))
for i in error_codes["short"]:
f.write(i)
f.write("\n")
f.write("}\n")
error_codes = {
"long": [],
"short": []
}
loop_dirs(error_codes, "src")
write_into_file(error_codes, "src/librustc_error_codes/src/error_codes.rs")
```
</details>
And to move the error codes into their own files:
<details>
```python
import os
try:
os.mkdir("src/librustc_error_codes/error_codes")
except OSError:
print("Seems like folder already exist, moving on!")
data = ''
with open("src/librustc_error_codes/error_codes.rs") as f:
x = f.read().split('\n')
i = 0
short_part = False
while i < len(x):
line = x[i]
if short_part is False and line.startswith('E0') and line.endswith(': r##"'):
err_code = line.split(':')[0]
i += 1
content = ''
while i < len(x):
if x[i] == '"##,':
break
content += x[i]
content += '\n'
i += 1
f_path = "src/librustc_error_codes/error_codes/{}.md".format(err_code)
with open(f_path, "w") as ff:
ff.write(content)
data += '{}: include_str!("./error_codes/{}.md"),'.format(err_code, err_code)
elif short_part is False and line == ';':
short_part is True
data += ';\n'
else:
data += line
data += '\n'
i += 1
with open("src/librustc_error_codes/error_codes.rs", "w") as f:
f.write(data)
```
</details>