mirror of
https://git.proxmox.com/git/rustc
synced 2026-01-26 04:25:31 +00:00
New upstream version 1.56.0+dfsg1
This commit is contained in:
parent
94222f6423
commit
dc3f568640
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1966,6 +1966,10 @@ dependencies = [
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lld-wrapper"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.1"
|
||||
|
||||
@ -35,6 +35,7 @@ members = [
|
||||
"src/tools/expand-yaml-anchors",
|
||||
"src/tools/jsondocck",
|
||||
"src/tools/html-checker",
|
||||
"src/tools/lld-wrapper",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
||||
188
RELEASES.md
188
RELEASES.md
@ -1,3 +1,185 @@
|
||||
Version 1.56.0 (2021-10-21)
|
||||
========================
|
||||
|
||||
Language
|
||||
--------
|
||||
|
||||
- [The 2021 Edition is now stable.][rust#88100]
|
||||
See [the edition guide][rust-2021-edition-guide] for more details.
|
||||
- [The pattern in `binding @ pattern` can now also introduce new bindings.][rust#85305]
|
||||
- [Union field access is permitted in `const fn`.][rust#85769]
|
||||
|
||||
[rust-2021-edition-guide]: https://doc.rust-lang.org/nightly/edition-guide/rust-2021/index.html
|
||||
|
||||
Compiler
|
||||
--------
|
||||
|
||||
- [Upgrade to LLVM 13.][rust#87570]
|
||||
- [Support memory, address, and thread sanitizers on aarch64-unknown-freebsd.][rust#88023]
|
||||
- [Allow specifying a deployment target version for all iOS targets][rust#87699]
|
||||
- [Warnings can be forced on with `--force-warn`.][rust#87472]
|
||||
This feature is primarily intended for usage by `cargo fix`, rather than end users.
|
||||
- [Promote `aarch64-apple-ios-sim` to Tier 2\*.][rust#87760]
|
||||
- [Add `powerpc-unknown-freebsd` at Tier 3\*.][rust#87370]
|
||||
- [Add `riscv32imc-esp-espidf` at Tier 3\*.][rust#87666]
|
||||
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
- [Allow writing of incomplete UTF-8 sequences via stdout/stderr on Windows.][rust#83342]
|
||||
The Windows console still requires valid Unicode, but this change allows
|
||||
splitting a UTF-8 character across multiple write calls. This allows, for
|
||||
instance, programs that just read and write data buffers (e.g. copying a file
|
||||
to stdout) without regard for Unicode or character boundaries.
|
||||
- [Prefer `AtomicU{64,128}` over Mutex for Instant backsliding protection.][rust#83093]
|
||||
For this use case, atomics scale much better under contention.
|
||||
- [Implement `Extend<(A, B)>` for `(Extend<A>, Extend<B>)`][rust#85835]
|
||||
- [impl Default, Copy, Clone for std::io::Sink and std::io::Empty][rust#86744]
|
||||
- [`impl From<[(K, V); N]>` for all collections.][rust#84111]
|
||||
- [Remove `P: Unpin` bound on impl Future for Pin.][rust#81363]
|
||||
- [Treat invalid environment variable names as non-existent.][rust#86183]
|
||||
Previously, the environment functions would panic if given a variable name
|
||||
with an internal null character or equal sign (`=`). Now, these functions will
|
||||
just treat such names as non-existent variables, since the OS cannot represent
|
||||
the existence of a variable with such a name.
|
||||
|
||||
Stabilised APIs
|
||||
---------------
|
||||
|
||||
- [`std::os::unix::fs::chroot`]
|
||||
- [`UnsafeCell::raw_get`]
|
||||
- [`BufWriter::into_parts`]
|
||||
- [`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]
|
||||
These APIs were previously stable in `std`, but are now also available in `core`.
|
||||
- [`Vec::shrink_to`]
|
||||
- [`String::shrink_to`]
|
||||
- [`OsString::shrink_to`]
|
||||
- [`PathBuf::shrink_to`]
|
||||
- [`BinaryHeap::shrink_to`]
|
||||
- [`VecDeque::shrink_to`]
|
||||
- [`HashMap::shrink_to`]
|
||||
- [`HashSet::shrink_to`]
|
||||
|
||||
These APIs are now usable in const contexts:
|
||||
|
||||
- [`std::mem::transmute`]
|
||||
- [`[T]::first`][`slice::first`]
|
||||
- [`[T]::split_first`][`slice::split_first`]
|
||||
- [`[T]::last`][`slice::last`]
|
||||
- [`[T]::split_last`][`slice::split_last`]
|
||||
|
||||
Cargo
|
||||
-----
|
||||
|
||||
- [Cargo supports specifying a minimum supported Rust version in Cargo.toml.][`rust-version`]
|
||||
This has no effect at present on dependency version selection.
|
||||
We encourage crates to specify their minimum supported Rust version, and we encourage CI systems
|
||||
that support Rust code to include a crate's specified minimum version in the text matrix for that
|
||||
crate by default.
|
||||
|
||||
Compatibility notes
|
||||
-------------------
|
||||
|
||||
- [Update to new argument parsing rules on Windows.][rust#87580]
|
||||
This adjusts Rust's standard library to match the behavior of the standard
|
||||
libraries for C/C++. The rules have changed slightly over time, and this PR
|
||||
brings us to the latest set of rules (changed in 2008).
|
||||
- [Disallow the aapcs calling convention on aarch64][rust#88399]
|
||||
This was already not supported by LLVM; this change surfaces this lack of
|
||||
support with a better error message.
|
||||
- [Make `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` warn by default][rust#87385]
|
||||
- [Warn when an escaped newline skips multiple lines.][rust#87671]
|
||||
- [Calls to `libc::getpid` / `std::process::id` from `Command::pre_exec`
|
||||
may return different values on glibc <= 2.24.][rust#81825]
|
||||
Rust now invokes the `clone3` system call directly, when available, to use new functionality
|
||||
available via that system call. Older versions of glibc cache the result of `getpid`, and only
|
||||
update that cache when calling glibc's clone/fork functions, so a direct system call bypasses
|
||||
that cache update. glibc 2.25 and newer no longer cache `getpid` for exactly this reason.
|
||||
|
||||
Internal changes
|
||||
----------------
|
||||
These changes provide no direct user facing benefits, but represent significant
|
||||
improvements to the internals and overall performance of rustc
|
||||
and related tools.
|
||||
|
||||
- [LLVM is compiled with PGO in published x86_64-unknown-linux-gnu artifacts.][rust#88069]
|
||||
This improves the performance of most Rust builds.
|
||||
- [Unify representation of macros in internal data structures.][rust#88019]
|
||||
This change fixes a host of bugs with the handling of macros by the compiler,
|
||||
as well as rustdoc.
|
||||
|
||||
[`std::os::unix::fs::chroot`]: https://doc.rust-lang.org/stable/std/os/unix/fs/fn.chroot.html
|
||||
[`Iterator::intersperse`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.intersperse
|
||||
[`Iterator::intersperse_with`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.intersperse
|
||||
[`UnsafeCell::raw_get`]: https://doc.rust-lang.org/stable/std/cell/struct.UnsafeCell.html#method.raw_get
|
||||
[`BufWriter::into_parts`]: https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_parts
|
||||
[`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]: https://github.com/rust-lang/rust/pull/84662
|
||||
[`Vec::shrink_to`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.shrink_to
|
||||
[`String::shrink_to`]: https://doc.rust-lang.org/stable/std/string/struct.String.html#method.shrink_to
|
||||
[`OsString::shrink_to`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.shrink_to
|
||||
[`PathBuf::shrink_to`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.shrink_to
|
||||
[`BinaryHeap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html#method.shrink_to
|
||||
[`VecDeque::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.shrink_to
|
||||
[`HashMap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.shrink_to
|
||||
[`HashSet::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_set/struct.HashSet.html#method.shrink_to
|
||||
[`std::mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html
|
||||
[`slice::first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first
|
||||
[`slice::split_first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first
|
||||
[`slice::last`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last
|
||||
[`slice::split_last`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last
|
||||
[`rust-version`]: https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-rust-version-field
|
||||
[rust#87671]: https://github.com/rust-lang/rust/pull/87671
|
||||
[rust#86183]: https://github.com/rust-lang/rust/pull/86183
|
||||
[rust#87385]: https://github.com/rust-lang/rust/pull/87385
|
||||
[rust#88100]: https://github.com/rust-lang/rust/pull/88100
|
||||
[rust#86860]: https://github.com/rust-lang/rust/pull/86860
|
||||
[rust#84039]: https://github.com/rust-lang/rust/pull/84039
|
||||
[rust#86492]: https://github.com/rust-lang/rust/pull/86492
|
||||
[rust#88363]: https://github.com/rust-lang/rust/pull/88363
|
||||
[rust#85305]: https://github.com/rust-lang/rust/pull/85305
|
||||
[rust#87832]: https://github.com/rust-lang/rust/pull/87832
|
||||
[rust#88069]: https://github.com/rust-lang/rust/pull/88069
|
||||
[rust#87472]: https://github.com/rust-lang/rust/pull/87472
|
||||
[rust#87699]: https://github.com/rust-lang/rust/pull/87699
|
||||
[rust#87570]: https://github.com/rust-lang/rust/pull/87570
|
||||
[rust#88023]: https://github.com/rust-lang/rust/pull/88023
|
||||
[rust#87760]: https://github.com/rust-lang/rust/pull/87760
|
||||
[rust#87370]: https://github.com/rust-lang/rust/pull/87370
|
||||
[rust#87580]: https://github.com/rust-lang/rust/pull/87580
|
||||
[rust#83342]: https://github.com/rust-lang/rust/pull/83342
|
||||
[rust#83093]: https://github.com/rust-lang/rust/pull/83093
|
||||
[rust#88177]: https://github.com/rust-lang/rust/pull/88177
|
||||
[rust#88548]: https://github.com/rust-lang/rust/pull/88548
|
||||
[rust#88551]: https://github.com/rust-lang/rust/pull/88551
|
||||
[rust#88299]: https://github.com/rust-lang/rust/pull/88299
|
||||
[rust#88220]: https://github.com/rust-lang/rust/pull/88220
|
||||
[rust#85835]: https://github.com/rust-lang/rust/pull/85835
|
||||
[rust#86879]: https://github.com/rust-lang/rust/pull/86879
|
||||
[rust#86744]: https://github.com/rust-lang/rust/pull/86744
|
||||
[rust#84662]: https://github.com/rust-lang/rust/pull/84662
|
||||
[rust#86593]: https://github.com/rust-lang/rust/pull/86593
|
||||
[rust#81050]: https://github.com/rust-lang/rust/pull/81050
|
||||
[rust#81363]: https://github.com/rust-lang/rust/pull/81363
|
||||
[rust#84111]: https://github.com/rust-lang/rust/pull/84111
|
||||
[rust#85769]: https://github.com/rust-lang/rust/pull/85769#issuecomment-854363720
|
||||
[rust#88490]: https://github.com/rust-lang/rust/pull/88490
|
||||
[rust#88269]: https://github.com/rust-lang/rust/pull/88269
|
||||
[rust#84176]: https://github.com/rust-lang/rust/pull/84176
|
||||
[rust#88399]: https://github.com/rust-lang/rust/pull/88399
|
||||
[rust#88227]: https://github.com/rust-lang/rust/pull/88227
|
||||
[rust#88200]: https://github.com/rust-lang/rust/pull/88200
|
||||
[rust#82776]: https://github.com/rust-lang/rust/pull/82776
|
||||
[rust#88077]: https://github.com/rust-lang/rust/pull/88077
|
||||
[rust#87728]: https://github.com/rust-lang/rust/pull/87728
|
||||
[rust#87050]: https://github.com/rust-lang/rust/pull/87050
|
||||
[rust#87619]: https://github.com/rust-lang/rust/pull/87619
|
||||
[rust#81825]: https://github.com/rust-lang/rust/pull/81825#issuecomment-808406918
|
||||
[rust#88019]: https://github.com/rust-lang/rust/pull/88019
|
||||
[rust#87666]: https://github.com/rust-lang/rust/pull/87666
|
||||
|
||||
Version 1.55.0 (2021-09-09)
|
||||
============================
|
||||
|
||||
@ -4985,7 +5167,7 @@ Libraries
|
||||
- [Upgrade to Unicode 10.0.0][42999]
|
||||
- [Reimplemented `{f32, f64}::{min, max}` in Rust instead of using CMath.][42430]
|
||||
- [Skip the main thread's manual stack guard on Linux][43072]
|
||||
- [Iterator::nth for `ops::{Range, RangeFrom}` is now done in O(1) time][43077]
|
||||
- [Iterator::nth for `ops::{Range, RangeFrom}` is now done in *O*(1) time][43077]
|
||||
- [`#[repr(align(N))]` attribute max number is now 2^31 - 1.][43097] This was
|
||||
previously 2^15.
|
||||
- [`{OsStr, Path}::Display` now avoids allocations where possible][42613]
|
||||
@ -8288,7 +8470,7 @@ Libraries
|
||||
algorithm][s].
|
||||
* [`std::io::copy` allows `?Sized` arguments][cc].
|
||||
* The `Windows`, `Chunks`, and `ChunksMut` iterators over slices all
|
||||
[override `count`, `nth` and `last` with an O(1)
|
||||
[override `count`, `nth` and `last` with an *O*(1)
|
||||
implementation][it].
|
||||
* [`Default` is implemented for arrays up to `[T; 32]`][d].
|
||||
* [`IntoRawFd` has been added to the Unix-specific prelude,
|
||||
@ -8810,7 +8992,7 @@ Libraries
|
||||
* The `Default` implementation for `Arc` [no longer requires `Sync +
|
||||
Send`][arc].
|
||||
* [The `Iterator` methods `count`, `nth`, and `last` have been
|
||||
overridden for slices to have O(1) performance instead of O(n)][si].
|
||||
overridden for slices to have *O*(1) performance instead of *O*(*n*)][si].
|
||||
* Incorrect handling of paths on Windows has been improved in both the
|
||||
compiler and the standard library.
|
||||
* [`AtomicPtr` gained a `Default` implementation][ap].
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
|
||||
use rustc_ast::{PatKind, RangeEnd};
|
||||
use rustc_ast::{PatKind, RangeEnd, VariantData};
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_feature::{Features, GateIssue};
|
||||
use rustc_session::parse::feature_err_issue;
|
||||
use rustc_session::parse::{feature_err, feature_err_issue};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -218,6 +218,46 @@ impl<'a> PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
|
||||
let has_fields = variants.iter().any(|variant| match variant.data {
|
||||
VariantData::Tuple(..) | VariantData::Struct(..) => true,
|
||||
VariantData::Unit(..) => false,
|
||||
});
|
||||
|
||||
let discriminant_spans = variants
|
||||
.iter()
|
||||
.filter(|variant| match variant.data {
|
||||
VariantData::Tuple(..) | VariantData::Struct(..) => false,
|
||||
VariantData::Unit(..) => true,
|
||||
})
|
||||
.filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !discriminant_spans.is_empty() && has_fields {
|
||||
let mut err = feature_err(
|
||||
&self.sess.parse_sess,
|
||||
sym::arbitrary_enum_discriminant,
|
||||
discriminant_spans.clone(),
|
||||
"custom discriminant values are not allowed in enums with tuple or struct variants",
|
||||
);
|
||||
for sp in discriminant_spans {
|
||||
err.span_label(sp, "disallowed custom discriminant");
|
||||
}
|
||||
for variant in variants.iter() {
|
||||
match &variant.data {
|
||||
VariantData::Struct(..) => {
|
||||
err.span_label(variant.span, "struct variant defined here");
|
||||
}
|
||||
VariantData::Tuple(..) => {
|
||||
err.span_label(variant.span, "tuple variant defined here");
|
||||
}
|
||||
VariantData::Unit(..) => {}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_gat(&self, generics: &ast::Generics, span: Span) {
|
||||
if !generics.params.is_empty() {
|
||||
gate_feature_post!(
|
||||
@ -362,6 +402,26 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
|
||||
for variant in variants {
|
||||
match (&variant.data, &variant.disr_expr) {
|
||||
(ast::VariantData::Unit(..), _) => {}
|
||||
(_, Some(disr_expr)) => gate_feature_post!(
|
||||
&self,
|
||||
arbitrary_enum_discriminant,
|
||||
disr_expr.value.span,
|
||||
"discriminants on non-unit variants are experimental"
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let has_feature = self.features.arbitrary_enum_discriminant;
|
||||
if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
|
||||
self.maybe_report_invalid_custom_discriminants(&variants);
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemKind::Impl(box ast::ImplKind {
|
||||
polarity, defaultness, ref of_trait, ..
|
||||
}) => {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
|
||||
use crate::panic::use_panic_2021;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_expand::base::*;
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
@ -28,7 +28,7 @@ pub fn expand_assert<'cx>(
|
||||
let sp = cx.with_call_site_ctxt(span);
|
||||
|
||||
let panic_call = if let Some(tokens) = custom_message {
|
||||
let path = if span.rust_2021() {
|
||||
let path = if use_panic_2021(span) {
|
||||
// On edition 2021, we always call `$crate::panic::panic_2021!()`.
|
||||
Path {
|
||||
span: sp,
|
||||
|
||||
@ -2,6 +2,7 @@ use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||
use rustc_ast::*;
|
||||
use rustc_expand::base::*;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -19,7 +20,7 @@ pub fn expand_panic<'cx>(
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> Box<dyn MacResult + 'cx> {
|
||||
let panic = if sp.rust_2021() { sym::panic_2021 } else { sym::panic_2015 };
|
||||
let panic = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 };
|
||||
|
||||
let sp = cx.with_call_site_ctxt(sp);
|
||||
|
||||
@ -46,3 +47,19 @@ pub fn expand_panic<'cx>(
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn use_panic_2021(mut span: Span) -> bool {
|
||||
// To determine the editon, we check the first span up the expansion
|
||||
// stack that does not have #[allow_internal_unstable(edition_panic)].
|
||||
// (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
|
||||
loop {
|
||||
let expn = span.ctxt().outer_expn_data();
|
||||
if let Some(features) = expn.allow_internal_unstable {
|
||||
if features.iter().any(|&f| f == sym::edition_panic) {
|
||||
span = expn.call_site;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break expn.edition >= Edition::Edition2021;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ pub(crate) fn get_vtable<'tcx>(
|
||||
ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
) -> Value {
|
||||
let alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
|
||||
let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref));
|
||||
let data_id =
|
||||
data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
|
||||
@ -72,7 +72,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
|
||||
return val;
|
||||
}
|
||||
|
||||
let vtable_alloc_id = tcx.vtable_allocation(ty, trait_ref);
|
||||
let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
|
||||
let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
|
||||
let vtable_const = cx.const_data_from_alloc(vtable_allocation);
|
||||
let align = cx.data_layout().pointer_align.abi;
|
||||
|
||||
@ -3,6 +3,8 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0732
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
|
||||
enum Enum { // error!
|
||||
Unit = 1,
|
||||
Tuple() = 2,
|
||||
@ -18,6 +20,8 @@ is a well-defined way to extract a variant's discriminant from a value;
|
||||
for instance:
|
||||
|
||||
```
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
|
||||
#[repr(u8)]
|
||||
enum Enum {
|
||||
Unit = 3,
|
||||
|
||||
@ -289,13 +289,11 @@ declare_features! (
|
||||
(accepted, member_constraints, "1.54.0", Some(61997), None),
|
||||
/// Allows bindings in the subpattern of a binding pattern.
|
||||
/// For example, you can write `x @ Some(y)`.
|
||||
(accepted, bindings_after_at, "1.54.0", Some(65490), None),
|
||||
(accepted, bindings_after_at, "1.56.0", Some(65490), None),
|
||||
/// Allows calling `transmute` in const fn
|
||||
(accepted, const_fn_transmute, "1.56.0", Some(53605), None),
|
||||
/// Allows accessing fields of unions inside `const` functions.
|
||||
(accepted, const_fn_union, "1.56.0", Some(51909), None),
|
||||
/// Allows explicit discriminants on non-unit enum variants.
|
||||
(accepted, arbitrary_enum_discriminant, "1.56.0", Some(60553), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: accepted features
|
||||
|
||||
@ -468,6 +468,9 @@ declare_features! (
|
||||
/// Allows #[repr(transparent)] on unions (RFC 2645).
|
||||
(active, transparent_unions, "1.37.0", Some(60405), None),
|
||||
|
||||
/// Allows explicit discriminants on non-unit enum variants.
|
||||
(active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
|
||||
|
||||
/// Allows `async || body` closures.
|
||||
(active, async_closure, "1.37.0", Some(62290), None),
|
||||
|
||||
|
||||
@ -1006,6 +1006,13 @@ rustc_queries! {
|
||||
key.1, key.0 }
|
||||
}
|
||||
|
||||
query vtable_allocation(key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId {
|
||||
desc { |tcx| "vtable const allocation for <{} as {}>",
|
||||
key.0,
|
||||
key.1.map(|trait_ref| format!("{}", trait_ref)).unwrap_or("_".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
query codegen_fulfill_obligation(
|
||||
key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
|
||||
) -> Result<ImplSource<'tcx, ()>, ErrorReported> {
|
||||
|
||||
@ -10,7 +10,7 @@ use crate::middle;
|
||||
use crate::middle::cstore::EncodedMetadata;
|
||||
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
|
||||
use crate::middle::stability;
|
||||
use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar};
|
||||
use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
|
||||
use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
|
||||
use crate::thir::Thir;
|
||||
use crate::traits;
|
||||
@ -1062,9 +1062,6 @@ pub struct GlobalCtxt<'tcx> {
|
||||
layout_interner: ShardedHashMap<&'tcx Layout, ()>,
|
||||
|
||||
output_filenames: Arc<OutputFilenames>,
|
||||
|
||||
pub(super) vtables_cache:
|
||||
Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
@ -1212,7 +1209,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
const_stability_interner: Default::default(),
|
||||
alloc_map: Lock::new(interpret::AllocMap::new()),
|
||||
output_filenames: Arc::new(output_filenames),
|
||||
vtables_cache: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2046,6 +2046,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||
trait_impls_of: trait_def::trait_impls_of_provider,
|
||||
type_uninhabited_from: inhabitedness::type_uninhabited_from,
|
||||
const_param_default: consts::const_param_default,
|
||||
vtable_allocation: vtable::vtable_allocation_provider,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
@ -2177,6 +2177,7 @@ forward_display_to_print! {
|
||||
// because `for<'tcx>` isn't possible yet.
|
||||
ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>,
|
||||
ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
ty::Binder<'tcx, ty::ExistentialTraitRef<'tcx>>,
|
||||
ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
ty::Binder<'tcx, ty::FnSig<'tcx>>,
|
||||
ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
|
||||
|
||||
@ -43,85 +43,72 @@ pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0;
|
||||
pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1;
|
||||
pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2;
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Retrieves an allocation that represents the contents of a vtable.
|
||||
/// There's a cache within `TyCtxt` so it will be deduplicated.
|
||||
pub fn vtable_allocation(
|
||||
self,
|
||||
ty: Ty<'tcx>,
|
||||
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||
) -> AllocId {
|
||||
let tcx = self;
|
||||
let vtables_cache = tcx.vtables_cache.lock();
|
||||
if let Some(alloc_id) = vtables_cache.get(&(ty, poly_trait_ref)).cloned() {
|
||||
return alloc_id;
|
||||
}
|
||||
drop(vtables_cache);
|
||||
/// Retrieves an allocation that represents the contents of a vtable.
|
||||
/// Since this is a query, allocations are cached and not duplicated.
|
||||
pub(super) fn vtable_allocation_provider<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
|
||||
) -> AllocId {
|
||||
let (ty, poly_trait_ref) = key;
|
||||
|
||||
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
|
||||
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
|
||||
let trait_ref = tcx.erase_regions(trait_ref);
|
||||
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
|
||||
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
|
||||
let trait_ref = tcx.erase_regions(trait_ref);
|
||||
|
||||
tcx.vtable_entries(trait_ref)
|
||||
} else {
|
||||
COMMON_VTABLE_ENTRIES
|
||||
tcx.vtable_entries(trait_ref)
|
||||
} else {
|
||||
COMMON_VTABLE_ENTRIES
|
||||
};
|
||||
|
||||
let layout = tcx
|
||||
.layout_of(ty::ParamEnv::reveal_all().and(ty))
|
||||
.expect("failed to build vtable representation");
|
||||
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
|
||||
let size = layout.size.bytes();
|
||||
let align = layout.align.abi.bytes();
|
||||
|
||||
let ptr_size = tcx.data_layout.pointer_size;
|
||||
let ptr_align = tcx.data_layout.pointer_align.abi;
|
||||
|
||||
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
|
||||
let mut vtable = Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap();
|
||||
|
||||
// No need to do any alignment checks on the memory accesses below, because we know the
|
||||
// allocation is correctly aligned as we created it above. Also we're only offsetting by
|
||||
// multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
|
||||
|
||||
for (idx, entry) in vtable_entries.iter().enumerate() {
|
||||
let idx: u64 = u64::try_from(idx).unwrap();
|
||||
let scalar = match entry {
|
||||
VtblEntry::MetadataDropInPlace => {
|
||||
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
|
||||
let fn_alloc_id = tcx.create_fn_alloc(instance);
|
||||
let fn_ptr = Pointer::from(fn_alloc_id);
|
||||
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
|
||||
}
|
||||
VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
|
||||
VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
|
||||
VtblEntry::Vacant => continue,
|
||||
VtblEntry::Method(instance) => {
|
||||
// Prepare the fn ptr we write into the vtable.
|
||||
let instance = instance.polymorphize(tcx);
|
||||
let fn_alloc_id = tcx.create_fn_alloc(instance);
|
||||
let fn_ptr = Pointer::from(fn_alloc_id);
|
||||
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
|
||||
}
|
||||
VtblEntry::TraitVPtr(trait_ref) => {
|
||||
let super_trait_ref = trait_ref
|
||||
.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
|
||||
let supertrait_alloc_id = tcx.vtable_allocation((ty, Some(super_trait_ref)));
|
||||
let vptr = Pointer::from(supertrait_alloc_id);
|
||||
ScalarMaybeUninit::from_pointer(vptr, &tcx)
|
||||
}
|
||||
};
|
||||
|
||||
let layout = tcx
|
||||
.layout_of(ty::ParamEnv::reveal_all().and(ty))
|
||||
vtable
|
||||
.write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar)
|
||||
.expect("failed to build vtable representation");
|
||||
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
|
||||
let size = layout.size.bytes();
|
||||
let align = layout.align.abi.bytes();
|
||||
|
||||
let ptr_size = tcx.data_layout.pointer_size;
|
||||
let ptr_align = tcx.data_layout.pointer_align.abi;
|
||||
|
||||
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
|
||||
let mut vtable =
|
||||
Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap();
|
||||
|
||||
// No need to do any alignment checks on the memory accesses below, because we know the
|
||||
// allocation is correctly aligned as we created it above. Also we're only offsetting by
|
||||
// multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
|
||||
|
||||
for (idx, entry) in vtable_entries.iter().enumerate() {
|
||||
let idx: u64 = u64::try_from(idx).unwrap();
|
||||
let scalar = match entry {
|
||||
VtblEntry::MetadataDropInPlace => {
|
||||
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
|
||||
let fn_alloc_id = tcx.create_fn_alloc(instance);
|
||||
let fn_ptr = Pointer::from(fn_alloc_id);
|
||||
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
|
||||
}
|
||||
VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
|
||||
VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
|
||||
VtblEntry::Vacant => continue,
|
||||
VtblEntry::Method(instance) => {
|
||||
// Prepare the fn ptr we write into the vtable.
|
||||
let instance = instance.polymorphize(tcx);
|
||||
let fn_alloc_id = tcx.create_fn_alloc(instance);
|
||||
let fn_ptr = Pointer::from(fn_alloc_id);
|
||||
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
|
||||
}
|
||||
VtblEntry::TraitVPtr(trait_ref) => {
|
||||
let super_trait_ref = trait_ref.map_bound(|trait_ref| {
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
});
|
||||
let supertrait_alloc_id = self.vtable_allocation(ty, Some(super_trait_ref));
|
||||
let vptr = Pointer::from(supertrait_alloc_id);
|
||||
ScalarMaybeUninit::from_pointer(vptr, &tcx)
|
||||
}
|
||||
};
|
||||
vtable
|
||||
.write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar)
|
||||
.expect("failed to build vtable representation");
|
||||
}
|
||||
|
||||
vtable.mutability = Mutability::Not;
|
||||
let alloc_id = tcx.create_memory_alloc(tcx.intern_const_alloc(vtable));
|
||||
let mut vtables_cache = self.vtables_cache.lock();
|
||||
vtables_cache.insert((ty, poly_trait_ref), alloc_id);
|
||||
alloc_id
|
||||
}
|
||||
|
||||
vtable.mutability = Mutability::Not;
|
||||
tcx.create_memory_alloc(tcx.intern_const_alloc(vtable))
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
ensure_monomorphic_enough(*self.tcx, ty)?;
|
||||
ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?;
|
||||
|
||||
let vtable_allocation = self.tcx.vtable_allocation(ty, poly_trait_ref);
|
||||
let vtable_allocation = self.tcx.vtable_allocation((ty, poly_trait_ref));
|
||||
|
||||
let vtable_ptr = self.memory.global_base_pointer(Pointer::from(vtable_allocation))?;
|
||||
|
||||
|
||||
@ -544,6 +544,12 @@ pub struct SimplifyBranchSame;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
// This optimization is disabled by default for now due to
|
||||
// soundness concerns; see issue #89485 and PR #89489.
|
||||
if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
|
||||
return;
|
||||
}
|
||||
|
||||
trace!("Running SimplifyBranchSame on {:?}", body.source);
|
||||
let finder = SimplifyBranchSameOptimizationFinder { body, tcx };
|
||||
let opts = finder.find();
|
||||
@ -706,12 +712,24 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
|
||||
let helper = |rhs: &Rvalue<'tcx>,
|
||||
place: &Place<'tcx>,
|
||||
variant_index: &VariantIdx,
|
||||
switch_value: u128,
|
||||
side_to_choose| {
|
||||
let place_type = place.ty(self.body, self.tcx).ty;
|
||||
let adt = match *place_type.kind() {
|
||||
ty::Adt(adt, _) if adt.is_enum() => adt,
|
||||
_ => return StatementEquality::NotEqual,
|
||||
};
|
||||
// We need to make sure that the switch value that targets the bb with
|
||||
// SetDiscriminant is the same as the variant discriminant.
|
||||
let variant_discr = adt.discriminant_for_variant(self.tcx, *variant_index).val;
|
||||
if variant_discr != switch_value {
|
||||
trace!(
|
||||
"NO: variant discriminant {} does not equal switch value {}",
|
||||
variant_discr,
|
||||
switch_value
|
||||
);
|
||||
return StatementEquality::NotEqual;
|
||||
}
|
||||
let variant_is_fieldless = adt.variants[*variant_index].fields.is_empty();
|
||||
if !variant_is_fieldless {
|
||||
trace!("NO: variant {:?} was not fieldless", variant_index);
|
||||
@ -740,20 +758,28 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
|
||||
(
|
||||
StatementKind::Assign(box (_, rhs)),
|
||||
StatementKind::SetDiscriminant { place, variant_index },
|
||||
)
|
||||
// we need to make sure that the switch value that targets the bb with SetDiscriminant (y), is the same as the variant index
|
||||
if Some(variant_index.index() as u128) == y_target_and_value.value => {
|
||||
) if y_target_and_value.value.is_some() => {
|
||||
// choose basic block of x, as that has the assign
|
||||
helper(rhs, place, variant_index, x_target_and_value.target)
|
||||
helper(
|
||||
rhs,
|
||||
place,
|
||||
variant_index,
|
||||
y_target_and_value.value.unwrap(),
|
||||
x_target_and_value.target,
|
||||
)
|
||||
}
|
||||
(
|
||||
StatementKind::SetDiscriminant { place, variant_index },
|
||||
StatementKind::Assign(box (_, rhs)),
|
||||
)
|
||||
// we need to make sure that the switch value that targets the bb with SetDiscriminant (x), is the same as the variant index
|
||||
if Some(variant_index.index() as u128) == x_target_and_value.value => {
|
||||
) if x_target_and_value.value.is_some() => {
|
||||
// choose basic block of y, as that has the assign
|
||||
helper(rhs, place, variant_index, y_target_and_value.target)
|
||||
helper(
|
||||
rhs,
|
||||
place,
|
||||
variant_index,
|
||||
x_target_and_value.value.unwrap(),
|
||||
y_target_and_value.target,
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
trace!("NO: statements `{:?}` and `{:?}` not considered equal", x, y);
|
||||
|
||||
@ -72,6 +72,17 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
|
||||
#[inline(always)]
|
||||
fn query_crate_is_local(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_span(&self, _: TyCtxt<'_>) -> Span {
|
||||
DUMMY_SP
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
|
||||
#[inline(always)]
|
||||
fn query_crate_is_local(&self) -> bool {
|
||||
|
||||
@ -558,6 +558,7 @@ symbols! {
|
||||
dyn_metadata,
|
||||
dyn_trait,
|
||||
edition_macro_pats,
|
||||
edition_panic,
|
||||
eh_catch_typeinfo,
|
||||
eh_personality,
|
||||
emit_enum,
|
||||
|
||||
@ -1391,7 +1391,7 @@ fn check_enum<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
if tcx.adt_def(def_id).repr.int.is_none() {
|
||||
if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
|
||||
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
|
||||
|
||||
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
|
||||
|
||||
@ -65,6 +65,7 @@ use std::iter;
|
||||
enum PlaceAncestryRelation {
|
||||
Ancestor,
|
||||
Descendant,
|
||||
SamePlace,
|
||||
Divergent,
|
||||
}
|
||||
|
||||
@ -565,7 +566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
for possible_ancestor in min_cap_list.iter_mut() {
|
||||
match determine_place_ancestry_relation(&place, &possible_ancestor.place) {
|
||||
// current place is descendant of possible_ancestor
|
||||
PlaceAncestryRelation::Descendant => {
|
||||
PlaceAncestryRelation::Descendant | PlaceAncestryRelation::SamePlace => {
|
||||
ancestor_found = true;
|
||||
let backup_path_expr_id = possible_ancestor.info.path_expr_id;
|
||||
|
||||
@ -2303,15 +2304,17 @@ fn determine_place_ancestry_relation(
|
||||
let projections_b = &place_b.projections;
|
||||
|
||||
let same_initial_projections =
|
||||
iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a == proj_b);
|
||||
iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a.kind == proj_b.kind);
|
||||
|
||||
if same_initial_projections {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
// First min(n, m) projections are the same
|
||||
// Select Ancestor/Descendant
|
||||
if projections_b.len() >= projections_a.len() {
|
||||
PlaceAncestryRelation::Ancestor
|
||||
} else {
|
||||
PlaceAncestryRelation::Descendant
|
||||
match projections_b.len().cmp(&projections_a.len()) {
|
||||
Ordering::Greater => PlaceAncestryRelation::Ancestor,
|
||||
Ordering::Equal => PlaceAncestryRelation::SamePlace,
|
||||
Ordering::Less => PlaceAncestryRelation::Descendant,
|
||||
}
|
||||
} else {
|
||||
PlaceAncestryRelation::Divergent
|
||||
|
||||
@ -776,29 +776,31 @@ fn infer_placeholder_type<'a>(
|
||||
// us to improve in typeck so we do that now.
|
||||
match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
|
||||
Some(mut err) => {
|
||||
// The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
|
||||
// We are typeck and have the real type, so remove that and suggest the actual type.
|
||||
err.suggestions.clear();
|
||||
if !ty.references_error() {
|
||||
// The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
|
||||
// We are typeck and have the real type, so remove that and suggest the actual type.
|
||||
err.suggestions.clear();
|
||||
|
||||
// Suggesting unnameable types won't help.
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
&format!("provide a type for the {item}", item = kind),
|
||||
format!("{}: {}", item_ident, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.span_note(
|
||||
tcx.hir().body(body_id).value.span,
|
||||
&format!("however, the inferred type `{}` cannot be named", ty.to_string()),
|
||||
);
|
||||
// Suggesting unnameable types won't help.
|
||||
let mut mk_nameable = MakeNameable::new(tcx);
|
||||
let ty = mk_nameable.fold_ty(ty);
|
||||
let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
|
||||
if let Some(sugg_ty) = sugg_ty {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
&format!("provide a type for the {item}", item = kind),
|
||||
format!("{}: {}", item_ident, sugg_ty),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.span_note(
|
||||
tcx.hir().body(body_id).value.span,
|
||||
&format!("however, the inferred type `{}` cannot be named", ty.to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
err.emit_unless(ty.references_error());
|
||||
err.emit();
|
||||
}
|
||||
None => {
|
||||
let mut diag = bad_placeholder_type(tcx, vec![span], kind);
|
||||
|
||||
@ -619,6 +619,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
|
||||
if let Some(hir::Guard::If(ref e)) = arm.guard {
|
||||
self.consume_expr(e)
|
||||
} else if let Some(hir::Guard::IfLet(_, ref e)) = arm.guard {
|
||||
self.consume_expr(e)
|
||||
}
|
||||
|
||||
self.consume_expr(&arm.body);
|
||||
|
||||
@ -1 +1 @@
|
||||
e6e620e1c7e7257babdfaed5c3bccbb654e72e83
|
||||
09c42c45858d5f3aedfa670698275303a3d19afa
|
||||
@ -4,7 +4,7 @@ use super::Peekable;
|
||||
///
|
||||
/// This `struct` is created by [`Iterator::intersperse`]. See its documentation
|
||||
/// for more information.
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Intersperse<I: Iterator>
|
||||
where
|
||||
@ -24,7 +24,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
impl<I> Iterator for Intersperse<I>
|
||||
where
|
||||
I: Iterator,
|
||||
@ -61,7 +61,7 @@ where
|
||||
///
|
||||
/// This `struct` is created by [`Iterator::intersperse_with`]. See its
|
||||
/// documentation for more information.
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
pub struct IntersperseWith<I, G>
|
||||
where
|
||||
I: Iterator,
|
||||
@ -71,7 +71,7 @@ where
|
||||
needs_sep: bool,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
impl<I, G> crate::fmt::Debug for IntersperseWith<I, G>
|
||||
where
|
||||
I: Iterator + crate::fmt::Debug,
|
||||
@ -87,7 +87,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
impl<I, G> crate::clone::Clone for IntersperseWith<I, G>
|
||||
where
|
||||
I: Iterator + crate::clone::Clone,
|
||||
@ -113,7 +113,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
impl<I, G> Iterator for IntersperseWith<I, G>
|
||||
where
|
||||
I: Iterator,
|
||||
|
||||
@ -42,7 +42,7 @@ pub use self::flatten::Flatten;
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
pub use self::copied::Copied;
|
||||
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
pub use self::intersperse::{Intersperse, IntersperseWith};
|
||||
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
|
||||
@ -414,7 +414,7 @@ pub use self::adapters::{
|
||||
Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan,
|
||||
Skip, SkipWhile, Take, TakeWhile, Zip,
|
||||
};
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
pub use self::adapters::{Intersperse, IntersperseWith};
|
||||
|
||||
pub(crate) use self::adapters::process_results;
|
||||
|
||||
@ -535,6 +535,8 @@ pub trait Iterator {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_intersperse)]
|
||||
///
|
||||
/// let mut a = [0, 1, 2].iter().intersperse(&100);
|
||||
/// assert_eq!(a.next(), Some(&0)); // The first element from `a`.
|
||||
/// assert_eq!(a.next(), Some(&100)); // The separator.
|
||||
@ -545,8 +547,9 @@ pub trait Iterator {
|
||||
/// ```
|
||||
///
|
||||
/// `intersperse` can be very useful to join an iterator's items using a common element:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_intersperse)]
|
||||
///
|
||||
/// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::<String>();
|
||||
/// assert_eq!(hello, "Hello World !");
|
||||
/// ```
|
||||
@ -554,7 +557,7 @@ pub trait Iterator {
|
||||
/// [`Clone`]: crate::clone::Clone
|
||||
/// [`intersperse_with`]: Iterator::intersperse_with
|
||||
#[inline]
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
@ -579,6 +582,8 @@ pub trait Iterator {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_intersperse)]
|
||||
///
|
||||
/// #[derive(PartialEq, Debug)]
|
||||
/// struct NotClone(usize);
|
||||
///
|
||||
@ -595,8 +600,9 @@ pub trait Iterator {
|
||||
///
|
||||
/// `intersperse_with` can be used in situations where the separator needs
|
||||
/// to be computed:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_intersperse)]
|
||||
///
|
||||
/// let src = ["Hello", "to", "all", "people", "!!"].iter().copied();
|
||||
///
|
||||
/// // The closure mutably borrows its context to generate an item.
|
||||
@ -609,7 +615,7 @@ pub trait Iterator {
|
||||
/// [`Clone`]: crate::clone::Clone
|
||||
/// [`intersperse`]: Iterator::intersperse
|
||||
#[inline]
|
||||
#[stable(feature = "iter_intersperse", since = "1.56.0")]
|
||||
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
|
||||
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
|
||||
where
|
||||
Self: Sized,
|
||||
|
||||
@ -210,6 +210,7 @@ pub macro assert_matches {
|
||||
#[macro_export]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "debug_assert_macro"]
|
||||
#[allow_internal_unstable(edition_panic)]
|
||||
macro_rules! debug_assert {
|
||||
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); })
|
||||
}
|
||||
|
||||
@ -11,5 +11,5 @@ mod wake;
|
||||
pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
|
||||
|
||||
mod ready;
|
||||
#[stable(feature = "ready_macro", since = "1.56.0")]
|
||||
#[unstable(feature = "ready_macro", issue = "70922")]
|
||||
pub use ready::ready;
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ready_macro)]
|
||||
///
|
||||
/// use std::task::{ready, Context, Poll};
|
||||
/// use std::future::{self, Future};
|
||||
/// use std::pin::Pin;
|
||||
@ -27,6 +29,7 @@
|
||||
/// The `ready!` call expands to:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(ready_macro)]
|
||||
/// # use std::task::{Context, Poll};
|
||||
/// # use std::future::{self, Future};
|
||||
/// # use std::pin::Pin;
|
||||
@ -45,7 +48,7 @@
|
||||
/// # Poll::Ready(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "ready_macro", since = "1.56.0")]
|
||||
#[unstable(feature = "ready_macro", issue = "70922")]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro ready($e:expr) {
|
||||
match $e {
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
#![feature(int_log)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_partition_in_place)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(iter_map_while)]
|
||||
|
||||
@ -166,6 +166,12 @@ impl Command {
|
||||
fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long
|
||||
}
|
||||
|
||||
// Bypassing libc for `clone3` can make further libc calls unsafe,
|
||||
// so we use it sparingly for now. See #89522 for details.
|
||||
// Some tools (e.g. sandboxing tools) may also expect `fork`
|
||||
// rather than `clone3`.
|
||||
let want_clone3 = self.get_create_pidfd();
|
||||
|
||||
// If we fail to create a pidfd for any reason, this will
|
||||
// stay as -1, which indicates an error.
|
||||
let mut pidfd: pid_t = -1;
|
||||
@ -173,7 +179,7 @@ impl Command {
|
||||
// Attempt to use the `clone3` syscall, which supports more arguments
|
||||
// (in particular, the ability to create a pidfd). If this fails,
|
||||
// we will fall through this block to a call to `fork()`
|
||||
if HAS_CLONE3.load(Ordering::Relaxed) {
|
||||
if want_clone3 && HAS_CLONE3.load(Ordering::Relaxed) {
|
||||
let mut flags = 0;
|
||||
if self.get_create_pidfd() {
|
||||
flags |= CLONE_PIDFD;
|
||||
@ -212,8 +218,8 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, the 'clone3' syscall does not exist
|
||||
// or we do not have permission to call it
|
||||
// Generally, we just call `fork`. If we get here after wanting `clone3`,
|
||||
// then the syscall does not exist or we do not have permission to call it.
|
||||
cvt(libc::fork()).map(|res| (res, pidfd))
|
||||
}
|
||||
|
||||
|
||||
@ -1137,14 +1137,14 @@ impl Step for Assemble {
|
||||
// for `-Z gcc-ld=lld`
|
||||
let gcc_ld_dir = libdir_bin.join("gcc-ld");
|
||||
t!(fs::create_dir(&gcc_ld_dir));
|
||||
builder.copy(
|
||||
&lld_install.join("bin").join(&src_exe),
|
||||
&gcc_ld_dir.join(exe("ld", target_compiler.host)),
|
||||
);
|
||||
builder.copy(
|
||||
&lld_install.join("bin").join(&src_exe),
|
||||
&gcc_ld_dir.join(exe("ld64", target_compiler.host)),
|
||||
);
|
||||
for flavor in ["ld", "ld64"] {
|
||||
let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper {
|
||||
compiler: build_compiler,
|
||||
target: target_compiler.host,
|
||||
flavor_feature: flavor,
|
||||
});
|
||||
builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(flavor, target_compiler.host)));
|
||||
}
|
||||
}
|
||||
|
||||
// Similarly, copy `llvm-dwp` into libdir for Split DWARF. Only copy it when the LLVM
|
||||
|
||||
@ -409,11 +409,14 @@ impl Step for Rustc {
|
||||
let rust_lld = exe("rust-lld", compiler.host);
|
||||
builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
|
||||
// for `-Z gcc-ld=lld`
|
||||
let gcc_lld_dir = dst_dir.join("gcc-ld");
|
||||
t!(fs::create_dir(&gcc_lld_dir));
|
||||
builder.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host)));
|
||||
builder
|
||||
.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld64", compiler.host)));
|
||||
let gcc_lld_src_dir = src_dir.join("gcc-ld");
|
||||
let gcc_lld_dst_dir = dst_dir.join("gcc-ld");
|
||||
t!(fs::create_dir(&gcc_lld_dst_dir));
|
||||
for flavor in ["ld", "ld64"] {
|
||||
let exe_name = exe(flavor, compiler.host);
|
||||
builder
|
||||
.copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy over llvm-dwp if it's there
|
||||
|
||||
@ -663,6 +663,38 @@ impl Step for Cargo {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct LldWrapper {
|
||||
pub compiler: Compiler,
|
||||
pub target: TargetSelection,
|
||||
pub flavor_feature: &'static str,
|
||||
}
|
||||
|
||||
impl Step for LldWrapper {
|
||||
type Output = PathBuf;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.never()
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
let src_exe = builder
|
||||
.ensure(ToolBuild {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: "lld-wrapper",
|
||||
mode: Mode::ToolStd,
|
||||
path: "src/tools/lld-wrapper",
|
||||
is_optional_tool: false,
|
||||
source_type: SourceType::InTree,
|
||||
extra_features: vec![self.flavor_feature.to_owned()],
|
||||
})
|
||||
.expect("expected to build -- essential tool");
|
||||
|
||||
src_exe
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tool_extended {
|
||||
(($sel:ident, $builder:ident),
|
||||
$($name:ident,
|
||||
|
||||
@ -1 +1 @@
|
||||
beta
|
||||
stable
|
||||
|
||||
@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
CT_USE_MIRROR=y
|
||||
CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
|
||||
|
||||
#
|
||||
# Extracting
|
||||
|
||||
@ -611,7 +611,7 @@ CT_ISL_V_0_20=y
|
||||
# CT_ISL_V_0_15 is not set
|
||||
# CT_ISL_NO_VERSIONS is not set
|
||||
CT_ISL_VERSION="0.20"
|
||||
CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
|
||||
CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
|
||||
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
|
||||
@ -22,7 +22,8 @@ exit 1
|
||||
mkdir build
|
||||
cd build
|
||||
cp ../arm-linux-gnueabi.config .config
|
||||
ct-ng oldconfig
|
||||
# FIXME ct-ng oldconfig is not working as intended.
|
||||
# ct-ng oldconfig
|
||||
hide_output ct-ng build
|
||||
cd ..
|
||||
rm -rf build
|
||||
|
||||
@ -14,6 +14,7 @@ CT_CONFIGURE_has_autoconf_2_65_or_newer=y
|
||||
CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
|
||||
CT_CONFIGURE_has_automake_1_15_or_newer=y
|
||||
CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
|
||||
CT_CONFIGURE_has_python_3_4_or_newer=y
|
||||
CT_CONFIGURE_has_bison_2_7_or_newer=y
|
||||
CT_CONFIGURE_has_python=y
|
||||
CT_CONFIGURE_has_git=y
|
||||
@ -132,12 +133,6 @@ CT_ARCH_ARM=y
|
||||
# CT_ARCH_XTENSA is not set
|
||||
CT_ARCH="arm"
|
||||
CT_ARCH_CHOICE_KSYM="ARM"
|
||||
# CT_ARCH_ALPHA_EV4 is not set
|
||||
# CT_ARCH_ALPHA_EV45 is not set
|
||||
# CT_ARCH_ALPHA_EV5 is not set
|
||||
# CT_ARCH_ALPHA_EV56 is not set
|
||||
# CT_ARCH_ALPHA_EV6 is not set
|
||||
# CT_ARCH_ALPHA_EV67 is not set
|
||||
CT_ARCH_CPU=""
|
||||
CT_ARCH_TUNE=""
|
||||
CT_ARCH_ARM_SHOW=y
|
||||
@ -372,8 +367,6 @@ CT_ALL_BINUTILS_CHOICES="BINUTILS"
|
||||
# C-library
|
||||
#
|
||||
CT_LIBC_GLIBC=y
|
||||
# CT_LIBC_NEWLIB is not set
|
||||
# CT_LIBC_NONE is not set
|
||||
# CT_LIBC_UCLIBC is not set
|
||||
CT_LIBC="glibc"
|
||||
CT_LIBC_CHOICE_KSYM="GLIBC"
|
||||
@ -390,6 +383,7 @@ CT_GLIBC_USE="GLIBC"
|
||||
CT_GLIBC_PKG_NAME="glibc"
|
||||
CT_GLIBC_SRC_RELEASE=y
|
||||
CT_GLIBC_PATCH_ORDER="global"
|
||||
# CT_GLIBC_V_2_29 is not set
|
||||
# CT_GLIBC_V_2_28 is not set
|
||||
# CT_GLIBC_V_2_27 is not set
|
||||
# CT_GLIBC_V_2_26 is not set
|
||||
@ -408,7 +402,6 @@ CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_GLIBC_2_29_or_older=y
|
||||
CT_GLIBC_older_than_2_29=y
|
||||
CT_GLIBC_REQUIRE_older_than_2_29=y
|
||||
CT_GLIBC_2_27_or_older=y
|
||||
CT_GLIBC_older_than_2_27=y
|
||||
CT_GLIBC_2_26_or_older=y
|
||||
@ -448,12 +441,6 @@ CT_GLIBC_FORCE_UNWIND=y
|
||||
CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
|
||||
# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
|
||||
CT_GLIBC_MIN_KERNEL="3.2.101"
|
||||
# CT_GLIBC_SSP_DEFAULT is not set
|
||||
# CT_GLIBC_SSP_NO is not set
|
||||
# CT_GLIBC_SSP_YES is not set
|
||||
# CT_GLIBC_SSP_ALL is not set
|
||||
# CT_GLIBC_SSP_STRONG is not set
|
||||
# CT_NEWLIB_USE_REDHAT is not set
|
||||
CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
|
||||
CT_LIBC_SUPPORT_THREADS_ANY=y
|
||||
CT_LIBC_SUPPORT_THREADS_NATIVE=y
|
||||
@ -625,7 +612,7 @@ CT_ISL_V_0_20=y
|
||||
# CT_ISL_V_0_15 is not set
|
||||
# CT_ISL_NO_VERSIONS is not set
|
||||
CT_ISL_VERSION="0.20"
|
||||
CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
|
||||
CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
|
||||
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
|
||||
@ -22,7 +22,8 @@ exit 1
|
||||
mkdir build
|
||||
cd build
|
||||
cp ../arm-linux-gnueabihf.config .config
|
||||
ct-ng oldconfig
|
||||
# FIXME ct-ng oldconfig is not working as intended.
|
||||
# ct-ng oldconfig
|
||||
hide_output ct-ng build
|
||||
cd ..
|
||||
rm -rf build
|
||||
|
||||
@ -17,8 +17,6 @@ CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
|
||||
CT_CONFIGURE_has_python_3_4_or_newer=y
|
||||
CT_CONFIGURE_has_bison_2_7_or_newer=y
|
||||
CT_CONFIGURE_has_python=y
|
||||
CT_CONFIGURE_has_dtc=y
|
||||
CT_CONFIGURE_has_svn=y
|
||||
CT_CONFIGURE_has_git=y
|
||||
CT_CONFIGURE_has_md5sum=y
|
||||
CT_CONFIGURE_has_sha1sum=y
|
||||
@ -612,7 +610,7 @@ CT_ISL_V_0_20=y
|
||||
# CT_ISL_V_0_15 is not set
|
||||
# CT_ISL_NO_VERSIONS is not set
|
||||
CT_ISL_VERSION="0.20"
|
||||
CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
|
||||
CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
|
||||
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
|
||||
@ -22,7 +22,8 @@ exit 1
|
||||
mkdir build
|
||||
cd build
|
||||
cp ../armv7-linux-gnueabihf.config .config
|
||||
ct-ng oldconfig
|
||||
# FIXME ct-ng oldconfig is not working as intended.
|
||||
# ct-ng oldconfig
|
||||
hide_output ct-ng build
|
||||
cd ..
|
||||
rm -rf build
|
||||
|
||||
@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
CT_USE_MIRROR=y
|
||||
CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
|
||||
|
||||
#
|
||||
# Extracting
|
||||
|
||||
@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
CT_USE_MIRROR=y
|
||||
CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
|
||||
|
||||
#
|
||||
# Extracting
|
||||
|
||||
@ -722,7 +722,7 @@ CT_ISL_V_0_20=y
|
||||
# CT_ISL_V_0_15 is not set
|
||||
# CT_ISL_NO_VERSIONS is not set
|
||||
CT_ISL_VERSION="0.20"
|
||||
CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
|
||||
CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
|
||||
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
|
||||
@ -37,7 +37,8 @@ CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
CT_USE_MIRROR=y
|
||||
CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
|
||||
|
||||
#
|
||||
# Extracting
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
# `arbitrary_enum_discriminant`
|
||||
|
||||
The tracking issue for this feature is: [#60553]
|
||||
|
||||
[#60553]: https://github.com/rust-lang/rust/issues/60553
|
||||
|
||||
------------------------
|
||||
|
||||
The `arbitrary_enum_discriminant` feature permits tuple-like and
|
||||
struct-like enum variants with `#[repr(<int-type>)]` to have explicit discriminants.
|
||||
|
||||
## Examples
|
||||
|
||||
```rust
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(u8)]
|
||||
enum Enum {
|
||||
Unit = 3,
|
||||
Tuple(u16) = 2,
|
||||
Struct {
|
||||
a: u8,
|
||||
b: u16,
|
||||
} = 1,
|
||||
}
|
||||
|
||||
impl Enum {
|
||||
fn tag(&self) -> u8 {
|
||||
unsafe { *(self as *const Self as *const u8) }
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(3, Enum::Unit.tag());
|
||||
assert_eq!(2, Enum::Tuple(5).tag());
|
||||
assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag());
|
||||
```
|
||||
@ -13,6 +13,7 @@
|
||||
#![feature(never_type)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(type_ascription)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![recursion_limit = "256"]
|
||||
#![warn(rustc::internal)]
|
||||
|
||||
|
||||
@ -86,13 +86,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
// the rexport defines the path that a user will actually see. Accordingly,
|
||||
// we add the rexport as an item here, and then skip over the original
|
||||
// definition in `visit_item()` below.
|
||||
//
|
||||
// We also skip `#[macro_export] macro_rules!` that have already been inserted,
|
||||
// it can happen if within the same module a `#[macro_export] macro_rules!`
|
||||
// is declared but also a reexport of itself producing two exports of the same
|
||||
// macro in the same module.
|
||||
let mut inserted = FxHashSet::default();
|
||||
for export in self.cx.tcx.module_exports(CRATE_DEF_ID).unwrap_or(&[]) {
|
||||
if let Res::Def(DefKind::Macro(_), def_id) = export.res {
|
||||
if let Some(local_def_id) = def_id.as_local() {
|
||||
if self.cx.tcx.has_attr(def_id, sym::macro_export) {
|
||||
let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
|
||||
let item = self.cx.tcx.hir().expect_item(hir_id);
|
||||
top_level_module.items.push((item, None));
|
||||
if inserted.insert(def_id) {
|
||||
let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
|
||||
let item = self.cx.tcx.hir().expect_item(hir_id);
|
||||
top_level_module.items.push((item, None));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
src/test/incremental/reorder_vtable.rs
Normal file
41
src/test/incremental/reorder_vtable.rs
Normal file
@ -0,0 +1,41 @@
|
||||
// revisions:rpass1 rpass2
|
||||
|
||||
// This test case makes sure re-order the methods in a vtable will
|
||||
// trigger recompilation of codegen units that instantiate it.
|
||||
//
|
||||
// See https://github.com/rust-lang/rust/issues/89598
|
||||
|
||||
trait Foo {
|
||||
#[cfg(rpass1)]
|
||||
fn method1(&self) -> u32;
|
||||
|
||||
fn method2(&self) -> u32;
|
||||
|
||||
#[cfg(rpass2)]
|
||||
fn method1(&self) -> u32;
|
||||
}
|
||||
|
||||
impl Foo for u32 {
|
||||
fn method1(&self) -> u32 { 17 }
|
||||
fn method2(&self) -> u32 { 42 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Before #89598 was fixed, the vtable allocation would be cached during
|
||||
// a MIR optimization pass and then the codegen pass for the main object
|
||||
// file would not register a dependency on it (because of the missing
|
||||
// dep-tracking).
|
||||
//
|
||||
// In the rpass2 session, the main object file would not be re-compiled,
|
||||
// thus the mod1::foo(x) call would pass in an outdated vtable, while the
|
||||
// mod1 object would expect the new, re-ordered vtable, resulting in a
|
||||
// call to the wrong method.
|
||||
let x: &dyn Foo = &0u32;
|
||||
assert_eq!(mod1::foo(x), 17);
|
||||
}
|
||||
|
||||
mod mod1 {
|
||||
pub(super) fn foo(x: &dyn super::Foo) -> u32 {
|
||||
x.method1()
|
||||
}
|
||||
}
|
||||
17
src/test/rustdoc-json/reexport/macro.rs
Normal file
17
src/test/rustdoc-json/reexport/macro.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// edition:2018
|
||||
|
||||
#![no_core]
|
||||
#![feature(no_core)]
|
||||
|
||||
// @count macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" 2
|
||||
|
||||
// @set repro_id = macro.json "$.index[*][?(@.name=='repro')].id"
|
||||
// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id
|
||||
#[macro_export]
|
||||
macro_rules! repro {
|
||||
() => {};
|
||||
}
|
||||
|
||||
// @set repro2_id = macro.json "$.index[*][?(@.inner.name=='repro2')].id"
|
||||
// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro2_id
|
||||
pub use crate::repro as repro2;
|
||||
14
src/test/rustdoc/issue-89852.rs
Normal file
14
src/test/rustdoc/issue-89852.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// edition:2018
|
||||
|
||||
#![no_core]
|
||||
#![feature(no_core)]
|
||||
|
||||
// @matches 'issue_89852/sidebar-items.js' '"repro"'
|
||||
// @!matches 'issue_89852/sidebar-items.js' '"repro".*"repro"'
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! repro {
|
||||
() => {};
|
||||
}
|
||||
|
||||
pub use crate::repro as repro2;
|
||||
24
src/test/ui/closures/2229_closure_analysis/issue-88118-2.rs
Normal file
24
src/test/ui/closures/2229_closure_analysis/issue-88118-2.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// edition:2021
|
||||
// run-pass
|
||||
#![feature(if_let_guard)]
|
||||
#[allow(unused_must_use)]
|
||||
#[allow(dead_code)]
|
||||
|
||||
fn print_error_count(registry: &Registry) {
|
||||
|x: &Registry| {
|
||||
match &x {
|
||||
Registry if let _ = registry.try_find_description() => { }
|
||||
//~^ WARNING: irrefutable `if let` guard pattern
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct Registry;
|
||||
impl Registry {
|
||||
pub fn try_find_description(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@ -0,0 +1,12 @@
|
||||
warning: irrefutable `if let` guard pattern
|
||||
--> $DIR/issue-88118-2.rs:10:29
|
||||
|
|
||||
LL | Registry if let _ = registry.try_find_description() => { }
|
||||
| ^
|
||||
|
|
||||
= note: `#[warn(irrefutable_let_patterns)]` on by default
|
||||
= note: this pattern will always match, so the guard is useless
|
||||
= help: consider removing the guard and adding a `let` inside the match arm
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
40
src/test/ui/closures/2229_closure_analysis/issue-89606.rs
Normal file
40
src/test/ui/closures/2229_closure_analysis/issue-89606.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Regression test for #89606. Used to ICE.
|
||||
//
|
||||
// check-pass
|
||||
// revisions: twenty_eighteen twenty_twentyone
|
||||
// [twenty_eighteen]compile-flags: --edition 2018
|
||||
// [twenty_twentyone]compile-flags: --edition 2021
|
||||
|
||||
struct S<'a>(Option<&'a mut i32>);
|
||||
|
||||
fn by_ref(s: &mut S<'_>) {
|
||||
(|| {
|
||||
let S(_o) = s;
|
||||
s.0 = None;
|
||||
})();
|
||||
}
|
||||
|
||||
fn by_value(s: S<'_>) {
|
||||
(|| {
|
||||
let S(ref _o) = s;
|
||||
let _g = s.0;
|
||||
})();
|
||||
}
|
||||
|
||||
struct V<'a>((Option<&'a mut i32>,));
|
||||
|
||||
fn nested(v: &mut V<'_>) {
|
||||
(|| {
|
||||
let V((_o,)) = v;
|
||||
v.0 = (None, );
|
||||
})();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut s = S(None);
|
||||
by_ref(&mut s);
|
||||
by_value(s);
|
||||
|
||||
let mut v = V((None, ));
|
||||
nested(&mut v);
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
#![crate_type="lib"]
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
|
||||
enum Enum {
|
||||
//~^ ERROR `#[repr(inttype)]` must be specified
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
error[E0732]: `#[repr(inttype)]` must be specified
|
||||
--> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1
|
||||
--> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1
|
||||
|
|
||||
LL | / enum Enum {
|
||||
LL | |
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
#![feature(const_raw_ptr_deref, test)]
|
||||
#![feature(arbitrary_enum_discriminant, const_raw_ptr_deref, test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// run-pass
|
||||
#![allow(stable_features)]
|
||||
#![feature(core, core_intrinsics)]
|
||||
#![feature(arbitrary_enum_discriminant, core, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::discriminant_value;
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
#![crate_type="lib"]
|
||||
|
||||
enum Enum {
|
||||
Unit = 1,
|
||||
//~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
|
||||
Tuple() = 2,
|
||||
//~^ ERROR discriminants on non-unit variants are experimental
|
||||
Struct{} = 3,
|
||||
//~^ ERROR discriminants on non-unit variants are experimental
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
error[E0658]: discriminants on non-unit variants are experimental
|
||||
--> $DIR/feature-gate-arbitrary_enum_discriminant.rs:6:13
|
||||
|
|
||||
LL | Tuple() = 2,
|
||||
| ^
|
||||
|
|
||||
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
|
||||
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: discriminants on non-unit variants are experimental
|
||||
--> $DIR/feature-gate-arbitrary_enum_discriminant.rs:8:14
|
||||
|
|
||||
LL | Struct{} = 3,
|
||||
| ^
|
||||
|
|
||||
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
|
||||
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
|
||||
--> $DIR/feature-gate-arbitrary_enum_discriminant.rs:4:10
|
||||
|
|
||||
LL | Unit = 1,
|
||||
| ^ disallowed custom discriminant
|
||||
LL |
|
||||
LL | Tuple() = 2,
|
||||
| ----------- tuple variant defined here
|
||||
LL |
|
||||
LL | Struct{} = 3,
|
||||
| ------------ struct variant defined here
|
||||
|
|
||||
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
|
||||
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
@ -1,4 +1,4 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::discriminant_value;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::discriminant_value;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
#![feature(repr128)]
|
||||
#![feature(repr128, arbitrary_enum_discriminant)]
|
||||
//~^ WARN the feature `repr128` is incomplete
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-70509-partial_eq.rs:2:12
|
||||
|
|
||||
LL | #![feature(repr128)]
|
||||
LL | #![feature(repr128, arbitrary_enum_discriminant)]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
|
||||
|
||||
#![feature(never_type)]
|
||||
#![feature(never_type, arbitrary_enum_discriminant)]
|
||||
#![allow(deprecated, invalid_value)]
|
||||
|
||||
use std::{
|
||||
|
||||
18
src/test/ui/mir/issue-89485.rs
Normal file
18
src/test/ui/mir/issue-89485.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Regression test for issue #89485.
|
||||
|
||||
// run-pass
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Type {
|
||||
A = 1,
|
||||
B = 2,
|
||||
}
|
||||
pub fn encode(v: Type) -> Type {
|
||||
match v {
|
||||
Type::A => Type::B,
|
||||
_ => v,
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
assert_eq!(Type::B, encode(Type::A));
|
||||
}
|
||||
7
src/test/ui/parser/issue-17383.rs
Normal file
7
src/test/ui/parser/issue-17383.rs
Normal file
@ -0,0 +1,7 @@
|
||||
enum X {
|
||||
A = 3,
|
||||
//~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
|
||||
B(usize)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
15
src/test/ui/parser/issue-17383.stderr
Normal file
15
src/test/ui/parser/issue-17383.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
|
||||
--> $DIR/issue-17383.rs:2:9
|
||||
|
|
||||
LL | A = 3,
|
||||
| ^ disallowed custom discriminant
|
||||
LL |
|
||||
LL | B(usize)
|
||||
| -------- tuple variant defined here
|
||||
|
|
||||
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
|
||||
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
4
src/test/ui/parser/issue-89574.rs
Normal file
4
src/test/ui/parser/issue-89574.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
const EMPTY_ARRAY = [];
|
||||
//~^ missing type for `const` item
|
||||
}
|
||||
8
src/test/ui/parser/issue-89574.stderr
Normal file
8
src/test/ui/parser/issue-89574.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: missing type for `const` item
|
||||
--> $DIR/issue-89574.rs:2:11
|
||||
|
|
||||
LL | const EMPTY_ARRAY = [];
|
||||
| ^^^^^^^^^^^ help: provide a type for the item: `EMPTY_ARRAY: <type>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
@ -4,3 +4,4 @@ fn main() {}
|
||||
|
||||
const A: u8; //~ ERROR free constant item without body
|
||||
const B; //~ ERROR free constant item without body
|
||||
//~^ ERROR missing type for `const` item
|
||||
|
||||
@ -14,5 +14,11 @@ LL | const B;
|
||||
| |
|
||||
| help: provide a definition for the constant: `= <expr>;`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: missing type for `const` item
|
||||
--> $DIR/item-free-const-no-body-semantic-fail.rs:6:7
|
||||
|
|
||||
LL | const B;
|
||||
| ^ help: provide a type for the item: `B: <type>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@ fn main() {}
|
||||
|
||||
static A: u8; //~ ERROR free static item without body
|
||||
static B; //~ ERROR free static item without body
|
||||
//~^ ERROR missing type for `static` item
|
||||
|
||||
static mut C: u8; //~ ERROR free static item without body
|
||||
static mut D; //~ ERROR free static item without body
|
||||
//~^ ERROR missing type for `static mut` item
|
||||
|
||||
@ -15,7 +15,7 @@ LL | static B;
|
||||
| help: provide a definition for the static: `= <expr>;`
|
||||
|
||||
error: free static item without body
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:8:1
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:9:1
|
||||
|
|
||||
LL | static mut C: u8;
|
||||
| ^^^^^^^^^^^^^^^^-
|
||||
@ -23,12 +23,24 @@ LL | static mut C: u8;
|
||||
| help: provide a definition for the static: `= <expr>;`
|
||||
|
||||
error: free static item without body
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:9:1
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:10:1
|
||||
|
|
||||
LL | static mut D;
|
||||
| ^^^^^^^^^^^^-
|
||||
| |
|
||||
| help: provide a definition for the static: `= <expr>;`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: missing type for `static` item
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:6:8
|
||||
|
|
||||
LL | static B;
|
||||
| ^ help: provide a type for the item: `B: <type>`
|
||||
|
||||
error: missing type for `static mut` item
|
||||
--> $DIR/item-free-static-no-body-semantic-fail.rs:10:12
|
||||
|
|
||||
LL | static mut D;
|
||||
| ^ help: provide a type for the item: `D: <type>`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
||||
12
src/test/ui/parser/tag-variant-disr-non-nullary.rs
Normal file
12
src/test/ui/parser/tag-variant-disr-non-nullary.rs
Normal file
@ -0,0 +1,12 @@
|
||||
enum Color {
|
||||
Red = 0xff0000,
|
||||
//~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
|
||||
Green = 0x00ff00,
|
||||
Blue = 0x0000ff,
|
||||
Black = 0x000000,
|
||||
White = 0xffffff,
|
||||
Other(usize),
|
||||
Other2(usize, usize),
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
25
src/test/ui/parser/tag-variant-disr-non-nullary.stderr
Normal file
25
src/test/ui/parser/tag-variant-disr-non-nullary.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
|
||||
--> $DIR/tag-variant-disr-non-nullary.rs:2:11
|
||||
|
|
||||
LL | Red = 0xff0000,
|
||||
| ^^^^^^^^ disallowed custom discriminant
|
||||
LL |
|
||||
LL | Green = 0x00ff00,
|
||||
| ^^^^^^^^ disallowed custom discriminant
|
||||
LL | Blue = 0x0000ff,
|
||||
| ^^^^^^^^ disallowed custom discriminant
|
||||
LL | Black = 0x000000,
|
||||
| ^^^^^^^^ disallowed custom discriminant
|
||||
LL | White = 0xffffff,
|
||||
| ^^^^^^^^ disallowed custom discriminant
|
||||
LL | Other(usize),
|
||||
| ------------ tuple variant defined here
|
||||
LL | Other2(usize, usize),
|
||||
| -------------------- tuple variant defined here
|
||||
|
|
||||
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
|
||||
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
24
src/test/ui/rust-2021/panic.rs
Normal file
24
src/test/ui/rust-2021/panic.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// edition:2021
|
||||
|
||||
fn main() {
|
||||
debug_assert!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
assert!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
panic!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
|
||||
std::debug_assert!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
std::assert!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
std::panic!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
|
||||
core::debug_assert!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
core::assert!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
core::panic!(false, 123);
|
||||
//~^ ERROR must be a string literal
|
||||
}
|
||||
101
src/test/ui/rust-2021/panic.stderr
Normal file
101
src/test/ui/rust-2021/panic.stderr
Normal file
@ -0,0 +1,101 @@
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:4:26
|
||||
|
|
||||
LL | debug_assert!(false, 123);
|
||||
| ^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | debug_assert!(false, "{}", 123);
|
||||
| +++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:6:20
|
||||
|
|
||||
LL | assert!(false, 123);
|
||||
| ^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | assert!(false, "{}", 123);
|
||||
| +++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:8:12
|
||||
|
|
||||
LL | panic!(false, 123);
|
||||
| ^^^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | panic!("{} {}", false, 123);
|
||||
| ++++++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:11:31
|
||||
|
|
||||
LL | std::debug_assert!(false, 123);
|
||||
| ^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | std::debug_assert!(false, "{}", 123);
|
||||
| +++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:13:25
|
||||
|
|
||||
LL | std::assert!(false, 123);
|
||||
| ^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | std::assert!(false, "{}", 123);
|
||||
| +++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:15:17
|
||||
|
|
||||
LL | std::panic!(false, 123);
|
||||
| ^^^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | std::panic!("{} {}", false, 123);
|
||||
| ++++++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:18:32
|
||||
|
|
||||
LL | core::debug_assert!(false, 123);
|
||||
| ^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | core::debug_assert!(false, "{}", 123);
|
||||
| +++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:20:26
|
||||
|
|
||||
LL | core::assert!(false, 123);
|
||||
| ^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | core::assert!(false, "{}", 123);
|
||||
| +++++
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/panic.rs:22:18
|
||||
|
|
||||
LL | core::panic!(false, 123);
|
||||
| ^^^^^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | core::panic!("{} {}", false, 123);
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fn main() {
|
||||
const FOO = "hello" + 1; //~ ERROR cannot add `{integer}` to `&str`
|
||||
//~^ ERROR cannot add `{integer}` to `&str`
|
||||
//~^ missing type for `const` item
|
||||
println!("{}", FOO);
|
||||
}
|
||||
|
||||
@ -6,13 +6,11 @@ LL | const FOO = "hello" + 1;
|
||||
| |
|
||||
| &str
|
||||
|
||||
error[E0369]: cannot add `{integer}` to `&str`
|
||||
--> $DIR/issue-79040.rs:2:25
|
||||
error: missing type for `const` item
|
||||
--> $DIR/issue-79040.rs:2:11
|
||||
|
|
||||
LL | const FOO = "hello" + 1;
|
||||
| ------- ^ - {integer}
|
||||
| |
|
||||
| &str
|
||||
| ^^^ help: provide a type for the item: `FOO: <type>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
11
src/tools/lld-wrapper/Cargo.toml
Normal file
11
src/tools/lld-wrapper/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "lld-wrapper"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[features]
|
||||
ld = []
|
||||
ld64 = []
|
||||
125
src/tools/lld-wrapper/src/main.rs
Normal file
125
src/tools/lld-wrapper/src/main.rs
Normal file
@ -0,0 +1,125 @@
|
||||
//! Script to invoke the bundled rust-lld with the correct flavor. The flavor is selected by
|
||||
//! feature.
|
||||
//!
|
||||
//! lld supports multiple command line interfaces. If `-flavor <flavor>` are passed as the first
|
||||
//! two arguments the `<flavor>` command line interface is used to process the remaining arguments.
|
||||
//! If no `-flavor` argument is present the flavor is determined by the executable name.
|
||||
//!
|
||||
//! In Rust with `-Z gcc-ld=lld` we have gcc or clang invoke rust-lld. Since there is no way to
|
||||
//! make gcc/clang pass `-flavor <flavor>` as the first two arguments in the linker invocation
|
||||
//! and since Windows does not support symbolic links for files this wrapper is used in place of a
|
||||
//! symblic link. It execs `../rust-lld -flavor ld` if the feature `ld` is enabled and
|
||||
//! `../rust-lld -flavor ld64` if `ld64` is enabled. On Windows it spawns a `..\rust-lld.exe`
|
||||
//! child process.
|
||||
|
||||
#[cfg(not(any(feature = "ld", feature = "ld64")))]
|
||||
compile_error!("One of the features ld and ld64 must be enabled.");
|
||||
|
||||
#[cfg(all(feature = "ld", feature = "ld64"))]
|
||||
compile_error!("Only one of the feature ld or ld64 can be enabled.");
|
||||
|
||||
#[cfg(feature = "ld")]
|
||||
const FLAVOR: &str = "ld";
|
||||
|
||||
#[cfg(feature = "ld64")]
|
||||
const FLAVOR: &str = "ld64";
|
||||
|
||||
use std::env;
|
||||
use std::fmt::Display;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
|
||||
trait ResultExt<T, E> {
|
||||
fn unwrap_or_exit_with(self, context: &str) -> T;
|
||||
}
|
||||
|
||||
impl<T, E> ResultExt<T, E> for Result<T, E>
|
||||
where
|
||||
E: Display,
|
||||
{
|
||||
fn unwrap_or_exit_with(self, context: &str) -> T {
|
||||
match self {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
eprintln!("lld-wrapper: {}: {}", context, e);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait OptionExt<T> {
|
||||
fn unwrap_or_exit_with(self, context: &str) -> T;
|
||||
}
|
||||
|
||||
impl<T> OptionExt<T> for Option<T> {
|
||||
fn unwrap_or_exit_with(self, context: &str) -> T {
|
||||
match self {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
eprintln!("lld-wrapper: {}", context);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path to rust-lld in the parent directory.
|
||||
///
|
||||
/// Exits if the parent directory cannot be determined.
|
||||
fn get_rust_lld_path(current_exe_path: &Path) -> PathBuf {
|
||||
let mut rust_lld_exe_name = "rust-lld".to_owned();
|
||||
rust_lld_exe_name.push_str(env::consts::EXE_SUFFIX);
|
||||
let mut rust_lld_path = current_exe_path
|
||||
.parent()
|
||||
.unwrap_or_exit_with("directory containing current executable could not be determined")
|
||||
.parent()
|
||||
.unwrap_or_exit_with("parent directory could not be determined")
|
||||
.to_owned();
|
||||
rust_lld_path.push(rust_lld_exe_name);
|
||||
rust_lld_path
|
||||
}
|
||||
|
||||
/// Returns the command for invoking rust-lld with the correct flavor.
|
||||
///
|
||||
/// Exits on error.
|
||||
fn get_rust_lld_command(current_exe_path: &Path) -> process::Command {
|
||||
let rust_lld_path = get_rust_lld_path(current_exe_path);
|
||||
let mut command = process::Command::new(rust_lld_path);
|
||||
command.arg("-flavor");
|
||||
command.arg(FLAVOR);
|
||||
command.args(env::args_os().skip(1));
|
||||
command
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn exec_lld(mut command: process::Command) {
|
||||
use std::os::unix::prelude::CommandExt;
|
||||
Result::<(), _>::Err(command.exec()).unwrap_or_exit_with("could not exec rust-lld");
|
||||
unreachable!("lld-wrapper: after exec without error");
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn exec_lld(mut command: process::Command) {
|
||||
// Windows has no exec(), spawn a child process and wait for it
|
||||
let exit_status = command.status().unwrap_or_exit_with("error running rust-lld child process");
|
||||
if !exit_status.success() {
|
||||
match exit_status.code() {
|
||||
Some(code) => {
|
||||
// return the original lld exit code
|
||||
process::exit(code)
|
||||
}
|
||||
None => {
|
||||
eprintln!("lld-wrapper: rust-lld child process exited with error: {}", exit_status,);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let current_exe_path =
|
||||
env::current_exe().unwrap_or_exit_with("could not get the path of the current executable");
|
||||
|
||||
exec_lld(get_rust_lld_command(current_exe_path.as_ref()));
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user