Rollup merge of #139535 - ChrisDenton:default-ptr, r=tgross35
Implement `Default` for raw pointers
ACP: https://github.com/rust-lang/libs-team/issues/571
This is instantly stable so we will need an FCP here.
Closes https://github.com/rust-lang/rfcs/issues/2464
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index d2a017b..af071c7 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -31,3 +31,5 @@
c682aa162b0d41e21cc6748f4fecfe01efb69d1f
# reformat with updated edition 2024
1fcae03369abb4c2cc180cd5a49e1f4440a81300
+# Breaking up of compiletest runtest.rs
+60600a6fa403216bfd66e04f948b1822f6450af7
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 51dd0f8..2e83bbf 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -53,6 +53,13 @@
steps:
- name: Checkout the source code
uses: actions/checkout@v4
+ # Cache citool to make its build faster, as it's in the critical path.
+ # The rust-cache doesn't bleed into the main `job`, so it should not affect any other
+ # Rust compilation.
+ - name: Cache citool
+ uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
+ with:
+ workspaces: src/ci/citool
- name: Calculate the CI job matrix
env:
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
diff --git a/.mailmap b/.mailmap
index b09aebd..c3ce111 100644
--- a/.mailmap
+++ b/.mailmap
@@ -292,6 +292,7 @@
James Miller <bladeon@gmail.com> <james@aatch.net>
James Perry <james.austin.perry@gmail.com>
James Sanderson <zofrex@gmail.com>
+Jamie Hill-Daniel <jamie@hill-daniel.co.uk> <clubby789@gmail.com>
Jana Dönszelmann <jana@donsz.nl>
Jana Dönszelmann <jana@donsz.nl> <jonathan@donsz.nl>
Jana Dönszelmann <jana@donsz.nl> <jonabent@gmail.com>
diff --git a/Cargo.lock b/Cargo.lock
index 901113b..97a90a4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -719,6 +719,7 @@
dependencies = [
"anstyle-svg",
"build_helper",
+ "camino",
"colored",
"diff",
"getopts",
@@ -932,15 +933,6 @@
]
[[package]]
-name = "deranged"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
-dependencies = [
- "powerfmt",
-]
-
-[[package]]
name = "derive-where"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1221,7 +1213,7 @@
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [
"crc32fast",
- "miniz_oxide 0.8.7",
+ "miniz_oxide 0.8.8",
]
[[package]]
@@ -2030,9 +2022,9 @@
[[package]]
name = "libc"
-version = "0.2.171"
+version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libdbus-sys"
@@ -2046,9 +2038,9 @@
[[package]]
name = "libffi"
-version = "3.2.0"
+version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
+checksum = "4a9434b6fc77375fb624698d5f8c49d7e80b10d59eb1219afda27d1f824d4074"
dependencies = [
"libc",
"libffi-sys",
@@ -2056,9 +2048,9 @@
[[package]]
name = "libffi-sys"
-version = "2.3.0"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c"
+checksum = "ead36a2496acfc8edd6cc32352110e9478ac5b9b5f5b9856ebd3d28019addb84"
dependencies = [
"cc",
]
@@ -2291,9 +2283,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
@@ -2426,12 +2418,6 @@
]
[[package]]
-name = "num-conv"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
-
-[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2587,16 +2573,6 @@
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
-name = "os_pipe"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
-dependencies = [
- "libc",
- "windows-sys 0.59.0",
-]
-
-[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2809,12 +2785,6 @@
]
[[package]]
-name = "powerfmt"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
-
-[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3162,7 +3132,6 @@
"gimli 0.31.1",
"libc",
"object 0.36.7",
- "os_pipe",
"regex",
"serde_json",
"similar",
@@ -3218,26 +3187,13 @@
]
[[package]]
-name = "rustc-rayon"
+name = "rustc-rayon-core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cd9fb077db982d7ceb42a90471e5a69a990b58f71e06f0d8340bb2cf35eb751"
+checksum = "2f42932dcd3bcbe484b38a3ccf79b7906fac41c02d408b5b1bac26da3416efdb"
dependencies = [
- "either",
- "indexmap",
- "rustc-rayon-core",
-]
-
-[[package]]
-name = "rustc-rayon-core"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67668daaf00e359c126f6dcb40d652d89b458a008c8afa727a42a2d20fca0b7f"
-dependencies = [
- "crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
- "num_cpus",
]
[[package]]
@@ -3599,7 +3555,7 @@
"parking_lot",
"portable-atomic",
"rustc-hash 2.1.1",
- "rustc-rayon",
+ "rustc-rayon-core",
"rustc-stable-hash",
"rustc_arena",
"rustc_graphviz",
@@ -3627,6 +3583,7 @@
version = "0.0.0"
dependencies = [
"ctrlc",
+ "jiff",
"libc",
"rustc_abi",
"rustc_ast",
@@ -3673,7 +3630,6 @@
"rustc_ty_utils",
"serde_json",
"shlex",
- "time",
"tracing",
"windows 0.59.0",
]
@@ -3945,7 +3901,6 @@
name = "rustc_interface"
version = "0.0.0"
dependencies = [
- "rustc-rayon",
"rustc-rayon-core",
"rustc_abi",
"rustc_ast",
@@ -4409,7 +4364,6 @@
"rustc_feature",
"rustc_fluent_macro",
"rustc_hir",
- "rustc_index",
"rustc_macros",
"rustc_metadata",
"rustc_middle",
@@ -4456,6 +4410,7 @@
"bitflags",
"getopts",
"libc",
+ "rand 0.9.0",
"rustc_abi",
"rustc_ast",
"rustc_data_structures",
@@ -4704,6 +4659,7 @@
version = "0.1.0"
dependencies = [
"build_helper",
+ "camino",
"compiletest",
"getopts",
"walkdir",
@@ -5369,37 +5325,6 @@
]
[[package]]
-name = "time"
-version = "0.3.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
-dependencies = [
- "deranged",
- "itoa",
- "num-conv",
- "powerfmt",
- "serde",
- "time-core",
- "time-macros",
-]
-
-[[package]]
-name = "time-core"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
-
-[[package]]
-name = "time-macros"
-version = "0.2.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
-dependencies = [
- "num-conv",
- "time-core",
-]
-
-[[package]]
name = "tinystr"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6123,11 +6048,13 @@
[[package]]
name = "windows-bindgen"
-version = "0.59.0"
+version = "0.61.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7fb600834d7e868f6e5bb748a86101427330fafbf9485c331b9d5f562d54a5"
+checksum = "ac1c59c20569610dd9ed784d5f003fb493ec57b4cf39d974eb03a84bb7156c90"
dependencies = [
"rayon",
+ "serde",
+ "serde_json",
]
[[package]]
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 7bffeaf..42250aa 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -315,7 +315,7 @@ pub fn layout_of_struct_or_enum<
repr: &ReprOptions,
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
is_enum: bool,
- is_unsafe_cell: bool,
+ is_special_no_niche: bool,
scalar_valid_range: (Bound<u128>, Bound<u128>),
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
@@ -348,7 +348,7 @@ pub fn layout_of_struct_or_enum<
repr,
variants,
is_enum,
- is_unsafe_cell,
+ is_special_no_niche,
scalar_valid_range,
always_sized,
present_first,
@@ -505,7 +505,7 @@ fn layout_of_struct<
repr: &ReprOptions,
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
is_enum: bool,
- is_unsafe_cell: bool,
+ is_special_no_niche: bool,
scalar_valid_range: (Bound<u128>, Bound<u128>),
always_sized: bool,
present_first: VariantIdx,
@@ -524,7 +524,7 @@ fn layout_of_struct<
let mut st = self.univariant(&variants[v], repr, kind)?;
st.variants = Variants::Single { index: v };
- if is_unsafe_cell {
+ if is_special_no_niche {
let hide_niches = |scalar: &mut _| match scalar {
Scalar::Initialized { value, valid_range } => {
*valid_range = WrappingRange::full(value.size(dl))
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 3fb88c9..1532ca7 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -120,6 +120,17 @@ pub fn from_ident(ident: Ident) -> Path {
Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
}
+ pub fn is_ident(&self, name: Symbol) -> bool {
+ if let [segment] = self.segments.as_ref()
+ && segment.args.is_none()
+ && segment.ident.name == name
+ {
+ true
+ } else {
+ false
+ }
+ }
+
pub fn is_global(&self) -> bool {
self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
}
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index c9e2e99..7f98e7b 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -6,7 +6,6 @@
use std::marker::PhantomData;
use crate::ptr::P;
-use crate::token::Nonterminal;
use crate::tokenstream::LazyAttrTokenStream;
use crate::{
Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
@@ -206,19 +205,6 @@ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
}
}
-impl HasTokens for Nonterminal {
- fn tokens(&self) -> Option<&LazyAttrTokenStream> {
- match self {
- Nonterminal::NtBlock(block) => block.tokens(),
- }
- }
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
- match self {
- Nonterminal::NtBlock(block) => block.tokens_mut(),
- }
- }
-}
-
/// A trait for AST nodes having (or not having) attributes.
pub trait HasAttrs {
/// This is `true` if this `HasAttrs` might support 'custom' (proc-macro) inner
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 0b65246..f104400 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -305,8 +305,8 @@ pub fn ident(&self) -> Option<Ident> {
if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None }
}
- pub fn name_or_empty(&self) -> Symbol {
- self.ident().unwrap_or_else(Ident::empty).name
+ pub fn name(&self) -> Option<Symbol> {
+ self.ident().map(|ident| ident.name)
}
pub fn has_name(&self, name: Symbol) -> bool {
@@ -511,13 +511,14 @@ pub fn span(&self) -> Span {
}
}
- /// For a single-segment meta item, returns its name; otherwise, returns `None`.
+ /// For a single-segment meta item, returns its identifier; otherwise, returns `None`.
pub fn ident(&self) -> Option<Ident> {
self.meta_item().and_then(|meta_item| meta_item.ident())
}
- pub fn name_or_empty(&self) -> Symbol {
- self.ident().unwrap_or_else(Ident::empty).name
+ /// For a single-segment meta item, returns its name; otherwise, returns `None`.
+ pub fn name(&self) -> Option<Symbol> {
+ self.ident().map(|ident| ident.name)
}
/// Returns `true` if this list item is a MetaItem with a name of `name`.
@@ -627,7 +628,7 @@ pub fn mk_doc_comment(
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
}
-pub fn mk_attr(
+fn mk_attr(
g: &AttrIdGenerator,
style: AttrStyle,
unsafety: Safety,
@@ -738,9 +739,9 @@ pub trait AttributeExt: Debug {
fn id(&self) -> AttrId;
/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
- /// return the name of the attribute, else return the empty identifier.
- fn name_or_empty(&self) -> Symbol {
- self.ident().unwrap_or_else(Ident::empty).name
+ /// return the name of the attribute; otherwise, returns `None`.
+ fn name(&self) -> Option<Symbol> {
+ self.ident().map(|ident| ident.name)
}
/// Get the meta item list, `#[attr(meta item list)]`
@@ -752,7 +753,7 @@ fn name_or_empty(&self) -> Symbol {
/// Gets the span of the value literal, as string, when using `#[attr = value]`
fn value_span(&self) -> Option<Span>;
- /// For a single-segment attribute, returns its name; otherwise, returns `None`.
+ /// For a single-segment attribute, returns its ident; otherwise, returns `None`.
fn ident(&self) -> Option<Ident>;
/// Checks whether the path of this attribute matches the name.
@@ -770,6 +771,11 @@ fn has_name(&self, name: Symbol) -> bool {
self.ident().map(|x| x.name == name).unwrap_or(false)
}
+ #[inline]
+ fn has_any_name(&self, names: &[Symbol]) -> bool {
+ names.iter().any(|&name| self.has_name(name))
+ }
+
/// get the span of the entire attribute
fn span(&self) -> Span;
@@ -813,8 +819,8 @@ pub fn id(&self) -> AttrId {
AttributeExt::id(self)
}
- pub fn name_or_empty(&self) -> Symbol {
- AttributeExt::name_or_empty(self)
+ pub fn name(&self) -> Option<Symbol> {
+ AttributeExt::name(self)
}
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
@@ -846,6 +852,11 @@ pub fn has_name(&self, name: Symbol) -> bool {
AttributeExt::has_name(self, name)
}
+ #[inline]
+ pub fn has_any_name(&self, names: &[Symbol]) -> bool {
+ AttributeExt::has_any_name(self, names)
+ }
+
pub fn span(&self) -> Span {
AttributeExt::span(self)
}
diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
index 13a7c5a..2f918fa 100644
--- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs
+++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
@@ -50,8 +50,16 @@ pub enum DiffActivity {
/// with it.
Dual,
/// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument
+ /// with it. It expects the shadow argument to be `width` times larger than the original
+ /// input/output.
+ Dualv,
+ /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument
/// with it. Drop the code which updates the original input/output for maximum performance.
DualOnly,
+ /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument
+ /// with it. Drop the code which updates the original input/output for maximum performance.
+ /// It expects the shadow argument to be `width` times larger than the original input/output.
+ DualvOnly,
/// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument.
Duplicated,
/// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument.
@@ -59,7 +67,15 @@ pub enum DiffActivity {
DuplicatedOnly,
/// All Integers must be Const, but these are used to mark the integer which represents the
/// length of a slice/vec. This is used for safety checks on slices.
- FakeActivitySize,
+ /// The integer (if given) specifies the size of the slice element in bytes.
+ FakeActivitySize(Option<u32>),
+}
+
+impl DiffActivity {
+ pub fn is_dual_or_const(&self) -> bool {
+ use DiffActivity::*;
+ matches!(self, |Dual| DualOnly | Dualv | DualvOnly | Const)
+ }
}
/// We generate one of these structs for each `#[autodiff(...)]` attribute.
#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
@@ -131,11 +147,7 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool {
match mode {
DiffMode::Error => false,
DiffMode::Source => false,
- DiffMode::Forward => {
- activity == DiffActivity::Dual
- || activity == DiffActivity::DualOnly
- || activity == DiffActivity::Const
- }
+ DiffMode::Forward => activity.is_dual_or_const(),
DiffMode::Reverse => {
activity == DiffActivity::Const
|| activity == DiffActivity::Active
@@ -153,10 +165,8 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool {
pub fn valid_ty_for_activity(ty: &P<Ty>, activity: DiffActivity) -> bool {
use DiffActivity::*;
// It's always allowed to mark something as Const, since we won't compute derivatives wrt. it.
- if matches!(activity, Const) {
- return true;
- }
- if matches!(activity, Dual | DualOnly) {
+ // Dual variants also support all types.
+ if activity.is_dual_or_const() {
return true;
}
// FIXME(ZuseZ4) We should make this more robust to also
@@ -172,9 +182,7 @@ pub fn valid_input_activity(mode: DiffMode, activity: DiffActivity) -> bool {
return match mode {
DiffMode::Error => false,
DiffMode::Source => false,
- DiffMode::Forward => {
- matches!(activity, Dual | DualOnly | Const)
- }
+ DiffMode::Forward => activity.is_dual_or_const(),
DiffMode::Reverse => {
matches!(activity, Active | ActiveOnly | Duplicated | DuplicatedOnly | Const)
}
@@ -189,10 +197,12 @@ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
DiffActivity::Active => write!(f, "Active"),
DiffActivity::ActiveOnly => write!(f, "ActiveOnly"),
DiffActivity::Dual => write!(f, "Dual"),
+ DiffActivity::Dualv => write!(f, "Dualv"),
DiffActivity::DualOnly => write!(f, "DualOnly"),
+ DiffActivity::DualvOnly => write!(f, "DualvOnly"),
DiffActivity::Duplicated => write!(f, "Duplicated"),
DiffActivity::DuplicatedOnly => write!(f, "DuplicatedOnly"),
- DiffActivity::FakeActivitySize => write!(f, "FakeActivitySize"),
+ DiffActivity::FakeActivitySize(s) => write!(f, "FakeActivitySize({:?})", s),
}
}
}
@@ -220,7 +230,9 @@ fn from_str(s: &str) -> Result<DiffActivity, ()> {
"ActiveOnly" => Ok(DiffActivity::ActiveOnly),
"Const" => Ok(DiffActivity::Const),
"Dual" => Ok(DiffActivity::Dual),
+ "Dualv" => Ok(DiffActivity::Dualv),
"DualOnly" => Ok(DiffActivity::DualOnly),
+ "DualvOnly" => Ok(DiffActivity::DualvOnly),
"Duplicated" => Ok(DiffActivity::Duplicated),
"DuplicatedOnly" => Ok(DiffActivity::DuplicatedOnly),
_ => Err(()),
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index da510e4..294c6c9 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -6,7 +6,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
test(attr(deny(warnings)))
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index b083e87..6aae2e4 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -844,9 +844,9 @@ fn visit_lazy_tts<T: MutVisitor>(vis: &mut T, lazy_tts: &mut Option<LazyAttrToke
visit_lazy_tts_opt_mut(vis, lazy_tts.as_mut());
}
-/// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
-/// In practice the ident part is not actually used by specific visitors right now,
-/// but there's a test below checking that it works.
+/// Applies ident visitor if it's an ident. In practice this is not actually
+/// used by specific visitors right now, but there's a test below checking that
+/// it works.
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
let Token { kind, span } = t;
@@ -864,46 +864,12 @@ pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
token::NtLifetime(ident, _is_raw) => {
vis.visit_ident(ident);
}
- token::Interpolated(nt) => {
- let nt = Arc::make_mut(nt);
- visit_nonterminal(vis, nt);
- }
_ => {}
}
vis.visit_span(span);
}
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-/// Applies the visitor to elements of interpolated nodes.
-//
-// N.B., this can occur only when applying a visitor to partially expanded
-// code, where parsed pieces have gotten implanted ito *other* macro
-// invocations. This is relevant for macro hygiene, but possibly not elsewhere.
-//
-// One problem here occurs because the types for flat_map_item, flat_map_stmt,
-// etc., allow the visitor to return *multiple* items; this is a problem for the
-// nodes here, because they insist on having exactly one piece. One solution
-// would be to mangle the MutVisitor trait to include one-to-many and
-// one-to-one versions of these entry points, but that would probably confuse a
-// lot of people and help very few. Instead, I'm just going to put in dynamic
-// checks. I think the performance impact of this will be pretty much
-// nonexistent. The danger is that someone will apply a `MutVisitor` to a
-// partially expanded node, and will be confused by the fact that their
-// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt`
-// nodes. Hopefully they'll wind up reading this comment, and doing something
-// appropriate.
-//
-// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to
-// contain multiple items, but decided against it when I looked at
-// `parse_item_or_view_item` and tried to figure out what I would do with
-// multiple items there....
-fn visit_nonterminal<T: MutVisitor>(vis: &mut T, nt: &mut token::Nonterminal) {
- match nt {
- token::NtBlock(block) => vis.visit_block(block),
- }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
fn visit_defaultness<T: MutVisitor>(vis: &mut T, defaultness: &mut Defaultness) {
match defaultness {
Defaultness::Default(span) => vis.visit_span(span),
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index d57a369..055481f 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -1,13 +1,10 @@
use std::borrow::Cow;
use std::fmt;
-use std::sync::Arc;
pub use LitKind::*;
-pub use Nonterminal::*;
pub use NtExprKind::*;
pub use NtPatKind::*;
pub use TokenKind::*;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::edition::Edition;
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym};
@@ -16,7 +13,6 @@
use rustc_span::{Ident, Symbol};
use crate::ast;
-use crate::ptr::P;
use crate::util::case::Case;
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
@@ -34,10 +30,6 @@ pub enum InvisibleOrigin {
// Converted from `proc_macro::Delimiter` in
// `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro.
ProcMacro,
-
- // Converted from `TokenKind::Interpolated` in
- // `TokenStream::flatten_token`. Treated similarly to `ProcMacro`.
- FlattenToken,
}
impl PartialEq for InvisibleOrigin {
@@ -134,9 +126,7 @@ pub fn skip(&self) -> bool {
match self {
Delimiter::Parenthesis | Delimiter::Bracket | Delimiter::Brace => false,
Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) => false,
- Delimiter::Invisible(InvisibleOrigin::FlattenToken | InvisibleOrigin::ProcMacro) => {
- true
- }
+ Delimiter::Invisible(InvisibleOrigin::ProcMacro) => true,
}
}
@@ -337,9 +327,7 @@ fn from(is_raw: IdentIsRaw) -> bool {
}
}
-// SAFETY: due to the `Clone` impl below, all fields of all variants other than
-// `Interpolated` must impl `Copy`.
-#[derive(PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum TokenKind {
/* Expression-operator symbols. */
/// `=`
@@ -468,21 +456,6 @@ pub enum TokenKind {
/// the `lifetime` metavariable in the macro's RHS.
NtLifetime(Ident, IdentIsRaw),
- /// An embedded AST node, as produced by a macro. This only exists for
- /// historical reasons. We'd like to get rid of it, for multiple reasons.
- /// - It's conceptually very strange. Saying a token can contain an AST
- /// node is like saying, in natural language, that a word can contain a
- /// sentence.
- /// - It requires special handling in a bunch of places in the parser.
- /// - It prevents `Token` from implementing `Copy`.
- /// It adds complexity and likely slows things down. Please don't add new
- /// occurrences of this token kind!
- ///
- /// The span in the surrounding `Token` is that of the metavariable in the
- /// macro's RHS. The span within the Nonterminal is that of the fragment
- /// passed to the macro at the call site.
- Interpolated(Arc<Nonterminal>),
-
/// A doc comment token.
/// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
/// similarly to symbols in string literal tokens.
@@ -492,20 +465,7 @@ pub enum TokenKind {
Eof,
}
-impl Clone for TokenKind {
- fn clone(&self) -> Self {
- // `TokenKind` would impl `Copy` if it weren't for `Interpolated`. So
- // for all other variants, this implementation of `clone` is just like
- // a copy. This is faster than the `derive(Clone)` version which has a
- // separate path for every variant.
- match self {
- Interpolated(nt) => Interpolated(Arc::clone(nt)),
- _ => unsafe { std::ptr::read(self) },
- }
- }
-}
-
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Token {
pub kind: TokenKind,
pub span: Span,
@@ -600,7 +560,7 @@ pub fn is_punct(&self) -> bool {
| FatArrow | Pound | Dollar | Question | SingleQuote => true,
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
- | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Interpolated(..) | Eof => false,
+ | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false,
}
}
@@ -631,7 +591,6 @@ pub fn can_begin_expr(&self) -> bool {
PathSep | // global path
Lifetime(..) | // labeled loop
Pound => true, // expression attributes
- Interpolated(ref nt) => matches!(&**nt, NtBlock(..)),
OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
MetaVarKind::Block |
MetaVarKind::Expr { .. } |
@@ -703,7 +662,6 @@ pub fn can_begin_const_arg(&self) -> bool {
match self.kind {
OpenDelim(Delimiter::Brace) | Literal(..) | Minus => true,
Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
- Interpolated(ref nt) => matches!(&**nt, NtBlock(..)),
OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal,
))) => true,
@@ -831,31 +789,20 @@ pub fn is_ident_named(&self, name: Symbol) -> bool {
/// Is this a pre-parsed expression dropped into the token stream
/// (which happens while parsing the result of macro expansion)?
pub fn is_metavar_expr(&self) -> bool {
- #[allow(irrefutable_let_patterns)] // FIXME: temporary
- if let Interpolated(nt) = &self.kind
- && let NtBlock(_) = &**nt
- {
- true
- } else if matches!(
+ matches!(
self.is_metavar_seq(),
- Some(MetaVarKind::Expr { .. } | MetaVarKind::Literal | MetaVarKind::Path)
- ) {
- true
- } else {
- matches!(self.is_metavar_seq(), Some(MetaVarKind::Path))
- }
+ Some(
+ MetaVarKind::Expr { .. }
+ | MetaVarKind::Literal
+ | MetaVarKind::Path
+ | MetaVarKind::Block
+ )
+ )
}
- /// Is the token an interpolated block (`$b:block`)?
- pub fn is_whole_block(&self) -> bool {
- #[allow(irrefutable_let_patterns)] // FIXME: temporary
- if let Interpolated(nt) = &self.kind
- && let NtBlock(..) = &**nt
- {
- return true;
- }
-
- false
+ /// Are we at a block from a metavar (`$b:block`)?
+ pub fn is_metavar_block(&self) -> bool {
+ matches!(self.is_metavar_seq(), Some(MetaVarKind::Block))
}
/// Returns `true` if the token is either the `mut` or `const` keyword.
@@ -1024,7 +971,7 @@ pub fn glue(&self, joint: &Token) -> Option<Token> {
| PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | DotDotDot | DotDotEq
| Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question
| OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) | NtIdent(..)
- | Lifetime(..) | NtLifetime(..) | Interpolated(..) | DocComment(..) | Eof,
+ | Lifetime(..) | NtLifetime(..) | DocComment(..) | Eof,
_,
) => {
return None;
@@ -1063,12 +1010,6 @@ pub enum NtExprKind {
Expr2021 { inferred: bool },
}
-#[derive(Clone, Encodable, Decodable)]
-/// For interpolation during macro expansion.
-pub enum Nonterminal {
- NtBlock(P<ast::Block>),
-}
-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
pub enum NonterminalKind {
Item,
@@ -1152,47 +1093,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl Nonterminal {
- pub fn use_span(&self) -> Span {
- match self {
- NtBlock(block) => block.span,
- }
- }
-
- pub fn descr(&self) -> &'static str {
- match self {
- NtBlock(..) => "block",
- }
- }
-}
-
-impl PartialEq for Nonterminal {
- fn eq(&self, _rhs: &Self) -> bool {
- // FIXME: Assume that all nonterminals are not equal, we can't compare them
- // correctly based on data from AST. This will prevent them from matching each other
- // in macros. The comparison will become possible only when each nonterminal has an
- // attached token stream from which it was parsed.
- false
- }
-}
-
-impl fmt::Debug for Nonterminal {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match *self {
- NtBlock(..) => f.pad("NtBlock(..)"),
- }
- }
-}
-
-impl<CTX> HashStable<CTX> for Nonterminal
-where
- CTX: crate::HashStableContext,
-{
- fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
- panic!("interpolated tokens should not be present in the HIR")
- }
-}
-
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
@@ -1202,7 +1102,6 @@ mod size_asserts {
// tidy-alphabetical-start
static_assert_size!(Lit, 12);
static_assert_size!(LitKind, 2);
- static_assert_size!(Nonterminal, 8);
static_assert_size!(Token, 24);
static_assert_size!(TokenKind, 16);
// tidy-alphabetical-end
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index fb331e7..43d25d1 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -25,7 +25,7 @@
use crate::ast::AttrStyle;
use crate::ast_traits::{HasAttrs, HasTokens};
-use crate::token::{self, Delimiter, InvisibleOrigin, Nonterminal, Token, TokenKind};
+use crate::token::{self, Delimiter, Token, TokenKind};
use crate::{AttrVec, Attribute};
/// Part of a `TokenStream`.
@@ -305,11 +305,6 @@ pub struct AttrsTarget {
}
/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
-///
-/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
-/// instead of a representation of the abstract syntax tree.
-/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
-/// backwards compatibility.
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
@@ -476,61 +471,6 @@ pub fn from_ast(node: &(impl HasAttrs + HasTokens + fmt::Debug)) -> TokenStream
TokenStream::new(tts)
}
- pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
- match nt {
- Nonterminal::NtBlock(block) => TokenStream::from_ast(block),
- }
- }
-
- fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
- match token.kind {
- token::NtIdent(ident, is_raw) => {
- TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
- }
- token::NtLifetime(ident, is_raw) => TokenTree::Delimited(
- DelimSpan::from_single(token.span),
- DelimSpacing::new(Spacing::JointHidden, spacing),
- Delimiter::Invisible(InvisibleOrigin::FlattenToken),
- TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span),
- ),
- token::Interpolated(ref nt) => TokenTree::Delimited(
- DelimSpan::from_single(token.span),
- DelimSpacing::new(Spacing::JointHidden, spacing),
- Delimiter::Invisible(InvisibleOrigin::FlattenToken),
- TokenStream::from_nonterminal_ast(&nt).flattened(),
- ),
- _ => TokenTree::Token(token.clone(), spacing),
- }
- }
-
- fn flatten_token_tree(tree: &TokenTree) -> TokenTree {
- match tree {
- TokenTree::Token(token, spacing) => TokenStream::flatten_token(token, *spacing),
- TokenTree::Delimited(span, spacing, delim, tts) => {
- TokenTree::Delimited(*span, *spacing, *delim, tts.flattened())
- }
- }
- }
-
- #[must_use]
- pub fn flattened(&self) -> TokenStream {
- fn can_skip(stream: &TokenStream) -> bool {
- stream.iter().all(|tree| match tree {
- TokenTree::Token(token, _) => !matches!(
- token.kind,
- token::NtIdent(..) | token::NtLifetime(..) | token::Interpolated(..)
- ),
- TokenTree::Delimited(.., inner) => can_skip(inner),
- })
- }
-
- if can_skip(self) {
- return self.clone();
- }
-
- self.iter().map(|tree| TokenStream::flatten_token_tree(tree)).collect()
- }
-
// If `vec` is not empty, try to glue `tt` onto its last token. The return
// value indicates if gluing took place.
fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 2296b05..93c627f 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -85,7 +85,7 @@ fn is_method(&self, def_id: DefId, span: Span) -> bool {
.delegation_fn_sigs
.get(&local_def_id)
.is_some_and(|sig| sig.has_self),
- None => self.tcx.associated_item(def_id).fn_has_self_parameter,
+ None => self.tcx.associated_item(def_id).is_method(),
},
_ => span_bug!(span, "unexpected DefKind for delegation item"),
}
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index df4fd2e..8e1a3cd 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -399,12 +399,16 @@ pub(crate) fn inject_ensures_check(
&mut self,
expr: &'hir hir::Expr<'hir>,
span: Span,
- check_ident: Ident,
- check_hir_id: HirId,
+ cond_ident: Ident,
+ cond_hir_id: HirId,
) -> &'hir hir::Expr<'hir> {
- let checker_fn = self.expr_ident(span, check_ident, check_hir_id);
- let span = self.mark_span_with_reason(DesugaringKind::Contract, span, None);
- self.expr_call(span, checker_fn, std::slice::from_ref(expr))
+ let cond_fn = self.expr_ident(span, cond_ident, cond_hir_id);
+ let call_expr = self.expr_call_lang_item_fn_mut(
+ span,
+ hir::LangItem::ContractCheckEnsures,
+ arena_vec![self; *cond_fn, *expr],
+ );
+ self.arena.alloc(call_expr)
}
pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 59099e5..fc32c4e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1206,8 +1206,13 @@ pub(super) fn lower_fn_body(
let precond = if let Some(req) = &contract.requires {
// Lower the precondition check intrinsic.
let lowered_req = this.lower_expr_mut(&req);
+ let req_span = this.mark_span_with_reason(
+ DesugaringKind::Contract,
+ lowered_req.span,
+ None,
+ );
let precond = this.expr_call_lang_item_fn_mut(
- req.span,
+ req_span,
hir::LangItem::ContractCheckRequires,
&*arena_vec![this; lowered_req],
);
@@ -1217,6 +1222,8 @@ pub(super) fn lower_fn_body(
};
let (postcond, body) = if let Some(ens) = &contract.ensures {
let ens_span = this.lower_span(ens.span);
+ let ens_span =
+ this.mark_span_with_reason(DesugaringKind::Contract, ens_span, None);
// Set up the postcondition `let` statement.
let check_ident: Ident =
Ident::from_str_and_span("__ensures_checker", ens_span);
@@ -1303,7 +1310,7 @@ fn lower_maybe_coroutine_body(
// create a fake body so that the entire rest of the compiler doesn't have to deal with
// this as a special case.
return self.lower_fn_body(decl, contract, |this| {
- if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) {
+ if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) {
let span = this.lower_span(span);
let empty_block = hir::Block {
hir_id: this.next_id(),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 22a293d..c409875 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -32,7 +32,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
@@ -917,7 +916,7 @@ fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
}
fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs {
- DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.flattened() }
+ DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.clone() }
}
/// Lower an associated item constraint.
@@ -1766,24 +1765,23 @@ fn new_named_lifetime(
ident: Ident,
is_anon_in_path: IsAnonInPath,
) -> &'hir hir::Lifetime {
- debug_assert_ne!(ident.name, kw::Empty);
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
let res = match res {
- LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param),
+ LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param),
LifetimeRes::Fresh { param, .. } => {
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
let param = self.local_def_id(param);
- hir::LifetimeName::Param(param)
+ hir::LifetimeKind::Param(param)
}
LifetimeRes::Infer => {
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
- hir::LifetimeName::Infer
+ hir::LifetimeKind::Infer
}
LifetimeRes::Static { .. } => {
debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
- hir::LifetimeName::Static
+ hir::LifetimeKind::Static
}
- LifetimeRes::Error => hir::LifetimeName::Error,
+ LifetimeRes::Error => hir::LifetimeKind::Error,
LifetimeRes::ElidedAnchor { .. } => {
panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span);
}
@@ -2390,7 +2388,7 @@ fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
let r = hir::Lifetime::new(
self.next_id(),
Ident::new(kw::UnderscoreLifetime, self.lower_span(span)),
- hir::LifetimeName::ImplicitObjectLifetimeDefault,
+ hir::LifetimeKind::ImplicitObjectLifetimeDefault,
IsAnonInPath::No,
);
debug!("elided_dyn_bound: r={:?}", r);
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index c464c15..0bd65ae 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -448,8 +448,7 @@ fn maybe_insert_elided_lifetimes_in_path(
generic_args.args.insert_many(
0,
- (start.as_u32()..end.as_u32()).map(|i| {
- let id = NodeId::from_u32(i);
+ (start..end).map(|id| {
let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span);
GenericArg::Lifetime(l)
}),
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 2594439..80754a8 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -79,6 +79,10 @@
.suggestion = remove the {$remove_descr}
.label = `extern` block begins here
+ast_passes_extern_without_abi = `extern` declarations without an explicit ABI are disallowed
+ .suggestion = specify an ABI
+ .help = prior to Rust 2024, a default ABI was inferred
+
ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
.suggestion = remove the attribute
.stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index dc77e7b..1feb3e9 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -347,7 +347,7 @@ fn check_decl_attrs(&self, fn_decl: &FnDecl) {
sym::forbid,
sym::warn,
];
- !arr.contains(&attr.name_or_empty()) && rustc_attr_parsing::is_builtin_attr(*attr)
+ !attr.has_any_name(&arr) && rustc_attr_parsing::is_builtin_attr(*attr)
})
.for_each(|attr| {
if attr.is_doc_comment() {
@@ -684,7 +684,7 @@ fn visit_ty_common(&mut self, ty: &'a Ty) {
self.dcx().emit_err(errors::PatternFnPointer { span });
});
if let Extern::Implicit(extern_span) = bfty.ext {
- self.maybe_lint_missing_abi(extern_span, ty.id);
+ self.handle_missing_abi(extern_span, ty.id);
}
}
TyKind::TraitObject(bounds, ..) => {
@@ -717,10 +717,12 @@ fn visit_ty_common(&mut self, ty: &'a Ty) {
}
}
- fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId) {
+ fn handle_missing_abi(&mut self, span: Span, id: NodeId) {
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
// call site which do not have a macro backtrace. See #61963.
- if self
+ if span.edition().at_least_edition_future() && self.features.explicit_extern_abis() {
+ self.dcx().emit_err(errors::MissingAbi { span });
+ } else if self
.sess
.source_map()
.span_to_snippet(span)
@@ -945,8 +947,7 @@ fn visit_item(&mut self, item: &'a Item) {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
self.check_defaultness(item.span, *defaultness);
- let is_intrinsic =
- item.attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic);
+ let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
if body.is_none() && !is_intrinsic {
self.dcx().emit_err(errors::FnWithoutBody {
span: item.span,
@@ -996,7 +997,7 @@ fn visit_item(&mut self, item: &'a Item) {
}
if abi.is_none() {
- self.maybe_lint_missing_abi(*extern_span, item.id);
+ self.handle_missing_abi(*extern_span, item.id);
}
self.with_in_extern_mod(*safety, |this| {
visit::walk_item(this, item);
@@ -1370,7 +1371,7 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
},
) = fk
{
- self.maybe_lint_missing_abi(*extern_span, id);
+ self.handle_missing_abi(*extern_span, id);
}
// Functions without bodies cannot have patterns.
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 8e53e60..6f9737e 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -2,7 +2,7 @@
use rustc_ast::ParamKindOrd;
use rustc_errors::codes::*;
-use rustc_errors::{Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Ident, Span, Symbol};
@@ -394,11 +394,7 @@ pub(crate) struct ArgsBeforeConstraint {
// The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
impl Subdiagnostic for EmptyLabelManySpans {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.span_labels(self.0, "");
}
}
@@ -749,11 +745,7 @@ pub(crate) struct StableFeature {
}
impl Subdiagnostic for StableFeature {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("name", self.name);
diag.arg("since", self.since);
diag.help(fluent::ast_passes_stable_since);
@@ -823,3 +815,12 @@ pub(crate) struct DuplicatePreciseCapturing {
#[label]
pub bound2: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_extern_without_abi)]
+#[help]
+pub(crate) struct MissingAbi {
+ #[primary_span]
+ #[suggestion(code = "extern \"<abi>\"", applicability = "has-placeholders")]
+ pub span: Span,
+}
diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs
index 97cb6e5..551506f 100644
--- a/compiler/rustc_ast_pretty/src/pprust/mod.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs
@@ -5,14 +5,10 @@
use std::borrow::Cow;
use rustc_ast as ast;
-use rustc_ast::token::{Nonterminal, Token, TokenKind};
+use rustc_ast::token::{Token, TokenKind};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate};
-pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
- State::new().nonterminal_to_string(nt)
-}
-
/// Print the token kind precisely, without converting `$crate` into its respective crate name.
pub fn token_kind_to_string(tok: &TokenKind) -> Cow<'static, str> {
State::new().token_kind_to_string(tok)
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 90caad1c..0985ebf 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -11,7 +11,7 @@
use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
use rustc_ast::util::classify;
use rustc_ast::util::comments::{Comment, CommentStyle};
@@ -876,14 +876,6 @@ fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
}
}
- fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
- // We extract the token stream from the AST fragment and pretty print
- // it, rather than using AST pretty printing, because `Nonterminal` is
- // slated for removal in #124141. (This method will also then be
- // removed.)
- self.tts_to_string(&TokenStream::from_nonterminal_ast(nt))
- }
-
/// Print the token kind precisely, without converting `$crate` into its respective crate name.
fn token_kind_to_string(&self, tok: &TokenKind) -> Cow<'static, str> {
self.token_kind_to_string_ext(tok, None)
@@ -976,8 +968,6 @@ fn token_kind_to_string_ext(
doc_comment_to_string(comment_kind, attr_style, data).into()
}
token::Eof => "<eof>".into(),
-
- token::Interpolated(ref nt) => self.nonterminal_to_string(&nt).into(),
}
}
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
index 0d6d521..7cb1fed 100644
--- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
@@ -7,7 +7,6 @@
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
use rustc_session::parse::feature_err;
-use rustc_span::symbol::kw;
use rustc_span::{Span, Symbol, sym};
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
@@ -89,20 +88,6 @@ pub fn eval_condition(
let cfg = match cfg {
MetaItemInner::MetaItem(meta_item) => meta_item,
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
- if let Some(features) = features {
- // we can't use `try_gate_cfg` as symbols don't differentiate between `r#true`
- // and `true`, and we want to keep the former working without feature gate
- gate_cfg(
- &(
- if *b { kw::True } else { kw::False },
- sym::cfg_boolean_literals,
- |features: &Features| features.cfg_boolean_literals(),
- ),
- cfg.span(),
- sess,
- features,
- );
- }
return *b;
}
_ => {
@@ -117,7 +102,7 @@ pub fn eval_condition(
};
match &cfg.kind {
- MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
+ MetaItemKind::List(mis) if cfg.has_name(sym::version) => {
try_gate_cfg(sym::version, cfg.span, sess, features);
let (min_version, span) = match &mis[..] {
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
@@ -164,18 +149,18 @@ pub fn eval_condition(
// The unwraps below may look dangerous, but we've already asserted
// that they won't fail with the loop above.
- match cfg.name_or_empty() {
- sym::any => mis
+ match cfg.name() {
+ Some(sym::any) => mis
.iter()
// We don't use any() here, because we want to evaluate all cfg condition
// as eval_condition can (and does) extra checks
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
- sym::all => mis
+ Some(sym::all) => mis
.iter()
// We don't use all() here, because we want to evaluate all cfg condition
// as eval_condition can (and does) extra checks
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
- sym::not => {
+ Some(sym::not) => {
let [mi] = mis.as_slice() else {
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
return false;
@@ -183,7 +168,7 @@ pub fn eval_condition(
!eval_condition(mi, sess, features, eval)
}
- sym::target => {
+ Some(sym::target) => {
if let Some(features) = features
&& !features.cfg_target_compact()
{
diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
index ad83a1f..ce42b050 100644
--- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
@@ -20,7 +20,7 @@ fn on_duplicate(cx: &crate::context::AcceptContext<'_>, first_span: rustc_span::
fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind> {
match args.name_value().and_then(|nv| nv.value_as_str()) {
Some(sym::transparent) => Some(Transparency::Transparent),
- Some(sym::semitransparent) => Some(Transparency::SemiTransparent),
+ Some(sym::semiopaque | sym::semitransparent) => Some(Transparency::SemiOpaque),
Some(sym::opaque) => Some(Transparency::Opaque),
Some(other) => {
cx.dcx().span_err(cx.attr_span, format!("unknown macro transparency: `{other}`"));
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index a68d457..972614a 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -222,7 +222,7 @@ pub fn parse_attribute_list<'a>(
// if we're only looking for a single attribute,
// skip all the ones we don't care about
if let Some(expected) = self.parse_only {
- if attr.name_or_empty() != expected {
+ if !attr.has_name(expected) {
continue;
}
}
@@ -232,7 +232,7 @@ pub fn parse_attribute_list<'a>(
// that's expanded right? But no, sometimes, when parsing attributes on macros,
// we already use the lowering logic and these are still there. So, when `omit_doc`
// is set we *also* want to ignore these
- if omit_doc == OmitDoc::Skip && attr.name_or_empty() == sym::doc {
+ if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
continue;
}
@@ -250,7 +250,7 @@ pub fn parse_attribute_list<'a>(
}))
}
// // FIXME: make doc attributes go through a proper attribute parser
- // ast::AttrKind::Normal(n) if n.name_or_empty() == sym::doc => {
+ // ast::AttrKind::Normal(n) if n.has_name(sym::doc) => {
// let p = GenericMetaItemParser::from_attr(&n, self.dcx());
//
// attributes.push(Attribute::Parsed(AttributeKind::DocComment {
@@ -320,7 +320,7 @@ fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Spa
ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(DelimArgs {
dspan: args.dspan,
delim: args.delim,
- tokens: args.tokens.flattened(),
+ tokens: args.tokens.clone(),
}),
// This is an inert key-value attribute - it will never be visible to macros
// after it gets lowered to HIR. Therefore, we can extract literals to handle
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs
index a746584..249e71e 100644
--- a/compiler/rustc_attr_parsing/src/lib.rs
+++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -77,7 +77,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(rust_logo)]
#![feature(let_chains)]
#![feature(rustdoc_internals)]
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index a8a1460..384fae5 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -485,25 +485,7 @@ fn next(&mut self) -> Option<MetaItemOrLitParser<'a>> {
}
// or a path.
- let path =
- if let Some(TokenTree::Token(Token { kind: token::Interpolated(_), span, .. }, _)) =
- self.inside_delimiters.peek()
- {
- self.inside_delimiters.next();
- // We go into this path if an expr ended up in an attribute that
- // expansion did not turn into a literal. Say, `#[repr(align(macro!()))]`
- // where the macro didn't expand to a literal. An error is already given
- // for this at this point, and then we do continue. This makes this path
- // reachable...
- let e = self.dcx.span_delayed_bug(
- *span,
- "expr in place where literal is expected (builtin attr parsing)",
- );
-
- return Some(MetaItemOrLitParser::Err(*span, e));
- } else {
- self.next_path()?
- };
+ let path = self.next_path()?;
// Paths can be followed by:
// - `(more meta items)` (another list)
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index 263f68d..b9ced81 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -77,6 +77,9 @@ pub(crate) fn categorize(context: PlaceContext) -> Option<DefUse> {
// Debug info is neither def nor use.
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
+ // Backwards incompatible drop hint is not a use, just a marker for linting.
+ PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint) => None,
+
PlaceContext::MutatingUse(MutatingUseContext::Deinit | MutatingUseContext::SetDiscriminant) => {
bug!("These statements are not allowed in this MIR phase")
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 8a8ecc3..cf73581 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -647,7 +647,7 @@ fn suggest_borrow_generic_arg(
&& tc.polarity() == ty::PredicatePolarity::Positive
&& supertrait_def_ids(tcx, tc.def_id())
.flat_map(|trait_did| tcx.associated_items(trait_did).in_definition_order())
- .any(|item| item.fn_has_self_parameter)
+ .any(|item| item.is_method())
})
}) {
return None;
@@ -2959,21 +2959,27 @@ fn report_local_value_does_not_live_long_enough(
}
}
- let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{name}`"));
+ let name = if borrow_span.in_external_macro(self.infcx.tcx.sess.source_map()) {
+ // Don't name local variables in external macros.
+ "value".to_string()
+ } else {
+ format!("`{name}`")
+ };
+
+ let mut err = self.path_does_not_live_long_enough(borrow_span, &name);
if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
let region_name = annotation.emit(self, &mut err);
err.span_label(
borrow_span,
- format!("`{name}` would have to be valid for `{region_name}`..."),
+ format!("{name} would have to be valid for `{region_name}`..."),
);
err.span_label(
drop_span,
format!(
- "...but `{}` will be dropped here, when the {} returns",
- name,
+ "...but {name} will be dropped here, when the {} returns",
self.infcx
.tcx
.opt_item_name(self.mir_def_id().to_def_id())
@@ -3011,7 +3017,7 @@ fn report_local_value_does_not_live_long_enough(
}
} else {
err.span_label(borrow_span, "borrowed value does not live long enough");
- err.span_label(drop_span, format!("`{name}` dropped here while still borrowed"));
+ err.span_label(drop_span, format!("{name} dropped here while still borrowed"));
borrow_spans.args_subdiag(&mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture {
@@ -3376,10 +3382,15 @@ fn report_escaping_closure_capture(
let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) {
Ok(string) => {
- let coro_prefix = if string.starts_with("async") {
- // `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize`
- // to `u32`.
- Some(5)
+ let coro_prefix = if let Some(sub) = string.strip_prefix("async") {
+ let trimmed_sub = sub.trim_end();
+ if trimmed_sub.ends_with("gen") {
+ // `async` is 5 chars long.
+ Some((trimmed_sub.len() + 5) as _)
+ } else {
+ // `async` is 5 chars long.
+ Some(5)
+ }
} else if string.starts_with("gen") {
// `gen` is 3 chars long
Some(3)
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index f77dda0..a845431 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -95,7 +95,9 @@ pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
&& let hir::def::Res::Local(hir_id) = p.res
&& let hir::Node::Pat(pat) = tcx.hir_node(hir_id)
{
- err.span_label(pat.span, format!("binding `{ident}` declared here"));
+ if !ident.span.in_external_macro(tcx.sess.source_map()) {
+ err.span_label(pat.span, format!("binding `{ident}` declared here"));
+ }
}
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 8d530b5..4423edb 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -888,7 +888,7 @@ fn add_static_impl_trait_suggestion(
// Skip `async` desugaring `impl Future`.
}
if let TyKind::TraitObject(_, lt) = alias_ty.kind {
- if lt.res == hir::LifetimeName::ImplicitObjectLifetimeDefault {
+ if lt.kind == hir::LifetimeKind::ImplicitObjectLifetimeDefault {
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
} else {
spans_suggs.push((lt.ident.span, "'a".to_string()));
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 64ad1c9..3b66142 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2,7 +2,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
@@ -22,6 +21,7 @@
use std::marker::PhantomData;
use std::ops::{ControlFlow, Deref};
+use borrow_set::LocalsStateAtExit;
use root_cx::BorrowCheckRootCtxt;
use rustc_abi::FieldIdx;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -304,33 +304,13 @@ fn do_mir_borrowck<'tcx>(
root_cx.set_tainted_by_errors(e);
}
- let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
- for var_debug_info in &input_body.var_debug_info {
- if let VarDebugInfoContents::Place(place) = var_debug_info.value {
- if let Some(local) = place.as_local() {
- if let Some(prev_name) = local_names[local]
- && var_debug_info.name != prev_name
- {
- span_bug!(
- var_debug_info.source_info.span,
- "local {:?} has many names (`{}` vs `{}`)",
- local,
- prev_name,
- var_debug_info.name
- );
- }
- local_names[local] = Some(var_debug_info.name);
- }
- }
- }
-
// Replace all regions with fresh inference variables. This
// requires first making our own copy of the MIR. This copy will
// be modified (in place) to contain non-lexical lifetimes. It
// will have a lifetime tied to the inference context.
let mut body_owned = input_body.clone();
let mut promoted = input_promoted.to_owned();
- let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
+ let universal_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
let body = &body_owned; // no further changes
let location_table = PoloniusLocationTable::new(body);
@@ -355,7 +335,7 @@ fn do_mir_borrowck<'tcx>(
} = nll::compute_regions(
root_cx,
&infcx,
- free_regions,
+ universal_regions,
body,
&promoted,
&location_table,
@@ -368,24 +348,23 @@ fn do_mir_borrowck<'tcx>(
// Dump MIR results into a file, if that is enabled. This lets us
// write unit-tests, as well as helping with debugging.
nll::dump_nll_mir(&infcx, body, ®ioncx, &opt_closure_req, &borrow_set);
+ polonius::dump_polonius_mir(
+ &infcx,
+ body,
+ ®ioncx,
+ &opt_closure_req,
+ &borrow_set,
+ polonius_diagnostics.as_ref(),
+ );
// We also have a `#[rustc_regions]` annotation that causes us to dump
// information.
+ nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req);
+
+ let movable_coroutine = body.coroutine.is_some()
+ && tcx.coroutine_movability(def.to_def_id()) == hir::Movability::Movable;
+
let diags_buffer = &mut BorrowckDiagnosticsBuffer::default();
- nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, diags_buffer);
-
- let movable_coroutine =
- // The first argument is the coroutine type passed by value
- if let Some(local) = body.local_decls.raw.get(1)
- // Get the interior types and args which typeck computed
- && let ty::Coroutine(def_id, _) = *local.ty.kind()
- && tcx.coroutine_movability(def_id) == hir::Movability::Movable
-{
- true
-} else {
- false
-};
-
// While promoteds should mostly be correct by construction, we need to check them for
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
for promoted_body in &promoted {
@@ -403,7 +382,6 @@ fn do_mir_borrowck<'tcx>(
location_table: &location_table,
movable_coroutine,
fn_self_span_reported: Default::default(),
- locals_are_invalidated_at_exit,
access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(),
uninitialized_error_reported: Default::default(),
@@ -435,6 +413,26 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
promoted_mbcx.report_move_errors();
}
+ let mut local_names = IndexVec::from_elem(None, &body.local_decls);
+ for var_debug_info in &body.var_debug_info {
+ if let VarDebugInfoContents::Place(place) = var_debug_info.value {
+ if let Some(local) = place.as_local() {
+ if let Some(prev_name) = local_names[local]
+ && var_debug_info.name != prev_name
+ {
+ span_bug!(
+ var_debug_info.source_info.span,
+ "local {:?} has many names (`{}` vs `{}`)",
+ local,
+ prev_name,
+ var_debug_info.name
+ );
+ }
+ local_names[local] = Some(var_debug_info.name);
+ }
+ }
+ }
+
let mut mbcx = MirBorrowckCtxt {
root_cx,
infcx: &infcx,
@@ -442,7 +440,6 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
move_data: &move_data,
location_table: &location_table,
movable_coroutine,
- locals_are_invalidated_at_exit,
fn_self_span_reported: Default::default(),
access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(),
@@ -455,9 +452,9 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
local_names,
region_names: RefCell::default(),
next_region_name: RefCell::new(1),
- polonius_output,
move_errors: Vec::new(),
diags_buffer,
+ polonius_output: polonius_output.as_deref(),
polonius_diagnostics: polonius_diagnostics.as_ref(),
};
@@ -474,16 +471,6 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
mbcx.report_move_errors();
- // If requested, dump polonius MIR.
- polonius::dump_polonius_mir(
- &infcx,
- body,
- ®ioncx,
- &borrow_set,
- polonius_diagnostics.as_ref(),
- &opt_closure_req,
- );
-
// For each non-user used mutable variable, check if it's been assigned from
// a user-declared local. If so, then put that local into the used_mut set.
// Note that this set is expected to be small - only upvars from closures
@@ -514,7 +501,6 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
};
let body_with_facts = if consumer_options.is_some() {
- let output_facts = mbcx.polonius_output;
Some(Box::new(BodyWithBorrowckFacts {
body: body_owned,
promoted,
@@ -522,7 +508,7 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
region_inference_context: regioncx,
location_table: polonius_input.as_ref().map(|_| location_table),
input_facts: polonius_input,
- output_facts,
+ output_facts: polonius_output,
}))
} else {
None
@@ -655,13 +641,6 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
location_table: &'a PoloniusLocationTable,
movable_coroutine: bool,
- /// This keeps track of whether local variables are free-ed when the function
- /// exits even without a `StorageDead`, which appears to be the case for
- /// constants.
- ///
- /// I'm not sure this is the right approach - @eddyb could you try and
- /// figure this out?
- locals_are_invalidated_at_exit: bool,
/// This field keeps track of when borrow errors are reported in the access_place function
/// so that there is no duplicate reporting. This field cannot also be used for the conflicting
/// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
@@ -709,12 +688,11 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
/// The counter for generating new region names.
next_region_name: RefCell<usize>,
- /// Results of Polonius analysis.
- polonius_output: Option<Box<PoloniusOutput>>,
-
diags_buffer: &'a mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
move_errors: Vec<MoveError<'tcx>>,
+ /// Results of Polonius analysis.
+ polonius_output: Option<&'a PoloniusOutput>,
/// When using `-Zpolonius=next`: the data used to compute errors and diagnostics.
polonius_diagnostics: Option<&'a PoloniusDiagnosticsContext>,
}
@@ -938,13 +916,20 @@ fn visit_after_primary_terminator_effect(
| TerminatorKind::Return
| TerminatorKind::TailCall { .. }
| TerminatorKind::CoroutineDrop => {
- // Returning from the function implicitly kills storage for all locals and statics.
- // Often, the storage will already have been killed by an explicit
- // StorageDead, but we don't always emit those (notably on unwind paths),
- // so this "extra check" serves as a kind of backup.
- for i in state.borrows.iter() {
- let borrow = &self.borrow_set[i];
- self.check_for_invalidation_at_exit(loc, borrow, span);
+ match self.borrow_set.locals_state_at_exit() {
+ LocalsStateAtExit::AllAreInvalidated => {
+ // Returning from the function implicitly kills storage for all locals and statics.
+ // Often, the storage will already have been killed by an explicit
+ // StorageDead, but we don't always emit those (notably on unwind paths),
+ // so this "extra check" serves as a kind of backup.
+ for i in state.borrows.iter() {
+ let borrow = &self.borrow_set[i];
+ self.check_for_invalidation_at_exit(loc, borrow, span);
+ }
+ }
+ // If we do not implicitly invalidate all locals on exit,
+ // we check for conflicts when dropping or moving this local.
+ LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved: _ } => {}
}
}
@@ -1301,7 +1286,7 @@ fn check_access_for_conflict(
error_reported
}
- /// Through #123739, backward incompatible drops (BIDs) are introduced.
+ /// Through #123739, `BackwardIncompatibleDropHint`s (BIDs) are introduced.
/// We would like to emit lints whether borrow checking fails at these future drop locations.
#[instrument(level = "debug", skip(self, state))]
fn check_backward_incompatible_drop(
@@ -1716,22 +1701,15 @@ fn check_for_invalidation_at_exit(
// we'll have a memory leak) and assume that all statics have a destructor.
//
// FIXME: allow thread-locals to borrow other thread locals?
-
- let (might_be_alive, will_be_dropped) =
- if self.body.local_decls[root_place.local].is_ref_to_thread_local() {
- // Thread-locals might be dropped after the function exits
- // We have to dereference the outer reference because
- // borrows don't conflict behind shared references.
- root_place.projection = TyCtxtConsts::DEREF_PROJECTION;
- (true, true)
- } else {
- (false, self.locals_are_invalidated_at_exit)
- };
-
- if !will_be_dropped {
- debug!("place_is_invalidated_at_exit({:?}) - won't be dropped", place);
- return;
- }
+ let might_be_alive = if self.body.local_decls[root_place.local].is_ref_to_thread_local() {
+ // Thread-locals might be dropped after the function exits
+ // We have to dereference the outer reference because
+ // borrows don't conflict behind shared references.
+ root_place.projection = TyCtxtConsts::DEREF_PROJECTION;
+ true
+ } else {
+ false
+ };
let sd = if might_be_alive { Deep } else { Shallow(None) };
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 8a2a34f..fe899bb 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -21,7 +21,7 @@
use crate::borrow_set::BorrowSet;
use crate::consumers::ConsumerOptions;
-use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors};
+use crate::diagnostics::RegionErrors;
use crate::polonius::PoloniusDiagnosticsContext;
use crate::polonius::legacy::{
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
@@ -117,11 +117,6 @@ pub(crate) fn compute_regions<'a, 'tcx>(
Rc::clone(&location_map),
);
- // Create the region inference context, taking ownership of the
- // region inference data that was contained in `infcx`, and the
- // base constraints generated by the type-check.
- let var_infos = infcx.get_region_var_infos();
-
// If requested, emit legacy polonius facts.
polonius::legacy::emit_facts(
&mut polonius_facts,
@@ -134,13 +129,8 @@ pub(crate) fn compute_regions<'a, 'tcx>(
&constraints,
);
- let mut regioncx = RegionInferenceContext::new(
- infcx,
- var_infos,
- constraints,
- universal_region_relations,
- location_map,
- );
+ let mut regioncx =
+ RegionInferenceContext::new(infcx, constraints, universal_region_relations, location_map);
// If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives constraints
// and use them to compute loan liveness.
@@ -297,7 +287,6 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
- diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
) {
let tcx = infcx.tcx;
let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
@@ -335,13 +324,11 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
} else {
let mut err = infcx.dcx().struct_span_note(def_span, "no external requirements");
regioncx.annotate(tcx, &mut err);
-
err
};
// FIXME(@lcnr): We currently don't dump the inferred hidden types here.
-
- diagnostics_buffer.buffer_non_error(err);
+ err.emit();
}
fn for_each_region_constraint<'tcx>(
diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs
index eb53a98..6a943e1 100644
--- a/compiler/rustc_borrowck/src/polonius/dump.rs
+++ b/compiler/rustc_borrowck/src/polonius/dump.rs
@@ -24,9 +24,9 @@ pub(crate) fn dump_polonius_mir<'tcx>(
infcx: &BorrowckInferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
+ closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
borrow_set: &BorrowSet<'tcx>,
polonius_diagnostics: Option<&PoloniusDiagnosticsContext>,
- closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
) {
let tcx = infcx.tcx;
if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 569c46e..f8af9e5 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -9,7 +9,7 @@
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_index::IndexVec;
use rustc_infer::infer::outlives::test_type_match;
-use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
+use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound, VerifyIfEq};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::bug;
use rustc_middle::mir::{
@@ -145,7 +145,7 @@ pub struct RegionInferenceContext<'tcx> {
/// variables are identified by their index (`RegionVid`). The
/// definition contains information about where the region came
/// from as well as its final inferred value.
- pub(crate) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
+ pub(crate) definitions: Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>>,
/// The liveness constraints added to each region. For most
/// regions, these start out empty and steadily grow, though for
@@ -338,8 +338,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
let num_components = sccs.num_sccs();
let mut components = vec![FxIndexSet::default(); num_components];
- for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() {
- let reg_var = ty::RegionVid::from_usize(reg_var_idx);
+ for (reg_var, scc_idx) in sccs.scc_indices().iter_enumerated() {
let origin = var_to_origin.get(®_var).unwrap_or(&RegionCtxt::Unknown);
components[scc_idx.as_usize()].insert((reg_var, *origin));
}
@@ -385,6 +384,26 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
debug!("SCC edges {:#?}", scc_node_to_edges);
}
+fn create_definitions<'tcx>(
+ infcx: &BorrowckInferCtxt<'tcx>,
+ universal_regions: &UniversalRegions<'tcx>,
+) -> Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>> {
+ // Create a RegionDefinition for each inference variable.
+ let mut definitions: IndexVec<_, _> = infcx
+ .get_region_var_infos()
+ .iter()
+ .map(|info| RegionDefinition::new(info.universe, info.origin))
+ .collect();
+
+ // Add the external name for all universal regions.
+ for (external_name, variable) in universal_regions.named_universal_regions_iter() {
+ debug!("region {variable:?} has external name {external_name:?}");
+ definitions[variable].external_name = Some(external_name);
+ }
+
+ Frozen::freeze(definitions)
+}
+
impl<'tcx> RegionInferenceContext<'tcx> {
/// Creates a new region inference context with a total of
/// `num_region_variables` valid inference variables; the first N
@@ -395,7 +414,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// of constraints produced by the MIR type check.
pub(crate) fn new(
infcx: &BorrowckInferCtxt<'tcx>,
- var_infos: VarInfos,
constraints: MirTypeckRegionConstraints<'tcx>,
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
location_map: Rc<DenseLocationMap>,
@@ -426,11 +444,7 @@ pub(crate) fn new(
infcx.set_tainted_by_errors(guar);
}
- // Create a RegionDefinition for each inference variable.
- let definitions: IndexVec<_, _> = var_infos
- .iter()
- .map(|info| RegionDefinition::new(info.universe, info.origin))
- .collect();
+ let definitions = create_definitions(infcx, &universal_regions);
let constraint_sccs =
outlives_constraints.add_outlives_static(&universal_regions, &definitions);
@@ -526,18 +540,6 @@ pub(crate) fn new(
/// means that the `R1: !1` constraint here will cause
/// `R1` to become `'static`.
fn init_free_and_bound_regions(&mut self) {
- // Update the names (if any)
- // This iterator has unstable order but we collect it all into an IndexVec
- for (external_name, variable) in
- self.universal_region_relations.universal_regions.named_universal_regions_iter()
- {
- debug!(
- "init_free_and_bound_regions: region {:?} has external name {:?}",
- variable, external_name
- );
- self.definitions[variable].external_name = Some(external_name);
- }
-
for variable in self.definitions.indices() {
let scc = self.constraint_sccs.scc(variable);
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index ccb257a..5751656 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -21,7 +21,6 @@
pub(crate) struct ConstraintConversion<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
- tcx: TyCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
/// Each RBP `GK: 'a` is assumed to be true. These encode
/// relationships like `T: 'a` that are added via implicit bounds
@@ -34,7 +33,6 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
/// logic expecting to see (e.g.) `ReStatic`, and if we supplied
/// our special inference variable there, we would mess that up.
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
- implicit_region_bound: ty::Region<'tcx>,
param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
locations: Locations,
@@ -49,7 +47,6 @@ pub(crate) fn new(
infcx: &'a InferCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
- implicit_region_bound: ty::Region<'tcx>,
param_env: ty::ParamEnv<'tcx>,
known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
locations: Locations,
@@ -59,10 +56,8 @@ pub(crate) fn new(
) -> Self {
Self {
infcx,
- tcx: infcx.tcx,
universal_regions,
region_bound_pairs,
- implicit_region_bound,
param_env,
known_type_outlives_obligations,
locations,
@@ -96,7 +91,7 @@ pub(crate) fn apply_closure_requirements(
// into a vector. These are the regions that we will be
// relating to one another.
let closure_mapping = &UniversalRegions::closure_mapping(
- self.tcx,
+ self.infcx.tcx,
closure_args,
closure_requirements.num_external_vids,
closure_def_id,
@@ -111,7 +106,7 @@ pub(crate) fn apply_closure_requirements(
let subject = match outlives_requirement.subject {
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
ClosureOutlivesSubject::Ty(subject_ty) => {
- subject_ty.instantiate(self.tcx, |vid| closure_mapping[vid]).into()
+ subject_ty.instantiate(self.infcx.tcx, |vid| closure_mapping[vid]).into()
}
};
@@ -127,14 +122,14 @@ fn convert(
predicate: ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
constraint_category: ConstraintCategory<'tcx>,
) {
+ let tcx = self.infcx.tcx;
debug!("generate: constraints at: {:#?}", self.locations);
// Extract out various useful fields we'll need below.
let ConstraintConversion {
- tcx,
infcx,
+ universal_regions,
region_bound_pairs,
- implicit_region_bound,
known_type_outlives_obligations,
..
} = *self;
@@ -145,7 +140,7 @@ fn convert(
break;
}
- if !self.tcx.recursion_limit().value_within_limit(iteration) {
+ if !tcx.recursion_limit().value_within_limit(iteration) {
bug!(
"FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}"
);
@@ -170,10 +165,11 @@ fn convert(
);
}
+ let implicit_region_bound =
+ ty::Region::new_var(tcx, universal_regions.implicit_region_bound());
// we don't actually use this for anything, but
// the `TypeOutlives` code needs an origin.
let origin = infer::RelateParamBound(self.span, t1, None);
-
TypeOutlives::new(
&mut *self,
tcx,
@@ -205,7 +201,7 @@ fn convert(
/// are dealt with during trait solving.
fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
if value.has_placeholders() {
- fold_regions(self.tcx, value, |r, _| match r.kind() {
+ fold_regions(self.infcx.tcx, value, |r, _| match r.kind() {
ty::RePlaceholder(placeholder) => {
self.constraints.placeholder_region(self.infcx, placeholder)
}
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index eaac633..536a277 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -49,14 +49,12 @@ pub(crate) struct CreateResult<'tcx> {
pub(crate) fn create<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- implicit_region_bound: ty::Region<'tcx>,
universal_regions: UniversalRegions<'tcx>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
) -> CreateResult<'tcx> {
UniversalRegionRelationsBuilder {
infcx,
param_env,
- implicit_region_bound,
constraints,
universal_regions,
region_bound_pairs: Default::default(),
@@ -181,7 +179,6 @@ struct UniversalRegionRelationsBuilder<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
universal_regions: UniversalRegions<'tcx>,
- implicit_region_bound: ty::Region<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
// outputs:
@@ -320,7 +317,6 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
self.infcx,
&self.universal_regions,
&self.region_bound_pairs,
- self.implicit_region_bound,
param_env,
&known_type_outlives_obligations,
Locations::All(span),
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index a17dff5..3c00b81 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -113,7 +113,6 @@ pub(crate) fn type_check<'a, 'tcx>(
move_data: &MoveData<'tcx>,
location_map: Rc<DenseLocationMap>,
) -> MirTypeckResults<'tcx> {
- let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
@@ -129,13 +128,7 @@ pub(crate) fn type_check<'a, 'tcx>(
region_bound_pairs,
normalized_inputs_and_output,
known_type_outlives_obligations,
- } = free_region_relations::create(
- infcx,
- infcx.param_env,
- implicit_region_bound,
- universal_regions,
- &mut constraints,
- );
+ } = free_region_relations::create(infcx, infcx.param_env, universal_regions, &mut constraints);
let pre_obligations = infcx.take_registered_region_obligations();
assert!(
@@ -160,7 +153,6 @@ pub(crate) fn type_check<'a, 'tcx>(
user_type_annotations: &body.user_type_annotations,
region_bound_pairs,
known_type_outlives_obligations,
- implicit_region_bound,
reported_errors: Default::default(),
universal_regions: &universal_region_relations.universal_regions,
location_table,
@@ -226,7 +218,6 @@ struct TypeChecker<'a, 'tcx> {
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
region_bound_pairs: RegionBoundPairs<'tcx>,
known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
- implicit_region_bound: ty::Region<'tcx>,
reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
universal_regions: &'a UniversalRegions<'tcx>,
location_table: &'a PoloniusLocationTable,
@@ -422,7 +413,6 @@ fn push_region_constraints(
self.infcx,
self.universal_regions,
&self.region_bound_pairs,
- self.implicit_region_bound,
self.infcx.param_env,
&self.known_type_outlives_obligations,
locations,
@@ -1567,11 +1557,15 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
}
}
CastKind::Transmute => {
- span_mirbug!(
- self,
- rvalue,
- "Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
- );
+ let ty_from = op.ty(self.body, tcx);
+ match ty_from.kind() {
+ ty::Pat(base, _) if base == ty => {}
+ _ => span_mirbug!(
+ self,
+ rvalue,
+ "Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
+ ),
+ }
}
}
}
@@ -2507,7 +2501,6 @@ fn prove_closure_bounds(
self.infcx,
self.universal_regions,
&self.region_bound_pairs,
- self.implicit_region_bound,
self.infcx.param_env,
&self.known_type_outlives_obligations,
locations,
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 5c57ab9..c11e14d 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -438,6 +438,10 @@ pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
}
}
+ pub(crate) fn implicit_region_bound(&self) -> RegionVid {
+ self.fr_fn_body
+ }
+
pub(crate) fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
self.indices.tainted_by_errors.get()
}
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 603dc90..5316e90 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -231,8 +231,6 @@
builtin_macros_format_use_positional = consider using a positional formatting argument instead
-builtin_macros_invalid_crate_attribute = invalid crate attribute
-
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
.note = only one `#[default]` attribute is needed
.label = `#[default]` used here
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 4161829..daebd51 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -799,8 +799,19 @@ fn gen_enzyme_decl(
d_inputs.push(shadow_arg.clone());
}
}
- DiffActivity::Dual | DiffActivity::DualOnly => {
- for i in 0..x.width {
+ DiffActivity::Dual
+ | DiffActivity::DualOnly
+ | DiffActivity::Dualv
+ | DiffActivity::DualvOnly => {
+ // the *v variants get lowered to enzyme_dupv and enzyme_dupnoneedv, which cause
+ // Enzyme to not expect N arguments, but one argument (which is instead larger).
+ let iterations =
+ if matches!(activity, DiffActivity::Dualv | DiffActivity::DualvOnly) {
+ 1
+ } else {
+ x.width
+ };
+ for i in 0..iterations {
let mut shadow_arg = arg.clone();
let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind {
ident.name
@@ -823,7 +834,7 @@ fn gen_enzyme_decl(
DiffActivity::Const => {
// Nothing to do here.
}
- DiffActivity::None | DiffActivity::FakeActivitySize => {
+ DiffActivity::None | DiffActivity::FakeActivitySize(_) => {
panic!("Should not happen");
}
}
@@ -887,8 +898,8 @@ fn gen_enzyme_decl(
}
};
- if let DiffActivity::Dual = x.ret_activity {
- let kind = if x.width == 1 {
+ if matches!(x.ret_activity, DiffActivity::Dual | DiffActivity::Dualv) {
+ let kind = if x.width == 1 || matches!(x.ret_activity, DiffActivity::Dualv) {
// Dual can only be used for f32/f64 ret.
// In that case we return now a tuple with two floats.
TyKind::Tup(thin_vec![ty.clone(), ty.clone()])
@@ -903,7 +914,7 @@ fn gen_enzyme_decl(
let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
d_decl.output = FnRetTy::Ty(ty);
}
- if let DiffActivity::DualOnly = x.ret_activity {
+ if matches!(x.ret_activity, DiffActivity::DualOnly | DiffActivity::DualvOnly) {
// No need to change the return type,
// we will just return the shadow in place of the primal return.
// However, if we have a width > 1, then we don't return -> T, but -> [T; width]
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index b3ba907..da01e3e 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -92,11 +92,7 @@ fn configure_annotatable(mut self, annotatable: Annotatable) -> Annotatable {
// the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
// process is lossless, so this process is invisible to proc-macros.
- // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`)
- // to `None`-delimited groups containing the corresponding tokens. This
- // is normally delayed until the proc-macro server actually needs to
- // provide a `TokenKind::Interpolated` to a proc-macro. We do this earlier,
- // so that we can handle cases like:
+ // Interesting cases:
//
// ```rust
// #[cfg_eval] #[cfg] $item
@@ -104,8 +100,8 @@ fn configure_annotatable(mut self, annotatable: Annotatable) -> Annotatable {
//
// where `$item` is `#[cfg_attr] struct Foo {}`. We want to make
// sure to evaluate *all* `#[cfg]` and `#[cfg_attr]` attributes - the simplest
- // way to do this is to do a single parse of a stream without any nonterminals.
- let orig_tokens = annotatable.to_tokens().flattened();
+ // way to do this is to do a single parse of the token stream.
+ let orig_tokens = annotatable.to_tokens();
// Re-parse the tokens, setting the `capture_cfg` flag to save extra information
// to the captured `AttrTokenStream` (specifically, we capture
diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
index 6afd8c4..423b6a1 100644
--- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
+++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
@@ -1,44 +1,37 @@
//! Attributes injected into the crate root from command line using `-Z crate-attr`.
-use rustc_ast::attr::mk_attr;
-use rustc_ast::{self as ast, AttrItem, AttrStyle, token};
-use rustc_parse::parser::ForceCollect;
-use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
+use rustc_ast::{self as ast};
+use rustc_errors::Diag;
+use rustc_parse::parser::attr::InnerAttrPolicy;
+use rustc_parse::{parse_in, source_str_to_stream};
use rustc_session::parse::ParseSess;
use rustc_span::FileName;
-use crate::errors;
-
pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
for raw_attr in attrs {
- let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str(
- psess,
- FileName::cli_crate_attr_source_code(raw_attr),
- raw_attr.clone(),
- ));
-
- let start_span = parser.token.span;
- let AttrItem { unsafety, path, args, tokens: _ } =
- match parser.parse_attr_item(ForceCollect::No) {
- Ok(ai) => ai,
- Err(err) => {
+ let source = format!("#![{raw_attr}]");
+ let parse = || -> Result<ast::Attribute, Vec<Diag<'_>>> {
+ let tokens = source_str_to_stream(
+ psess,
+ FileName::cli_crate_attr_source_code(raw_attr),
+ source,
+ None,
+ )?;
+ parse_in(psess, tokens, "<crate attribute>", |p| {
+ p.parse_attribute(InnerAttrPolicy::Permitted)
+ })
+ .map_err(|e| vec![e])
+ };
+ let meta = match parse() {
+ Ok(meta) => meta,
+ Err(errs) => {
+ for err in errs {
err.emit();
- continue;
}
- };
- let end_span = parser.token.span;
- if parser.token != token::Eof {
- psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
- continue;
- }
+ continue;
+ }
+ };
- krate.attrs.push(mk_attr(
- &psess.attr_id_generator,
- AttrStyle::Inner,
- unsafety,
- path,
- args,
- start_span.to(end_span),
- ));
+ krate.attrs.push(meta);
}
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index b9197be..d9aac54 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -527,15 +527,14 @@ pub(crate) fn expand_ext(
item.attrs
.iter()
.filter(|a| {
- [
+ a.has_any_name(&[
sym::allow,
sym::warn,
sym::deny,
sym::forbid,
sym::stable,
sym::unstable,
- ]
- .contains(&a.name_or_empty())
+ ])
})
.cloned(),
);
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 4bbe212..d14ad8f 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -1,7 +1,7 @@
use rustc_errors::codes::*;
use rustc_errors::{
Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans,
- SubdiagMessageOp, Subdiagnostic,
+ Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Ident, Span, Symbol};
@@ -110,13 +110,6 @@ pub(crate) struct ProcMacro {
}
#[derive(Diagnostic)]
-#[diag(builtin_macros_invalid_crate_attribute)]
-pub(crate) struct InvalidCrateAttr {
- #[primary_span]
- pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(builtin_macros_non_abi)]
pub(crate) struct NonABI {
#[primary_span]
@@ -691,13 +684,9 @@ pub(crate) struct FormatUnusedArg {
// Allow the singular form to be a subdiagnostic of the multiple-unused
// form of diagnostic.
impl Subdiagnostic for FormatUnusedArg {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("named", self.named);
- let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
+ let msg = diag.eagerly_translate(crate::fluent_generated::builtin_macros_format_unused_arg);
diag.span_label(self.span, msg);
}
}
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 606e855..bcd40f9 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -5,7 +5,6 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 444dc44..00136ac 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -169,8 +169,11 @@ fn produce_final_output_artifacts(
if codegen_results.modules.len() == 1 {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
- let module_name = Some(&codegen_results.modules[0].name[..]);
- let path = crate_output.temp_path(output_type, module_name);
+ let path = crate_output.temp_path_for_cgu(
+ output_type,
+ &codegen_results.modules[0].name,
+ sess.invocation_temp.as_deref(),
+ );
let output = crate_output.path(output_type);
if !output_type.is_text_output() && output.is_tty() {
sess.dcx()
@@ -183,22 +186,16 @@ fn produce_final_output_artifacts(
ensure_removed(sess.dcx(), &path);
}
} else {
- let extension = crate_output
- .temp_path(output_type, None)
- .extension()
- .unwrap()
- .to_str()
- .unwrap()
- .to_owned();
-
if crate_output.outputs.contains_explicit_name(&output_type) {
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
// no good solution for this case, so warn the user.
- sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension });
+ sess.dcx()
+ .emit_warn(ssa_errors::IgnoringEmitPath { extension: output_type.extension() });
} else if crate_output.single_output_file.is_some() {
// 3) Multiple codegen units, with `-o some_name`. We have
// no good solution for this case, so warn the user.
- sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension });
+ sess.dcx()
+ .emit_warn(ssa_errors::IgnoringOutput { extension: output_type.extension() });
} else {
// 4) Multiple codegen units, but no explicit name. We
// just leave the `foo.0.x` files in place.
@@ -351,6 +348,7 @@ fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
fn emit_cgu(
output_filenames: &OutputFilenames,
+ invocation_temp: Option<&str>,
prof: &SelfProfilerRef,
name: String,
module: UnwindModule<ObjectModule>,
@@ -366,6 +364,7 @@ fn emit_cgu(
let module_regular = emit_module(
output_filenames,
+ invocation_temp,
prof,
product.object,
ModuleKind::Regular,
@@ -391,6 +390,7 @@ fn emit_cgu(
fn emit_module(
output_filenames: &OutputFilenames,
+ invocation_temp: Option<&str>,
prof: &SelfProfilerRef,
mut object: cranelift_object::object::write::Object<'_>,
kind: ModuleKind,
@@ -409,7 +409,7 @@ fn emit_module(
object.set_section_data(comment_section, producer, 1);
}
- let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name));
+ let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name, invocation_temp);
let file = match File::create(&tmp_file) {
Ok(file) => file,
Err(err) => return Err(format!("error creating object file: {}", err)),
@@ -449,8 +449,11 @@ fn reuse_workproduct_for_cgu(
cgu: &CodegenUnit<'_>,
) -> Result<ModuleCodegenResult, String> {
let work_product = cgu.previous_work_product(tcx);
- let obj_out_regular =
- tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str()));
+ let obj_out_regular = tcx.output_filenames(()).temp_path_for_cgu(
+ OutputType::Object,
+ cgu.name().as_str(),
+ tcx.sess.invocation_temp.as_deref(),
+ );
let source_file_regular = rustc_incremental::in_incr_comp_dir_sess(
&tcx.sess,
&work_product.saved_files.get("o").expect("no saved object file in work product"),
@@ -595,13 +598,19 @@ fn module_codegen(
let global_asm_object_file =
profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| {
- crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)
+ crate::global_asm::compile_global_asm(
+ &global_asm_config,
+ &cgu_name,
+ &cx.global_asm,
+ cx.invocation_temp.as_deref(),
+ )
})?;
let codegen_result =
profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| {
emit_cgu(
&global_asm_config.output_filenames,
+ cx.invocation_temp.as_deref(),
&profiler,
cgu_name,
module,
@@ -626,8 +635,11 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled
.as_str()
.to_string();
- let tmp_file =
- tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
+ let tmp_file = tcx.output_filenames(()).temp_path_for_cgu(
+ OutputType::Metadata,
+ &metadata_cgu_name,
+ tcx.sess.invocation_temp.as_deref(),
+ );
let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx);
let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name);
@@ -657,6 +669,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
match emit_module(
tcx.output_filenames(()),
+ tcx.sess.invocation_temp.as_deref(),
&tcx.sess.prof,
product.object,
ModuleKind::Allocator,
@@ -728,26 +741,27 @@ pub(crate) fn run_aot(
let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(todo_cgus.len()));
- let modules = tcx.sess.time("codegen mono items", || {
- let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| {
- let dep_node = cgu.codegen_dep_node(tcx);
- tcx.dep_graph
- .with_task(
+ let modules: Vec<_> =
+ tcx.sess.time("codegen mono items", || {
+ let modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| {
+ let dep_node = cgu.codegen_dep_node(tcx);
+ let (module, _) = tcx.dep_graph.with_task(
dep_node,
tcx,
(global_asm_config.clone(), cgu.name(), concurrency_limiter.acquire(tcx.dcx())),
module_codegen,
Some(rustc_middle::dep_graph::hash_result),
- )
- .0
- });
- modules.extend(
- done_cgus
+ );
+ IntoDynSyncSend(module)
+ });
+ modules
.into_iter()
- .map(|(_, cgu)| OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))),
- );
- modules
- });
+ .map(|module| module.0)
+ .chain(done_cgus.into_iter().map(|(_, cgu)| {
+ OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))
+ }))
+ .collect()
+ });
let allocator_module = emit_allocator_module(tcx);
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 9ea92c3..79cefb0 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -132,6 +132,7 @@ pub(crate) fn compile_global_asm(
config: &GlobalAsmConfig,
cgu_name: &str,
global_asm: &str,
+ invocation_temp: Option<&str>,
) -> Result<Option<PathBuf>, String> {
if global_asm.is_empty() {
return Ok(None);
@@ -146,7 +147,7 @@ pub(crate) fn compile_global_asm(
global_asm.push('\n');
let global_asm_object_file = add_file_stem_postfix(
- config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)),
+ config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp),
".asm",
);
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index e7afaff..9d9e790 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -124,6 +124,7 @@ fn drop(&mut self) {
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
struct CodegenCx {
output_filenames: Arc<OutputFilenames>,
+ invocation_temp: Option<String>,
should_write_ir: bool,
global_asm: String,
inline_asm_index: usize,
@@ -142,6 +143,7 @@ fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, debug_info: bool, cgu_name: Symbol)
};
CodegenCx {
output_filenames: tcx.output_filenames(()).clone(),
+ invocation_temp: tcx.sess.invocation_temp.clone(),
should_write_ir: crate::pretty_clif::should_write_ir(tcx),
global_asm: String::new(),
inline_asm_index: 0,
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 3b48adb..6eef97c 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -1,6 +1,6 @@
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use rustc_hir::LangItem;
-use rustc_middle::ty::{AssocKind, GenericArg};
+use rustc_middle::ty::{AssocTag, GenericArg};
use rustc_session::config::EntryFnType;
use rustc_span::{DUMMY_SP, Ident};
@@ -107,7 +107,7 @@ fn create_entry_fn(
.find_by_ident_and_kind(
tcx,
Ident::from_str("report"),
- AssocKind::Fn,
+ AssocTag::Fn,
termination_trait,
)
.unwrap();
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
index f96912e..ef02425 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
@@ -1,8 +1,10 @@
name: CI
on:
- - push
- - pull_request
+ push:
+ branches:
+ - master
+ pull_request:
permissions:
contents: read
@@ -121,3 +123,22 @@
run: |
cd build_system
cargo test
+
+ # Summary job for the merge queue.
+ # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+ success:
+ needs: [build, duplicates, build_system]
+ # We need to ensure this job does *not* get skipped if its dependencies fail,
+ # because a skipped job is considered a success by GitHub. So we have to
+ # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
+ # when the workflow is canceled manually.
+ if: ${{ !cancelled() }}
+ runs-on: ubuntu-latest
+ steps:
+ # Manually check the status of all dependencies. `if: failure()` does not work.
+ - name: Conclusion
+ run: |
+ # Print the dependent jobs to see them in the CI log
+ jq -C <<< '${{ toJson(needs) }}'
+ # Check if all jobs that we depend on (in the needs array) were successful.
+ jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
index d080bbf..bc42eb1 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
@@ -2,7 +2,10 @@
name: Failures
on:
- - pull_request
+ push:
+ branches:
+ - master
+ pull_request:
permissions:
contents: read
@@ -108,3 +111,22 @@
echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!"
exit 1
fi
+
+ # Summary job for the merge queue.
+ # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+ success_failures:
+ needs: [build]
+ # We need to ensure this job does *not* get skipped if its dependencies fail,
+ # because a skipped job is considered a success by GitHub. So we have to
+ # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
+ # when the workflow is canceled manually.
+ if: ${{ !cancelled() }}
+ runs-on: ubuntu-latest
+ steps:
+ # Manually check the status of all dependencies. `if: failure()` does not work.
+ - name: Conclusion
+ run: |
+ # Print the dependent jobs to see them in the CI log
+ jq -C <<< '${{ toJson(needs) }}'
+ # Check if all jobs that we depend on (in the needs array) were successful.
+ jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
index bb9e020..da9a150 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
@@ -1,8 +1,10 @@
name: CI libgccjit 12
on:
- - push
- - pull_request
+ push:
+ branches:
+ - master
+ pull_request:
permissions:
contents: read
@@ -85,3 +87,22 @@
#- name: Run tests
#run: |
#./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
+
+ # Summary job for the merge queue.
+ # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+ success_gcc12:
+ needs: [build]
+ # We need to ensure this job does *not* get skipped if its dependencies fail,
+ # because a skipped job is considered a success by GitHub. So we have to
+ # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
+ # when the workflow is canceled manually.
+ if: ${{ !cancelled() }}
+ runs-on: ubuntu-latest
+ steps:
+ # Manually check the status of all dependencies. `if: failure()` does not work.
+ - name: Conclusion
+ run: |
+ # Print the dependent jobs to see them in the CI log
+ jq -C <<< '${{ toJson(needs) }}'
+ # Check if all jobs that we depend on (in the needs array) were successful.
+ jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
index ed1fc02..21731f7 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
@@ -3,8 +3,10 @@
name: m68k CI
on:
- - push
- - pull_request
+ push:
+ branches:
+ - master
+ pull_request:
permissions:
contents: read
@@ -105,3 +107,22 @@
- name: Run tests
run: |
./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
+
+ # Summary job for the merge queue.
+ # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+ success_m68k:
+ needs: [build]
+ # We need to ensure this job does *not* get skipped if its dependencies fail,
+ # because a skipped job is considered a success by GitHub. So we have to
+ # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
+ # when the workflow is canceled manually.
+ if: ${{ !cancelled() }}
+ runs-on: ubuntu-latest
+ steps:
+ # Manually check the status of all dependencies. `if: failure()` does not work.
+ - name: Conclusion
+ run: |
+ # Print the dependent jobs to see them in the CI log
+ jq -C <<< '${{ toJson(needs) }}'
+ # Check if all jobs that we depend on (in the needs array) were successful.
+ jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
index 886ce90..47a4028 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/release.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
@@ -1,8 +1,10 @@
name: CI with sysroot compiled in release mode
on:
- - push
- - pull_request
+ push:
+ branches:
+ - master
+ pull_request:
permissions:
contents: read
@@ -82,3 +84,22 @@
echo "Test is done with LTO enabled, hence inlining should occur across crates"
exit 1
fi
+
+ # Summary job for the merge queue.
+ # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+ success_release:
+ needs: [build]
+ # We need to ensure this job does *not* get skipped if its dependencies fail,
+ # because a skipped job is considered a success by GitHub. So we have to
+ # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
+ # when the workflow is canceled manually.
+ if: ${{ !cancelled() }}
+ runs-on: ubuntu-latest
+ steps:
+ # Manually check the status of all dependencies. `if: failure()` does not work.
+ - name: Conclusion
+ run: |
+ # Print the dependent jobs to see them in the CI log
+ jq -C <<< '${{ toJson(needs) }}'
+ # Check if all jobs that we depend on (in the needs array) were successful.
+ jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
index d5ae614..4b9f48e 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
@@ -1,8 +1,10 @@
name: stdarch tests with sysroot compiled in release mode
on:
- - push
- - pull_request
+ push:
+ branches:
+ - master
+ pull_request:
permissions:
contents: read
@@ -102,3 +104,22 @@
# TODO: remove --skip test_mm512_stream_ps when stdarch is updated in rustc.
# TODO: remove --skip test_tile_ when it's implemented.
STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features --cfg stdarch_intel_sde" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_mm512_stream_ps --skip test_tile_
+
+ # Summary job for the merge queue.
+ # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+ success_stdarch:
+ needs: [build]
+ # We need to ensure this job does *not* get skipped if its dependencies fail,
+ # because a skipped job is considered a success by GitHub. So we have to
+ # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
+ # when the workflow is canceled manually.
+ if: ${{ !cancelled() }}
+ runs-on: ubuntu-latest
+ steps:
+ # Manually check the status of all dependencies. `if: failure()` does not work.
+ - name: Conclusion
+ run: |
+ # Print the dependent jobs to see them in the CI log
+ jq -C <<< '${{ toJson(needs) }}'
+ # Check if all jobs that we depend on (in the needs array) were successful.
+ jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 636e75b..832603a 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -56,18 +56,18 @@
[[package]]
name = "gccjit"
-version = "2.4.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72fd91f4adbf02b53cfc73c97bc33c5f253009043f30c56a5ec08dd5c8094dc8"
+checksum = "2895ddec764de7ac76fe6c056050c4801a80109c066f177a00a9cc8dee02b29b"
dependencies = [
"gccjit_sys",
]
[[package]]
name = "gccjit_sys"
-version = "0.5.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fb7b8f48a75e2cfe78c3d9a980b32771c34ffd12d196021ab3f98c49fbd2f0d"
+checksum = "ac133db68db8a6a8b2c51ef4b18d8ea16682d5814c4641272fe37bbbc223d5f3"
dependencies = [
"libc",
]
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 63d3735..b50f2a6 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -22,7 +22,7 @@
default = ["master"]
[dependencies]
-gccjit = "2.4"
+gccjit = "2.5"
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
# Local copy.
diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md
index e92c16e..d0e4dbb 100644
--- a/compiler/rustc_codegen_gcc/Readme.md
+++ b/compiler/rustc_codegen_gcc/Readme.md
@@ -23,7 +23,7 @@
## Building
**This requires a patched libgccjit in order to work.
-You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.**
+You need to use my [fork of gcc](https://github.com/rust-lang/gcc) which already includes these patches.**
```bash
$ cp config.example.toml config.toml
@@ -40,7 +40,7 @@
To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue):
```bash
-$ git clone https://github.com/antoyo/gcc
+$ git clone https://github.com/rust-lang/gcc
$ sudo apt install flex libmpfr-dev libgmp-dev libmpc3 libmpc-dev
$ mkdir gcc-build gcc-install
$ cd gcc-build
diff --git a/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
index e28ee87..b49dd47 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
@@ -61,7 +61,7 @@ pub fn run() -> Result<(), String> {
return Ok(());
};
- let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?;
+ let result = git_clone("https://github.com/rust-lang/gcc", Some(&args.out_path), false)?;
if result.ran_clone {
let gcc_commit = args.config_info.get_gcc_commit()?;
println!("Checking out GCC commit `{}`...", gcc_commit);
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index 6c29c7d..df4ac85 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -529,20 +529,21 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> {
env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string());
- let extra =
- if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" };
-
- let rustc_args = &format!(
- r#"-Zpanic-abort-tests \
- -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \
- --sysroot "{sysroot_dir}" -Cpanic=abort{extra}"#,
+ let codegen_backend_path = format!(
+ "{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}",
pwd = std::env::current_dir()
.map_err(|error| format!("`current_dir` failed: {:?}", error))?
.display(),
channel = args.config_info.channel.as_str(),
dylib_ext = args.config_info.dylib_ext,
- sysroot_dir = args.config_info.sysroot_path,
- extra = extra,
+ );
+
+ let extra =
+ if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" };
+
+ let rustc_args = format!(
+ "-Zpanic-abort-tests -Zcodegen-backend={codegen_backend_path} --sysroot {} -Cpanic=abort{extra}",
+ args.config_info.sysroot_path
);
run_command_with_env(
@@ -677,7 +678,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
// FIXME: create a function "display_if_not_quiet" or something along the line.
println!("[TEST] libcore");
- let path = get_sysroot_dir().join("sysroot_src/library/core/tests");
+ let path = get_sysroot_dir().join("sysroot_src/library/coretests");
let _ = remove_dir_all(path.join("target"));
run_cargo_command(&[&"test"], Some(&path), env, args)?;
Ok(())
diff --git a/compiler/rustc_codegen_gcc/doc/add-attribute.md b/compiler/rustc_codegen_gcc/doc/add-attribute.md
index ae3bcc5..267c181 100644
--- a/compiler/rustc_codegen_gcc/doc/add-attribute.md
+++ b/compiler/rustc_codegen_gcc/doc/add-attribute.md
@@ -14,4 +14,4 @@
To test it, build `gcc`, run `cargo update -p gccjit` and then you can test the generated output for a given Rust crate.
-[gccjit.rs]: https://github.com/antoyo/gccjit.rs
+[gccjit.rs]: https://github.com/rust-lang/gccjit.rs
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 5544aee..c554a87 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -51,6 +51,10 @@ impl<T: ?Sized> LegacyReceiver for &T {}
impl<T: ?Sized> LegacyReceiver for &mut T {}
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
+#[lang = "receiver"]
+trait Receiver {
+}
+
#[lang = "copy"]
pub trait Copy {}
@@ -134,6 +138,14 @@ fn mul(self, rhs: Self) -> Self::Output {
}
}
+impl Mul for i32 {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self::Output {
+ self * rhs
+ }
+}
+
impl Mul for usize {
type Output = Self;
@@ -142,6 +154,14 @@ fn mul(self, rhs: Self) -> Self::Output {
}
}
+impl Mul for isize {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self::Output {
+ self * rhs
+ }
+}
+
#[lang = "add"]
pub trait Add<RHS = Self> {
type Output;
@@ -165,6 +185,14 @@ fn add(self, rhs: Self) -> Self {
}
}
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
impl Add for usize {
type Output = Self;
@@ -196,6 +224,14 @@ fn sub(self, rhs: Self) -> Self {
}
}
+impl Sub for isize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
impl Sub for u8 {
type Output = Self;
@@ -220,6 +256,14 @@ fn sub(self, rhs: Self) -> Self {
}
}
+impl Sub for i32 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
#[lang = "rem"]
pub trait Rem<RHS = Self> {
type Output;
@@ -628,6 +672,10 @@ pub mod libc {
pub fn memcpy(dst: *mut u8, src: *const u8, size: usize);
pub fn memmove(dst: *mut u8, src: *const u8, size: usize);
pub fn strncpy(dst: *mut u8, src: *const u8, size: usize);
+ pub fn fflush(stream: *mut i32) -> i32;
+ pub fn exit(status: i32);
+
+ pub static stdout: *mut i32;
}
}
diff --git a/compiler/rustc_codegen_gcc/libgccjit.version b/compiler/rustc_codegen_gcc/libgccjit.version
index 417fd5b..125b040 100644
--- a/compiler/rustc_codegen_gcc/libgccjit.version
+++ b/compiler/rustc_codegen_gcc/libgccjit.version
@@ -1 +1 @@
-e607be166673a8de9fc07f6f02c60426e556c5f2
+0ea98a1365b81f7488073512c850e8ee951a4afd
diff --git a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
deleted file mode 100644
index 70e3e2b..0000000
--- a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From af0e237f056fa838c77463381a19b0dc993c0a35 Mon Sep 17 00:00:00 2001
-From: None <none@example.com>
-Date: Sun, 1 Sep 2024 11:42:17 -0400
-Subject: [PATCH] Disable not compiling tests
-
----
- library/core/tests/Cargo.toml | 14 ++++++++++++++
- library/core/tests/lib.rs | 1 +
- 2 files changed, 15 insertions(+)
- create mode 100644 library/core/tests/Cargo.toml
-
-diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml
-new file mode 100644
-index 0000000..ca326ac
---- /dev/null
-+++ b/library/core/tests/Cargo.toml
-@@ -0,0 +1,14 @@
-+[workspace]
-+
-+[package]
-+name = "coretests"
-+version = "0.0.0"
-+edition = "2021"
-+
-+[lib]
-+name = "coretests"
-+path = "lib.rs"
-+
-+[dependencies]
-+rand = { version = "0.8.5", default-features = false }
-+rand_xorshift = { version = "0.3.0", default-features = false }
-diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
-index a4a7946..ecfe43f 100644
---- a/library/core/tests/lib.rs
-+++ b/library/core/tests/lib.rs
-@@ -1,4 +1,5 @@
- // tidy-alphabetical-start
-+#![cfg(test)]
- #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
- #![cfg_attr(test, feature(cfg_match))]
- #![feature(alloc_layout_extra)]
---
-2.47.1
-
diff --git a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch
index dc1beae..20df424 100644
--- a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch
+++ b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch
@@ -1,17 +1,17 @@
-From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Fri, 3 Dec 2021 12:16:30 +0100
+From ec2d0dc77fb484d926b45bb626b0db6a4bb0ab5c Mon Sep 17 00:00:00 2001
+From: None <none@example.com>
+Date: Thu, 27 Mar 2025 09:20:41 -0400
Subject: [PATCH] Disable long running tests
---
- library/core/tests/slice.rs | 2 ++
+ library/coretests/tests/slice.rs | 2 ++
1 file changed, 2 insertions(+)
-diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
-index 8402833..84592e0 100644
---- a/library/core/tests/slice.rs
-+++ b/library/core/tests/slice.rs
-@@ -2462,6 +2462,7 @@ take_tests! {
+diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
+index d17e681..fba5cd6 100644
+--- a/library/coretests/tests/slice.rs
++++ b/library/coretests/tests/slice.rs
+@@ -2486,6 +2486,7 @@ split_off_tests! {
#[cfg(not(miri))] // unused in Miri
const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
@@ -19,14 +19,14 @@
// can't be a constant due to const mutability rules
#[cfg(not(miri))] // unused in Miri
macro_rules! empty_max_mut {
-@@ -2485,6 +2486,7 @@ take_tests! {
- (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
- (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
+@@ -2509,6 +2510,7 @@ split_off_tests! {
+ (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
+ (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
}
+*/
#[test]
fn test_slice_from_ptr_range() {
--
-2.26.2.7.g19db9cfb68
+2.49.0
diff --git a/compiler/rustc_codegen_gcc/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch b/compiler/rustc_codegen_gcc/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
index c220f53..fa360fe 100644
--- a/compiler/rustc_codegen_gcc/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
+++ b/compiler/rustc_codegen_gcc/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
@@ -1,19 +1,18 @@
-From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001
+From b2911e732d1bf0e28872495c4c47af1dad3c7911 Mon Sep 17 00:00:00 2001
From: None <none@example.com>
-Date: Thu, 28 Sep 2023 17:37:38 -0400
+Date: Thu, 27 Mar 2025 14:30:10 -0400
Subject: [PATCH] Disable libstd and libtest dylib
---
- library/std/Cargo.toml | 2 +-
- library/test/Cargo.toml | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
+ library/std/Cargo.toml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
-index 5b21355..cb0c49b 100644
+index 176da60..c183cdb 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
-@@ -9,7 +9,7 @@ description = "The Rust Standard Library"
- edition = "2021"
+@@ -10,7 +10,7 @@ edition = "2024"
+ autobenches = false
[lib]
-crate-type = ["dylib", "rlib"]
@@ -21,3 +20,6 @@
[dependencies]
alloc = { path = "../alloc", public = true }
+--
+2.49.0
+
diff --git a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
index 9ef5e0e..9d5b2dc 100644
--- a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
+++ b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch
@@ -1,25 +1,17 @@
-From 124a11ce086952a5794d5cfbaa45175809497b81 Mon Sep 17 00:00:00 2001
+From 1a8f6b8e39f343959d4d2e6b6957a6d780ac3fc0 Mon Sep 17 00:00:00 2001
From: None <none@example.com>
-Date: Sat, 18 Nov 2023 10:50:36 -0500
-Subject: [PATCH] [core] Disable portable-simd test
+Date: Thu, 27 Mar 2025 14:32:14 -0400
+Subject: [PATCH] Disable portable-simd test
---
- library/core/tests/lib.rs | 2 --
- 1 file changed, 2 deletions(-)
+ library/coretests/tests/lib.rs | 1 -
+ 1 file changed, 1 deletion(-)
-diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
-index b71786c..cf484d5 100644
---- a/library/core/tests/lib.rs
-+++ b/library/core/tests/lib.rs
-@@ -87,7 +87,6 @@
- #![feature(numfmt)]
- #![feature(pattern)]
- #![feature(pointer_is_aligned_to)]
--#![feature(portable_simd)]
- #![feature(ptr_metadata)]
- #![feature(slice_from_ptr_range)]
- #![feature(slice_internals)]
-@@ -155,7 +154,6 @@ mod pin;
+diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
+index 79022fe..9223b2f 100644
+--- a/library/coretests/tests/lib.rs
++++ b/library/coretests/tests/lib.rs
+@@ -165,7 +165,6 @@ mod pin;
mod pin_macro;
mod ptr;
mod result;
@@ -27,4 +19,6 @@
mod slice;
mod str;
mod str_lossy;
--- 2.45.2
+--
+2.49.0
+
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index 940b3de..fd898c5 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2025-01-12"
+channel = "nightly-2025-04-17"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index 9fe6baa..a96b18e 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -9,6 +9,8 @@
use rustc_middle::ty::layout::LayoutOf;
#[cfg(feature = "master")]
use rustc_session::config;
+#[cfg(feature = "master")]
+use rustc_target::callconv::Conv;
use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
use crate::builder::Builder;
@@ -105,6 +107,8 @@ pub trait FnAbiGccExt<'gcc, 'tcx> {
// TODO(antoyo): return a function pointer type instead?
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>;
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
+ #[cfg(feature = "master")]
+ fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option<FnAttribute<'gcc>>;
}
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
@@ -227,4 +231,47 @@ fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
);
pointer_type
}
+
+ #[cfg(feature = "master")]
+ fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option<FnAttribute<'gcc>> {
+ conv_to_fn_attribute(self.conv, &cx.tcx.sess.target.arch)
+ }
+}
+
+#[cfg(feature = "master")]
+pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<'gcc>> {
+ // TODO: handle the calling conventions returning None.
+ let attribute = match conv {
+ Conv::C
+ | Conv::Rust
+ | Conv::CCmseNonSecureCall
+ | Conv::CCmseNonSecureEntry
+ | Conv::RiscvInterrupt { .. } => return None,
+ Conv::Cold => return None,
+ Conv::PreserveMost => return None,
+ Conv::PreserveAll => return None,
+ Conv::GpuKernel => {
+ // TODO(antoyo): remove clippy allow attribute when this is implemented.
+ #[allow(clippy::if_same_then_else)]
+ if arch == "amdgpu" {
+ return None;
+ } else if arch == "nvptx64" {
+ return None;
+ } else {
+ panic!("Architecture {} does not support GpuKernel calling convention", arch);
+ }
+ }
+ Conv::AvrInterrupt => return None,
+ Conv::AvrNonBlockingInterrupt => return None,
+ Conv::ArmAapcs => return None,
+ Conv::Msp430Intr => return None,
+ Conv::X86Fastcall => return None,
+ Conv::X86Intr => return None,
+ Conv::X86Stdcall => return None,
+ Conv::X86ThisCall => return None,
+ Conv::X86VectorCall => return None,
+ Conv::X86_64SysV => FnAttribute::SysvAbi,
+ Conv::X86_64Win64 => FnAttribute::MsAbi,
+ };
+ Some(attribute)
}
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 415f8af..dbdf37e 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -36,7 +36,8 @@
//
// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes.
// Contrary, Rust expresses clobbers through "out" operands that aren't tied to
-// a variable (`_`), and such "clobbers" do have index.
+// a variable (`_`), and such "clobbers" do have index. Input operands cannot also
+// be clobbered.
//
// 4. Furthermore, GCC Extended Asm does not support explicit register constraints
// (like `out("eax")`) directly, offering so-called "local register variables"
@@ -161,6 +162,16 @@ fn codegen_inline_asm(
// Also, we don't emit any asm operands immediately; we save them to
// the one of the buffers to be emitted later.
+ let mut input_registers = vec![];
+
+ for op in rust_operands {
+ if let InlineAsmOperandRef::In { reg, .. } = *op {
+ if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
+ input_registers.push(reg_name);
+ }
+ }
+ }
+
// 1. Normal variables (and saving operands to buffers).
for (rust_idx, op) in rust_operands.iter().enumerate() {
match *op {
@@ -183,25 +194,39 @@ fn codegen_inline_asm(
continue;
}
(Register(reg_name), None) => {
- // `clobber_abi` can add lots of clobbers that are not supported by the target,
- // such as AVX-512 registers, so we just ignore unsupported registers
- let is_target_supported =
- reg.reg_class().supported_types(asm_arch, true).iter().any(
- |&(_, feature)| {
- if let Some(feature) = feature {
- self.tcx
- .asm_target_features(instance.def_id())
- .contains(&feature)
- } else {
- true // Register class is unconditionally supported
- }
- },
- );
+ if input_registers.contains(®_name) {
+ // the `clobber_abi` operand is converted into a series of
+ // `lateout("reg") _` operands. Of course, a user could also
+ // explicitly define such an output operand.
+ //
+ // GCC does not allow input registers to be clobbered, so if this out register
+ // is also used as an in register, do not add it to the clobbers list.
+ // it will be treated as a lateout register with `out_place: None`
+ if !late {
+ bug!("input registers can only be used as lateout regisers");
+ }
+ ("r", dummy_output_type(self.cx, reg.reg_class()))
+ } else {
+ // `clobber_abi` can add lots of clobbers that are not supported by the target,
+ // such as AVX-512 registers, so we just ignore unsupported registers
+ let is_target_supported =
+ reg.reg_class().supported_types(asm_arch, true).iter().any(
+ |&(_, feature)| {
+ if let Some(feature) = feature {
+ self.tcx
+ .asm_target_features(instance.def_id())
+ .contains(&feature)
+ } else {
+ true // Register class is unconditionally supported
+ }
+ },
+ );
- if is_target_supported && !clobbers.contains(®_name) {
- clobbers.push(reg_name);
+ if is_target_supported && !clobbers.contains(®_name) {
+ clobbers.push(reg_name);
+ }
+ continue;
}
- continue;
}
};
@@ -230,13 +255,10 @@ fn codegen_inline_asm(
}
InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
- let constraint =
- if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
- constraint
- } else {
- // left for the next pass
- continue;
- };
+ let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) else {
+ // left for the next pass
+ continue;
+ };
// Rustc frontend guarantees that input and output types are "compatible",
// so we can just use input var's type for the output variable.
@@ -589,114 +611,127 @@ fn estimate_template_length(
}
/// Converts a register class to a GCC constraint code.
-fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
- let constraint = match reg {
- // For vector registers LLVM wants the register name to match the type size.
+fn reg_to_gcc(reg_or_reg_class: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
+ match reg_or_reg_class {
InlineAsmRegOrRegClass::Reg(reg) => {
- match reg {
- InlineAsmReg::X86(_) => {
- // TODO(antoyo): add support for vector register.
- //
- // // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
- return ConstraintOrRegister::Register(match reg.name() {
- // Some of registers' names does not map 1-1 from rust to gcc
- "st(0)" => "st",
+ ConstraintOrRegister::Register(explicit_reg_to_gcc(reg))
+ }
+ InlineAsmRegOrRegClass::RegClass(reg_class) => {
+ ConstraintOrRegister::Constraint(reg_class_to_gcc(reg_class))
+ }
+ }
+}
- name => name,
- });
+fn explicit_reg_to_gcc(reg: InlineAsmReg) -> &'static str {
+ // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
+ match reg {
+ InlineAsmReg::X86(reg) => {
+ // TODO(antoyo): add support for vector register.
+ match reg.reg_class() {
+ X86InlineAsmRegClass::reg_byte => {
+ // GCC does not support the `b` suffix, so we just strip it
+ // see https://github.com/rust-lang/rustc_codegen_gcc/issues/485
+ reg.name().trim_end_matches('b')
}
+ _ => match reg.name() {
+ // Some of registers' names does not map 1-1 from rust to gcc
+ "st(0)" => "st",
- _ => unimplemented!(),
+ name => name,
+ },
}
}
- // They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
- InlineAsmRegOrRegClass::RegClass(reg) => match reg {
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
- unreachable!("clobber-only")
- }
- InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
- InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
- InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
- InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
- InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
- InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
- InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
- unreachable!("clobber-only")
- }
- InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
- InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
- InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
- InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f",
- InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
- InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
- InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
- // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
- // "define_constraint".
- InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
- InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
- InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
- | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
- unreachable!("clobber-only")
- }
- InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
- InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
- unreachable!("clobber-only")
- }
- InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
- InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
- InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
- | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
- InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
- InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
- InlineAsmRegClass::X86(
- X86InlineAsmRegClass::kreg0
- | X86InlineAsmRegClass::x87_reg
- | X86InlineAsmRegClass::mmx_reg
- | X86InlineAsmRegClass::tmm_reg,
- ) => unreachable!("clobber-only"),
- InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
- bug!("GCC backend does not support SPIR-V")
- }
- InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
- unreachable!("clobber-only")
- }
- InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
- InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
- InlineAsmRegClass::Err => unreachable!(),
- },
- };
+ _ => unimplemented!(),
+ }
+}
- ConstraintOrRegister::Constraint(constraint)
+/// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
+fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
+ match reg_class {
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+ unreachable!("clobber-only")
+ }
+ InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
+ InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
+ InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
+ unreachable!("clobber-only")
+ }
+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
+ InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
+ InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
+ InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
+ // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
+ // "define_constraint".
+ InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
+ InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
+ InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
+
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
+ | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
+ unreachable!("clobber-only")
+ }
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+ unreachable!("clobber-only")
+ }
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
+ | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
+ InlineAsmRegClass::X86(
+ X86InlineAsmRegClass::kreg0
+ | X86InlineAsmRegClass::x87_reg
+ | X86InlineAsmRegClass::mmx_reg
+ | X86InlineAsmRegClass::tmm_reg,
+ ) => unreachable!("clobber-only"),
+ InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
+ bug!("GCC backend does not support SPIR-V")
+ }
+ InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
+ unreachable!("clobber-only")
+ }
+ InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
+ InlineAsmRegClass::Err => unreachable!(),
+ }
}
/// Type to use for outputs that are discarded. It doesn't really matter what
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index 51c5ba7..16c8953 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -24,19 +24,23 @@ pub(crate) unsafe fn codegen(
{
let context = &module.module_llvm.context;
- let module_name = module.name.clone();
-
let should_combine_object_files = module.module_llvm.should_combine_object_files;
- let module_name = Some(&module_name[..]);
-
// NOTE: Only generate object files with GIMPLE when this environment variable is set for
// now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
// TODO(antoyo): remove this environment variable.
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
- let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
- let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
+ let bc_out = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::Bitcode,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
+ let obj_out = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::Object,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
if config.bitcode_needed() {
if fat_lto {
@@ -117,14 +121,22 @@ pub(crate) unsafe fn codegen(
}
if config.emit_ir {
- let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
+ let out = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::LlvmAssembly,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
std::fs::write(out, "").expect("write file");
}
if config.emit_asm {
let _timer =
cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
- let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+ let path = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::Assembly,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
}
@@ -238,6 +250,7 @@ pub(crate) unsafe fn codegen(
config.emit_asm,
config.emit_ir,
&cgcx.output_filenames,
+ cgcx.invocation_temp.as_deref(),
))
}
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 6573b5b..5c70f4a 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -368,16 +368,8 @@ fn function_ptr_call(
let previous_arg_count = args.len();
let orig_args = args;
let args = {
- let function_address_names = self.function_address_names.borrow();
- let original_function_name = function_address_names.get(&func_ptr);
func_ptr = llvm::adjust_function(self.context, &func_name, func_ptr, args);
- llvm::adjust_intrinsic_arguments(
- self,
- gcc_func,
- args.into(),
- &func_name,
- original_function_name,
- )
+ llvm::adjust_intrinsic_arguments(self, gcc_func, args.into(), &func_name)
};
let args_adjusted = args.len() != previous_arg_count;
let args = self.check_ptr_call("call", func_ptr, &args);
@@ -1271,7 +1263,50 @@ fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RV
}
fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
- self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs)
+ // LLVM has a concept of "unordered compares", where eg ULT returns true if either the two
+ // arguments are unordered (i.e. either is NaN), or the lhs is less than the rhs. GCC does
+ // not natively have this concept, so in some cases we must manually handle NaNs
+ let must_handle_nan = match op {
+ RealPredicate::RealPredicateFalse => unreachable!(),
+ RealPredicate::RealOEQ => false,
+ RealPredicate::RealOGT => false,
+ RealPredicate::RealOGE => false,
+ RealPredicate::RealOLT => false,
+ RealPredicate::RealOLE => false,
+ RealPredicate::RealONE => false,
+ RealPredicate::RealORD => unreachable!(),
+ RealPredicate::RealUNO => unreachable!(),
+ RealPredicate::RealUEQ => false,
+ RealPredicate::RealUGT => true,
+ RealPredicate::RealUGE => true,
+ RealPredicate::RealULT => true,
+ RealPredicate::RealULE => true,
+ RealPredicate::RealUNE => false,
+ RealPredicate::RealPredicateTrue => unreachable!(),
+ };
+
+ let cmp = self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs);
+
+ if must_handle_nan {
+ let is_nan = self.context.new_binary_op(
+ self.location,
+ BinaryOp::LogicalOr,
+ self.cx.bool_type,
+ // compare a value to itself to check whether it is NaN
+ self.context.new_comparison(self.location, ComparisonOp::NotEquals, lhs, lhs),
+ self.context.new_comparison(self.location, ComparisonOp::NotEquals, rhs, rhs),
+ );
+
+ self.context.new_binary_op(
+ self.location,
+ BinaryOp::LogicalOr,
+ self.cx.bool_type,
+ is_nan,
+ cmp,
+ )
+ } else {
+ cmp
+ }
}
/* Miscellaneous instructions */
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 1e1f577..7371899 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -23,6 +23,8 @@
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi,
};
+#[cfg(feature = "master")]
+use crate::abi::conv_to_fn_attribute;
use crate::callee::get_fn;
use crate::common::SignType;
@@ -213,33 +215,7 @@ pub fn new(
let bool_type = context.new_type::<bool>();
let mut functions = FxHashMap::default();
- let builtins = [
- "__builtin_unreachable",
- "abort",
- "__builtin_expect", /*"__builtin_expect_with_probability",*/
- "__builtin_constant_p",
- "__builtin_add_overflow",
- "__builtin_mul_overflow",
- "__builtin_saddll_overflow",
- /*"__builtin_sadd_overflow",*/
- "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/
- "__builtin_ssubll_overflow",
- /*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow",
- "__builtin_uaddll_overflow",
- "__builtin_uadd_overflow",
- "__builtin_umulll_overflow",
- "__builtin_umul_overflow",
- "__builtin_usubll_overflow",
- "__builtin_usub_overflow",
- "__builtin_powif",
- "__builtin_powi",
- "fabsf",
- "fabs",
- "copysignf",
- "copysign",
- "nearbyintf",
- "nearbyint",
- ];
+ let builtins = ["abort"];
for builtin in builtins.iter() {
functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
@@ -509,7 +485,11 @@ fn apply_target_cpu_attr(&self, _llfn: RValue<'gcc>) {
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
let entry_name = self.sess().target.entry_name.as_ref();
if !self.functions.borrow().contains_key(entry_name) {
- Some(self.declare_entry_fn(entry_name, fn_type, ()))
+ #[cfg(feature = "master")]
+ let conv = conv_to_fn_attribute(self.sess().target.entry_abi, &self.sess().target.arch);
+ #[cfg(not(feature = "master"))]
+ let conv = None;
+ Some(self.declare_entry_fn(entry_name, fn_type, conv))
} else {
// If the symbol already exists, it is an error: for example, the user wrote
// #[no_mangle] extern "C" fn main(..) {..}
@@ -605,7 +585,10 @@ pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
let mut name = String::with_capacity(prefix.len() + 6);
name.push_str(prefix);
name.push('.');
- name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
+ // Offset the index by the base so that always at least two characters
+ // are generated. This avoids cases where the suffix is interpreted as
+ // size by the assembler (for m68k: .b, .w, .l).
+ name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY));
name
}
}
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index 7cdbe3c..c1ca3eb 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -58,7 +58,7 @@ pub fn declare_func(
variadic: bool,
) -> Function<'gcc> {
self.linkage.set(FunctionType::Extern);
- declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic)
+ declare_raw_fn(self, name, None, return_type, params, variadic)
}
pub fn declare_global(
@@ -92,7 +92,8 @@ pub fn declare_entry_fn(
&self,
name: &str,
_fn_type: Type<'gcc>,
- callconv: (), /*llvm::CCallConv*/
+ #[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>,
+ #[cfg(not(feature = "master"))] callconv: Option<()>,
) -> RValue<'gcc> {
// TODO(antoyo): use the fn_type parameter.
let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
@@ -123,14 +124,11 @@ pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function
#[cfg(feature = "master")]
fn_attributes,
} = fn_abi.gcc_type(self);
- let func = declare_raw_fn(
- self,
- name,
- (), /*fn_abi.llvm_cconv()*/
- return_type,
- &arguments_type,
- is_c_variadic,
- );
+ #[cfg(feature = "master")]
+ let conv = fn_abi.gcc_cconv(self);
+ #[cfg(not(feature = "master"))]
+ let conv = None;
+ let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic);
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
#[cfg(feature = "master")]
for fn_attr in fn_attributes {
@@ -162,7 +160,8 @@ pub fn get_declared_value(&self, name: &str) -> Option<RValue<'gcc>> {
fn declare_raw_fn<'gcc>(
cx: &CodegenCx<'gcc, '_>,
name: &str,
- _callconv: (), /*llvm::CallConv*/
+ #[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>,
+ #[cfg(not(feature = "master"))] _callconv: Option<()>,
return_type: Type<'gcc>,
param_types: &[Type<'gcc>],
variadic: bool,
@@ -192,6 +191,10 @@ fn declare_raw_fn<'gcc>(
let name = &mangle_name(name);
let func =
cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, name, variadic);
+ #[cfg(feature = "master")]
+ if let Some(attribute) = callconv {
+ func.add_attribute(attribute);
+ }
cx.functions.borrow_mut().insert(name.to_string(), func);
#[cfg(feature = "master")]
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 6eae0c2..202764d 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -194,6 +194,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
fn arch_to_gcc(name: &str) -> &str {
match name {
+ "M68000" => "68000",
"M68020" => "68020",
_ => name,
}
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index f3552d9..9b5b0fd 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -404,7 +404,7 @@ pub fn operation_with_overflow(
let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
- let result = if ret_indirect {
+ let call = if ret_indirect {
let res_value = self.current_func().new_local(self.location, res_type, "result_value");
let res_addr = res_value.get_address(self.location);
let res_param_type = res_type.make_pointer();
@@ -432,8 +432,17 @@ pub fn operation_with_overflow(
);
self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr])
};
+ // NOTE: we must assign the result of the operation to a variable at this point to make
+ // sure it will be evaluated by libgccjit now.
+ // Otherwise, it will only be evaluated when the rvalue for the call is used somewhere else
+ // and overflow_value will not be initialized at the correct point in the program.
+ let result = self.current_func().new_local(self.location, res_type, "result");
+ self.block.add_assignment(self.location, result, call);
- (result, self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue())
+ (
+ result.to_rvalue(),
+ self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue(),
+ )
}
pub fn gcc_icmp(
@@ -865,6 +874,7 @@ pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<
let value_type = value.get_type();
if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type)
{
+ // TODO: use self.location.
self.context.new_cast(None, value, dest_typ)
} else if self.is_native_int_type_or_bool(dest_typ) {
self.context.new_cast(None, self.low(value), dest_typ)
@@ -905,6 +915,7 @@ fn int_to_float_cast(
let name_suffix = match self.type_kind(dest_typ) {
TypeKind::Float => "tisf",
TypeKind::Double => "tidf",
+ TypeKind::FP128 => "tixf",
kind => panic!("cannot cast a non-native integer to type {:?}", kind),
};
let sign = if signed { "" } else { "un" };
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
index 2d731f8..0eebd21 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
@@ -1,11 +1,90 @@
use std::borrow::Cow;
-use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue, UnaryOp};
+use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type};
use rustc_codegen_ssa::traits::BuilderMethods;
use crate::builder::Builder;
use crate::context::CodegenCx;
+fn encode_key_128_type<'a, 'gcc, 'tcx>(
+ builder: &Builder<'a, 'gcc, 'tcx>,
+) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
+ let m128i = builder.context.new_vector_type(builder.i64_type, 2);
+ let field1 = builder.context.new_field(None, builder.u32_type, "field1");
+ let field2 = builder.context.new_field(None, m128i, "field2");
+ let field3 = builder.context.new_field(None, m128i, "field3");
+ let field4 = builder.context.new_field(None, m128i, "field4");
+ let field5 = builder.context.new_field(None, m128i, "field5");
+ let field6 = builder.context.new_field(None, m128i, "field6");
+ let field7 = builder.context.new_field(None, m128i, "field7");
+ let encode_type = builder.context.new_struct_type(
+ None,
+ "EncodeKey128Output",
+ &[field1, field2, field3, field4, field5, field6, field7],
+ );
+ #[cfg(feature = "master")]
+ encode_type.as_type().set_packed();
+ (encode_type.as_type(), field1, field2)
+}
+
+fn encode_key_256_type<'a, 'gcc, 'tcx>(
+ builder: &Builder<'a, 'gcc, 'tcx>,
+) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
+ let m128i = builder.context.new_vector_type(builder.i64_type, 2);
+ let field1 = builder.context.new_field(None, builder.u32_type, "field1");
+ let field2 = builder.context.new_field(None, m128i, "field2");
+ let field3 = builder.context.new_field(None, m128i, "field3");
+ let field4 = builder.context.new_field(None, m128i, "field4");
+ let field5 = builder.context.new_field(None, m128i, "field5");
+ let field6 = builder.context.new_field(None, m128i, "field6");
+ let field7 = builder.context.new_field(None, m128i, "field7");
+ let field8 = builder.context.new_field(None, m128i, "field8");
+ let encode_type = builder.context.new_struct_type(
+ None,
+ "EncodeKey256Output",
+ &[field1, field2, field3, field4, field5, field6, field7, field8],
+ );
+ #[cfg(feature = "master")]
+ encode_type.as_type().set_packed();
+ (encode_type.as_type(), field1, field2)
+}
+
+fn aes_output_type<'a, 'gcc, 'tcx>(
+ builder: &Builder<'a, 'gcc, 'tcx>,
+) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
+ let m128i = builder.context.new_vector_type(builder.i64_type, 2);
+ let field1 = builder.context.new_field(None, builder.u8_type, "field1");
+ let field2 = builder.context.new_field(None, m128i, "field2");
+ let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]);
+ let typ = aes_output_type.as_type();
+ #[cfg(feature = "master")]
+ typ.set_packed();
+ (typ, field1, field2)
+}
+
+fn wide_aes_output_type<'a, 'gcc, 'tcx>(
+ builder: &Builder<'a, 'gcc, 'tcx>,
+) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
+ let m128i = builder.context.new_vector_type(builder.i64_type, 2);
+ let field1 = builder.context.new_field(None, builder.u8_type, "field1");
+ let field2 = builder.context.new_field(None, m128i, "field2");
+ let field3 = builder.context.new_field(None, m128i, "field3");
+ let field4 = builder.context.new_field(None, m128i, "field4");
+ let field5 = builder.context.new_field(None, m128i, "field5");
+ let field6 = builder.context.new_field(None, m128i, "field6");
+ let field7 = builder.context.new_field(None, m128i, "field7");
+ let field8 = builder.context.new_field(None, m128i, "field8");
+ let field9 = builder.context.new_field(None, m128i, "field9");
+ let aes_output_type = builder.context.new_struct_type(
+ None,
+ "WideAesOutput",
+ &[field1, field2, field3, field4, field5, field6, field7, field8, field9],
+ );
+ #[cfg(feature = "master")]
+ aes_output_type.as_type().set_packed();
+ (aes_output_type.as_type(), field1, field2)
+}
+
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
pub fn adjust_function<'gcc>(
context: &'gcc Context<'gcc>,
@@ -43,7 +122,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
gcc_func: FunctionPtrType<'gcc>,
mut args: Cow<'b, [RValue<'gcc>]>,
func_name: &str,
- original_function_name: Option<&String>,
) -> Cow<'b, [RValue<'gcc>]> {
// TODO: this might not be a good way to workaround the missing tile builtins.
if func_name == "__builtin_trap" {
@@ -504,6 +582,72 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
let arg4 = builder.context.new_rvalue_from_int(arg4_type, -1);
args = vec![a, b, c, arg4, new_args[3]].into();
}
+ "__builtin_ia32_encodekey128_u32" => {
+ let mut new_args = args.to_vec();
+ let m128i = builder.context.new_vector_type(builder.i64_type, 2);
+ let array_type = builder.context.new_array_type(None, m128i, 6);
+ let result = builder.current_func().new_local(None, array_type, "result");
+ new_args.push(result.get_address(None));
+ args = new_args.into();
+ }
+ "__builtin_ia32_encodekey256_u32" => {
+ let mut new_args = args.to_vec();
+ let m128i = builder.context.new_vector_type(builder.i64_type, 2);
+ let array_type = builder.context.new_array_type(None, m128i, 7);
+ let result = builder.current_func().new_local(None, array_type, "result");
+ new_args.push(result.get_address(None));
+ args = new_args.into();
+ }
+ "__builtin_ia32_aesenc128kl_u8"
+ | "__builtin_ia32_aesdec128kl_u8"
+ | "__builtin_ia32_aesenc256kl_u8"
+ | "__builtin_ia32_aesdec256kl_u8" => {
+ let mut new_args = vec![];
+ let m128i = builder.context.new_vector_type(builder.i64_type, 2);
+ let result = builder.current_func().new_local(None, m128i, "result");
+ new_args.push(result.get_address(None));
+ new_args.extend(args.to_vec());
+ args = new_args.into();
+ }
+ "__builtin_ia32_aesencwide128kl_u8"
+ | "__builtin_ia32_aesdecwide128kl_u8"
+ | "__builtin_ia32_aesencwide256kl_u8"
+ | "__builtin_ia32_aesdecwide256kl_u8" => {
+ let mut new_args = vec![];
+
+ let mut old_args = args.to_vec();
+ let handle = old_args.swap_remove(0); // Called __P in GCC.
+ let first_value = old_args.swap_remove(0);
+
+ let element_type = first_value.get_type();
+ let array_type = builder.context.new_array_type(None, element_type, 8);
+ let result = builder.current_func().new_local(None, array_type, "result");
+ new_args.push(result.get_address(None));
+
+ let array = builder.current_func().new_local(None, array_type, "array");
+ let input = builder.context.new_array_constructor(
+ None,
+ array_type,
+ &[
+ first_value,
+ old_args.swap_remove(0),
+ old_args.swap_remove(0),
+ old_args.swap_remove(0),
+ old_args.swap_remove(0),
+ old_args.swap_remove(0),
+ old_args.swap_remove(0),
+ old_args.swap_remove(0),
+ ],
+ );
+ builder.llbb().add_assignment(None, array, input);
+ let input_ptr = array.get_address(None);
+ let arg2_type = gcc_func.get_param_type(1);
+ let input_ptr = builder.context.new_cast(None, input_ptr, arg2_type);
+ new_args.push(input_ptr);
+
+ new_args.push(handle);
+ args = new_args.into();
+ }
_ => (),
}
} else {
@@ -541,33 +685,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
let c = builder.context.new_rvalue_from_vector(None, arg3_type, &[new_args[2]; 2]);
args = vec![a, b, c, new_args[3]].into();
}
- "__builtin_ia32_vfmaddsubpd256"
- | "__builtin_ia32_vfmaddsubps"
- | "__builtin_ia32_vfmaddsubps256"
- | "__builtin_ia32_vfmaddsubpd" => {
- if let Some(original_function_name) = original_function_name {
- match &**original_function_name {
- "llvm.x86.fma.vfmsubadd.pd.256"
- | "llvm.x86.fma.vfmsubadd.ps"
- | "llvm.x86.fma.vfmsubadd.ps.256"
- | "llvm.x86.fma.vfmsubadd.pd" => {
- // NOTE: since both llvm.x86.fma.vfmsubadd.ps and llvm.x86.fma.vfmaddsub.ps maps to
- // __builtin_ia32_vfmaddsubps, only add minus if this comes from a
- // subadd LLVM intrinsic, e.g. _mm256_fmsubadd_pd.
- let mut new_args = args.to_vec();
- let arg3 = &mut new_args[2];
- *arg3 = builder.context.new_unary_op(
- None,
- UnaryOp::Minus,
- arg3.get_type(),
- *arg3,
- );
- args = new_args.into();
- }
- _ => (),
- }
- }
- }
"__builtin_ia32_ldmxcsr" => {
// The builtin __builtin_ia32_ldmxcsr takes an integer value while llvm.x86.sse.ldmxcsr takes a pointer,
// so dereference the pointer.
@@ -728,6 +845,96 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
let f16_type = builder.context.new_c_type(CType::Float16);
return_value = builder.context.new_cast(None, return_value, f16_type);
}
+ "__builtin_ia32_encodekey128_u32" => {
+ // The builtin __builtin_ia32_encodekey128_u32 writes the result in its pointer argument while
+ // llvm.x86.encodekey128 returns a value.
+ // We added a result pointer argument and now need to assign its value to the return_value expected by
+ // the LLVM intrinsic.
+ let (encode_type, field1, field2) = encode_key_128_type(builder);
+ let result = builder.current_func().new_local(None, encode_type, "result");
+ let field1 = result.access_field(None, field1);
+ builder.llbb().add_assignment(None, field1, return_value);
+ let field2 = result.access_field(None, field2);
+ let field2_type = field2.to_rvalue().get_type();
+ let array_type = builder.context.new_array_type(None, field2_type, 6);
+ let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer());
+ let field2_ptr =
+ builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
+ builder.llbb().add_assignment(
+ None,
+ field2_ptr.dereference(None),
+ ptr.dereference(None),
+ );
+ return_value = result.to_rvalue();
+ }
+ "__builtin_ia32_encodekey256_u32" => {
+ // The builtin __builtin_ia32_encodekey256_u32 writes the result in its pointer argument while
+ // llvm.x86.encodekey256 returns a value.
+ // We added a result pointer argument and now need to assign its value to the return_value expected by
+ // the LLVM intrinsic.
+ let (encode_type, field1, field2) = encode_key_256_type(builder);
+ let result = builder.current_func().new_local(None, encode_type, "result");
+ let field1 = result.access_field(None, field1);
+ builder.llbb().add_assignment(None, field1, return_value);
+ let field2 = result.access_field(None, field2);
+ let field2_type = field2.to_rvalue().get_type();
+ let array_type = builder.context.new_array_type(None, field2_type, 7);
+ let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer());
+ let field2_ptr =
+ builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
+ builder.llbb().add_assignment(
+ None,
+ field2_ptr.dereference(None),
+ ptr.dereference(None),
+ );
+ return_value = result.to_rvalue();
+ }
+ "__builtin_ia32_aesdec128kl_u8"
+ | "__builtin_ia32_aesenc128kl_u8"
+ | "__builtin_ia32_aesdec256kl_u8"
+ | "__builtin_ia32_aesenc256kl_u8" => {
+ // The builtin for aesdec/aesenc writes the result in its pointer argument while
+ // llvm.x86.aesdec128kl returns a value.
+ // We added a result pointer argument and now need to assign its value to the return_value expected by
+ // the LLVM intrinsic.
+ let (aes_output_type, field1, field2) = aes_output_type(builder);
+ let result = builder.current_func().new_local(None, aes_output_type, "result");
+ let field1 = result.access_field(None, field1);
+ builder.llbb().add_assignment(None, field1, return_value);
+ let field2 = result.access_field(None, field2);
+ let ptr = builder.context.new_cast(
+ None,
+ args[0],
+ field2.to_rvalue().get_type().make_pointer(),
+ );
+ builder.llbb().add_assignment(None, field2, ptr.dereference(None));
+ return_value = result.to_rvalue();
+ }
+ "__builtin_ia32_aesencwide128kl_u8"
+ | "__builtin_ia32_aesdecwide128kl_u8"
+ | "__builtin_ia32_aesencwide256kl_u8"
+ | "__builtin_ia32_aesdecwide256kl_u8" => {
+ // The builtin for aesdecwide/aesencwide writes the result in its pointer argument while
+ // llvm.x86.aesencwide128kl returns a value.
+ // We added a result pointer argument and now need to assign its value to the return_value expected by
+ // the LLVM intrinsic.
+ let (aes_output_type, field1, field2) = wide_aes_output_type(builder);
+ let result = builder.current_func().new_local(None, aes_output_type, "result");
+ let field1 = result.access_field(None, field1);
+ builder.llbb().add_assignment(None, field1, return_value);
+ let field2 = result.access_field(None, field2);
+ let field2_type = field2.to_rvalue().get_type();
+ let array_type = builder.context.new_array_type(None, field2_type, 8);
+ let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer());
+ let field2_ptr =
+ builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
+ builder.llbb().add_assignment(
+ None,
+ field2_ptr.dereference(None),
+ ptr.dereference(None),
+ );
+ return_value = result.to_rvalue();
+ }
_ => (),
}
@@ -915,16 +1122,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.ctlz.v4i64" => "__builtin_ia32_vplzcntq_256_mask",
"llvm.ctlz.v2i64" => "__builtin_ia32_vplzcntq_128_mask",
"llvm.ctpop.v32i16" => "__builtin_ia32_vpopcountw_v32hi",
- "llvm.x86.fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd3",
- "llvm.x86.fma.vfmsub.ss" => "__builtin_ia32_vfmsubss3",
- "llvm.x86.fma.vfmsubadd.pd" => "__builtin_ia32_vfmaddsubpd",
- "llvm.x86.fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmaddsubpd256",
- "llvm.x86.fma.vfmsubadd.ps" => "__builtin_ia32_vfmaddsubps",
- "llvm.x86.fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmaddsubps256",
- "llvm.x86.fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd3",
- "llvm.x86.fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss3",
- "llvm.x86.fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd3",
- "llvm.x86.fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss3",
"llvm.x86.avx512.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask",
"llvm.x86.avx512.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask",
"llvm.x86.avx512.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask",
@@ -1002,8 +1199,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.fshr.v32i16" => "__builtin_ia32_vpshrdv_v32hi",
"llvm.fshr.v16i16" => "__builtin_ia32_vpshrdv_v16hi",
"llvm.fshr.v8i16" => "__builtin_ia32_vpshrdv_v8hi",
- "llvm.x86.fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd3",
- "llvm.x86.fma.vfmadd.ss" => "__builtin_ia32_vfmaddss3",
"llvm.x86.rdrand.64" => "__builtin_ia32_rdrand64_step",
// The above doc points to unknown builtins for the following, so override them:
@@ -1324,6 +1519,16 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.x86.avx512fp16.mask.vfmadd.cph.256" => "__builtin_ia32_vfmaddcph256_mask3",
"llvm.x86.avx512fp16.mask.vfcmadd.cph.128" => "__builtin_ia32_vfcmaddcph128_mask3",
"llvm.x86.avx512fp16.mask.vfmadd.cph.128" => "__builtin_ia32_vfmaddcph128_mask3",
+ "llvm.x86.encodekey128" => "__builtin_ia32_encodekey128_u32",
+ "llvm.x86.encodekey256" => "__builtin_ia32_encodekey256_u32",
+ "llvm.x86.aesenc128kl" => "__builtin_ia32_aesenc128kl_u8",
+ "llvm.x86.aesdec128kl" => "__builtin_ia32_aesdec128kl_u8",
+ "llvm.x86.aesenc256kl" => "__builtin_ia32_aesenc256kl_u8",
+ "llvm.x86.aesdec256kl" => "__builtin_ia32_aesdec256kl_u8",
+ "llvm.x86.aesencwide128kl" => "__builtin_ia32_aesencwide128kl_u8",
+ "llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8",
+ "llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8",
+ "llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8",
// TODO: support the tile builtins:
"llvm.x86.ldtilecfg" => "__builtin_trap",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index f386220..d22f422 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -78,6 +78,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
sym::maxnumf64 => "fmax",
sym::copysignf32 => "copysignf",
sym::copysignf64 => "copysign",
+ sym::copysignf128 => "copysignl",
sym::floorf32 => "floorf",
sym::floorf64 => "floor",
sym::ceilf32 => "ceilf",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 8b454ab..6d40d52 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -399,7 +399,7 @@ macro_rules! require_simd {
}
#[cfg(feature = "master")]
- if name == sym::simd_insert {
+ if name == sym::simd_insert || name == sym::simd_insert_dyn {
require!(
in_elem == arg_tys[2],
InvalidMonomorphization::InsertedType {
@@ -410,6 +410,8 @@ macro_rules! require_simd {
out_ty: arg_tys[2]
}
);
+
+ // TODO(antoyo): For simd_insert, check if the index is a constant of the correct size.
let vector = args[0].immediate();
let index = args[1].immediate();
let value = args[2].immediate();
@@ -422,13 +424,15 @@ macro_rules! require_simd {
}
#[cfg(feature = "master")]
- if name == sym::simd_extract {
+ if name == sym::simd_extract || name == sym::simd_extract_dyn {
require!(
ret_ty == in_elem,
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
);
+ // TODO(antoyo): For simd_extract, check if the index is a constant of the correct size.
let vector = args[0].immediate();
- return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
+ let index = args[1].immediate();
+ return Ok(bx.context.new_vector_access(None, vector, index).to_rvalue());
}
if name == sym::simd_select {
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index bfa2317..624fdb4 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -188,10 +188,10 @@ fn locale_resource(&self) -> &'static str {
crate::DEFAULT_LOCALE_RESOURCE
}
- fn init(&self, sess: &Session) {
+ fn init(&self, _sess: &Session) {
#[cfg(feature = "master")]
{
- let target_cpu = target_cpu(sess);
+ let target_cpu = target_cpu(_sess);
// Get the second TargetInfo with the correct CPU features by setting the arch.
let context = Context::default();
diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index 082958b..499c1a9 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -1,11 +1,9 @@
tests/ui/allocator/no_std-alloc-error-handler-custom.rs
tests/ui/allocator/no_std-alloc-error-handler-default.rs
tests/ui/asm/may_unwind.rs
-tests/ui/asm/x86_64/multiple-clobber-abi.rs
tests/ui/functions-closures/parallel-codegen-closures.rs
tests/ui/linkage-attr/linkage1.rs
tests/ui/lto/dylib-works.rs
-tests/ui/numbers-arithmetic/saturating-float-casts.rs
tests/ui/sepcomp/sepcomp-cci.rs
tests/ui/sepcomp/sepcomp-extern.rs
tests/ui/sepcomp/sepcomp-fns-backwards.rs
@@ -33,7 +31,6 @@
tests/ui/parser/unclosed-delimiter-in-dep.rs
tests/ui/consts/missing_span_in_backtrace.rs
tests/ui/drop/dynamic-drop.rs
-tests/ui/issues/issue-40883.rs
tests/ui/issues/issue-43853.rs
tests/ui/issues/issue-47364.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
@@ -102,14 +99,12 @@
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
-tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs
-tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs
@@ -117,8 +112,9 @@
tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs
-tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
tests/ui/simd/simd-bitmask-notpow2.rs
+tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs
+tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
index fe46d9a..ff2bb75 100644
--- a/compiler/rustc_codegen_gcc/tests/run/abort1.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
@@ -3,45 +3,13 @@
// Run-time:
// status: signal
-#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-mod intrinsics {
- use super::Sized;
-
- #[rustc_nounwind]
- #[rustc_intrinsic]
- pub fn abort() -> !;
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
fn test_fail() -> ! {
unsafe { intrinsics::abort() };
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
index 4123f4f..781f518 100644
--- a/compiler/rustc_codegen_gcc/tests/run/abort2.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
@@ -3,45 +3,13 @@
// Run-time:
// status: signal
-#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-mod intrinsics {
- use super::Sized;
-
- #[rustc_nounwind]
- #[rustc_intrinsic]
- pub fn abort() -> !;
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
fn fail() -> i32 {
unsafe { intrinsics::abort() };
diff --git a/compiler/rustc_codegen_gcc/tests/run/array.rs b/compiler/rustc_codegen_gcc/tests/run/array.rs
index e18a4ce..3ab0c30 100644
--- a/compiler/rustc_codegen_gcc/tests/run/array.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/array.rs
@@ -8,20 +8,12 @@
// 10
#![feature(no_core)]
-
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- pub fn puts(s: *const u8) -> i32;
- }
-}
+use mini_core::*;
static mut ONE: usize = 1;
diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs
index 4e05d02..2dbf43b 100644
--- a/compiler/rustc_codegen_gcc/tests/run/asm.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs
@@ -174,6 +174,59 @@ extern "C" fn foo() -> u64 {
mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3);
}
assert_eq!(array1, array2);
+
+ // in and clobber registers cannot overlap. This tests that the lateout register without an
+ // output place (indicated by the `_`) is not added to the list of clobbered registers
+ let x = 8;
+ let y: i32;
+ unsafe {
+ asm!(
+ "mov rax, rdi",
+ in("rdi") x,
+ lateout("rdi") _,
+ out("rax") y,
+ );
+ }
+ assert_eq!((x, y), (8, 8));
+
+ // sysv64 is the default calling convention on unix systems. The rdi register is
+ // used to pass arguments in the sysv64 calling convention, so this register will be clobbered
+ #[cfg(unix)]
+ {
+ let x = 16;
+ let y: i32;
+ unsafe {
+ asm!(
+ "mov rax, rdi",
+ in("rdi") x,
+ out("rax") y,
+ clobber_abi("sysv64"),
+ );
+ }
+ assert_eq!((x, y), (16, 16));
+ }
+
+ // the `b` suffix for registers in the `reg_byte` register class is not supported in GCC
+ // and needs to be stripped in order to use these registers.
+ unsafe {
+ core::arch::asm!(
+ "",
+ out("al") _,
+ out("bl") _,
+ out("cl") _,
+ out("dl") _,
+ out("sil") _,
+ out("dil") _,
+ out("r8b") _,
+ out("r9b") _,
+ out("r10b") _,
+ out("r11b") _,
+ out("r12b") _,
+ out("r13b") _,
+ out("r14b") _,
+ out("r15b") _,
+ );
+ }
}
#[cfg(not(target_arch = "x86_64"))]
diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs
index 2861558..4535ab5 100644
--- a/compiler/rustc_codegen_gcc/tests/run/assign.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs
@@ -5,130 +5,13 @@
// 7 8
// 10
-#![allow(internal_features, unused_attributes)]
-#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-impl Copy for *mut i32 {}
-impl Copy for usize {}
-impl Copy for u8 {}
-impl Copy for i8 {}
-impl Copy for i32 {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-#[lang = "panic_location"]
-struct PanicLocation {
- file: &'static str,
- line: u32,
- column: u32,
-}
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn puts(s: *const u8) -> i32;
- pub fn fflush(stream: *mut i32) -> i32;
- pub fn printf(format: *const i8, ...) -> i32;
-
- pub static stdout: *mut i32;
- }
-}
-
-mod intrinsics {
- #[rustc_nounwind]
- #[rustc_intrinsic]
- pub fn abort() -> !;
-}
-
-#[lang = "panic"]
-#[track_caller]
-#[no_mangle]
-pub fn panic(_msg: &'static str) -> ! {
- unsafe {
- libc::puts("Panicking\0" as *const str as *const u8);
- libc::fflush(libc::stdout);
- intrinsics::abort();
- }
-}
-
-#[lang = "add"]
-trait Add<RHS = Self> {
- type Output;
-
- fn add(self, rhs: RHS) -> Self::Output;
-}
-
-impl Add for u8 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for i8 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for i32 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for usize {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for isize {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-#[track_caller]
-#[lang = "panic_const_add_overflow"]
-pub fn panic_const_add_overflow() -> ! {
- panic("attempt to add with overflow");
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
fn inc_ref(num: &mut isize) -> isize {
*num = *num + 5;
@@ -139,9 +22,8 @@ fn inc(num: isize) -> isize {
num + 1
}
-
#[no_mangle]
-extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
+extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
argc = inc(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);
diff --git a/compiler/rustc_codegen_gcc/tests/run/closure.rs b/compiler/rustc_codegen_gcc/tests/run/closure.rs
index c7a236f..a8a3fad 100644
--- a/compiler/rustc_codegen_gcc/tests/run/closure.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/closure.rs
@@ -9,55 +9,38 @@
// Both args: 11
#![feature(no_core)]
-
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
+use mini_core::*;
#[no_mangle]
-extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
+extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
let string = "Arg: %d\n\0";
- let mut closure = || {
- unsafe {
- libc::printf(string as *const str as *const i8, argc);
- }
+ let mut closure = || unsafe {
+ libc::printf(string as *const str as *const i8, argc);
};
closure();
- let mut closure = || {
- unsafe {
- libc::printf("Argument: %d\n\0" as *const str as *const i8, argc);
- }
+ let mut closure = || unsafe {
+ libc::printf("Argument: %d\n\0" as *const str as *const i8, argc);
};
closure();
- let mut closure = |string| {
- unsafe {
- libc::printf(string as *const str as *const i8, argc);
- }
+ let mut closure = |string| unsafe {
+ libc::printf(string as *const str as *const i8, argc);
};
closure("String arg: %d\n\0");
- let mut closure = |arg: isize| {
- unsafe {
- libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg);
- }
+ let mut closure = |arg: isize| unsafe {
+ libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg);
};
closure(argc + 1);
- let mut closure = |string, arg: isize| {
- unsafe {
- libc::printf(string as *const str as *const i8, arg);
- }
+ let mut closure = |string, arg: isize| unsafe {
+ libc::printf(string as *const str as *const i8, arg);
};
closure("Both args: %d\n\0", argc + 10);
diff --git a/compiler/rustc_codegen_gcc/tests/run/condition.rs b/compiler/rustc_codegen_gcc/tests/run/condition.rs
index b023597..bd3b6f7 100644
--- a/compiler/rustc_codegen_gcc/tests/run/condition.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/condition.rs
@@ -6,19 +6,12 @@
// 1
#![feature(no_core)]
-
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
+use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
@@ -27,15 +20,14 @@ extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
libc::printf(b"true\n\0" as *const u8 as *const i8);
}
- let string =
- match argc {
- 1 => b"1\n\0",
- 2 => b"2\n\0",
- 3 => b"3\n\0",
- 4 => b"4\n\0",
- 5 => b"5\n\0",
- _ => b"_\n\0",
- };
+ let string = match argc {
+ 1 => b"1\n\0",
+ 2 => b"2\n\0",
+ 3 => b"3\n\0",
+ 4 => b"4\n\0",
+ 5 => b"5\n\0",
+ _ => b"_\n\0",
+ };
libc::printf(string as *const u8 as *const i8);
}
0
diff --git a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
index 042e440..fe3df5a 100644
--- a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
@@ -3,37 +3,13 @@
// Run-time:
// status: 0
-#![feature(auto_traits, lang_items, no_core)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
diff --git a/compiler/rustc_codegen_gcc/tests/run/exit.rs b/compiler/rustc_codegen_gcc/tests/run/exit.rs
index 9a7c91c..e0a5917 100644
--- a/compiler/rustc_codegen_gcc/tests/run/exit.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/exit.rs
@@ -3,44 +3,13 @@
// Run-time:
// status: 2
-#![feature(auto_traits, lang_items, no_core, intrinsics)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn exit(status: i32);
- }
-}
-
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
diff --git a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
index c50d2b0..376824d 100644
--- a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
@@ -3,37 +3,13 @@
// Run-time:
// status: 1
-#![feature(auto_traits, lang_items, no_core)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
diff --git a/compiler/rustc_codegen_gcc/tests/run/float.rs b/compiler/rustc_codegen_gcc/tests/run/float.rs
new file mode 100644
index 0000000..424fa1c
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/float.rs
@@ -0,0 +1,28 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+
+#![feature(const_black_box)]
+
+fn main() {
+ use std::hint::black_box;
+
+ macro_rules! check {
+ ($ty:ty, $expr:expr) => {{
+ const EXPECTED: $ty = $expr;
+ assert_eq!($expr, EXPECTED);
+ }};
+ }
+
+ check!(i32, (black_box(0.0f32) as i32));
+
+ check!(u64, (black_box(f32::NAN) as u64));
+ check!(u128, (black_box(f32::NAN) as u128));
+
+ check!(i64, (black_box(f64::NAN) as i64));
+ check!(u64, (black_box(f64::NAN) as u64));
+
+ check!(i16, (black_box(f32::MIN) as i16));
+ check!(i16, (black_box(f32::MAX) as i16));
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
index 98b351e..93b9bae 100644
--- a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
@@ -5,19 +5,12 @@
// stdout: 1
#![feature(no_core)]
-
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
+use mini_core::*;
fn i16_as_i8(a: i16) -> i8 {
a as i8
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
index 58a2680..47b5dea 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -3,9 +3,7 @@
// Run-time:
// status: 0
-/*
- * Code
- */
+#![feature(const_black_box)]
fn main() {
use std::hint::black_box;
diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
index b021586..fa50d5b 100644
--- a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
@@ -1,4 +1,3 @@
-
// Compiler:
//
// Run-time:
@@ -7,139 +6,20 @@
// 6
// 11
-#![allow(internal_features, unused_attributes)]
-#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-impl Copy for *mut i32 {}
-impl Copy for usize {}
-impl Copy for u8 {}
-impl Copy for i8 {}
-impl Copy for i32 {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-#[lang = "panic_location"]
-struct PanicLocation {
- file: &'static str,
- line: u32,
- column: u32,
-}
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn puts(s: *const u8) -> i32;
- pub fn fflush(stream: *mut i32) -> i32;
- pub fn printf(format: *const i8, ...) -> i32;
-
- pub static stdout: *mut i32;
- }
-}
-
-mod intrinsics {
- #[rustc_nounwind]
- #[rustc_intrinsic]
- pub fn abort() -> !;
-}
-
-#[lang = "panic"]
-#[track_caller]
-#[no_mangle]
-pub fn panic(_msg: &'static str) -> ! {
- unsafe {
- libc::puts("Panicking\0" as *const str as *const u8);
- libc::fflush(libc::stdout);
- intrinsics::abort();
- }
-}
-
-#[lang = "add"]
-trait Add<RHS = Self> {
- type Output;
-
- fn add(self, rhs: RHS) -> Self::Output;
-}
-
-impl Add for u8 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for i8 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for i32 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for usize {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for isize {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-#[track_caller]
-#[lang = "panic_const_add_overflow"]
-pub fn panic_const_add_overflow() -> ! {
- panic("attempt to add with overflow");
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
struct Test {
field: isize,
}
fn test(num: isize) -> Test {
- Test {
- field: num + 1,
- }
+ Test { field: num + 1 }
}
fn update_num(num: &mut isize) {
@@ -147,7 +27,7 @@ fn update_num(num: &mut isize) {
}
#[no_mangle]
-extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
+extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
let mut test = test(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs
index 8ba7a4c..a1b0772 100644
--- a/compiler/rustc_codegen_gcc/tests/run/operations.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs
@@ -5,229 +5,13 @@
// 39
// 10
-#![allow(internal_features, unused_attributes)]
-#![feature(auto_traits, lang_items, no_core, intrinsics, arbitrary_self_types, rustc_attrs)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-impl Copy for *mut i32 {}
-impl Copy for usize {}
-impl Copy for u8 {}
-impl Copy for i8 {}
-impl Copy for i16 {}
-impl Copy for i32 {}
-
-#[lang = "deref"]
-pub trait Deref {
- type Target: ?Sized;
-
- fn deref(&self) -> &Self::Target;
-}
-
-#[lang = "legacy_receiver"]
-trait LegacyReceiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-#[lang = "panic_location"]
-struct PanicLocation {
- file: &'static str,
- line: u32,
- column: u32,
-}
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- pub fn puts(s: *const u8) -> i32;
- pub fn fflush(stream: *mut i32) -> i32;
-
- pub static stdout: *mut i32;
- }
-}
-
-mod intrinsics {
- #[rustc_nounwind]
- #[rustc_intrinsic]
- pub fn abort() -> !;
-}
-
-#[lang = "panic"]
-#[track_caller]
-#[no_mangle]
-pub fn panic(_msg: &'static str) -> ! {
- unsafe {
- libc::puts("Panicking\0" as *const str as *const u8);
- libc::fflush(libc::stdout);
- intrinsics::abort();
- }
-}
-
-#[lang = "add"]
-trait Add<RHS = Self> {
- type Output;
-
- fn add(self, rhs: RHS) -> Self::Output;
-}
-
-impl Add for u8 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for i8 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for i32 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for usize {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-impl Add for isize {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self {
- self + rhs
- }
-}
-
-#[lang = "sub"]
-pub trait Sub<RHS = Self> {
- type Output;
-
- fn sub(self, rhs: RHS) -> Self::Output;
-}
-
-impl Sub for usize {
- type Output = Self;
-
- fn sub(self, rhs: Self) -> Self {
- self - rhs
- }
-}
-
-impl Sub for isize {
- type Output = Self;
-
- fn sub(self, rhs: Self) -> Self {
- self - rhs
- }
-}
-
-impl Sub for u8 {
- type Output = Self;
-
- fn sub(self, rhs: Self) -> Self {
- self - rhs
- }
-}
-
-impl Sub for i8 {
- type Output = Self;
-
- fn sub(self, rhs: Self) -> Self {
- self - rhs
- }
-}
-
-impl Sub for i16 {
- type Output = Self;
-
- fn sub(self, rhs: Self) -> Self {
- self - rhs
- }
-}
-
-#[lang = "mul"]
-pub trait Mul<RHS = Self> {
- type Output;
-
- #[must_use]
- fn mul(self, rhs: RHS) -> Self::Output;
-}
-
-impl Mul for u8 {
- type Output = Self;
-
- fn mul(self, rhs: Self) -> Self::Output {
- self * rhs
- }
-}
-
-impl Mul for usize {
- type Output = Self;
-
- fn mul(self, rhs: Self) -> Self::Output {
- self * rhs
- }
-}
-
-impl Mul for isize {
- type Output = Self;
-
- fn mul(self, rhs: Self) -> Self::Output {
- self * rhs
- }
-}
-
-#[track_caller]
-#[lang = "panic_const_add_overflow"]
-pub fn panic_const_add_overflow() -> ! {
- panic("attempt to add with overflow");
-}
-
-#[track_caller]
-#[lang = "panic_const_sub_overflow"]
-pub fn panic_const_sub_overflow() -> ! {
- panic("attempt to subtract with overflow");
-}
-
-#[track_caller]
-#[lang = "panic_const_mul_overflow"]
-pub fn panic_const_mul_overflow() -> ! {
- panic("attempt to multiply with overflow");
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
index 0ba49e7..c1254c5 100644
--- a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
@@ -2,35 +2,32 @@
//
// Run-time:
// status: 0
-// stdout: 1
+// stdout: 10
+// 10
+// 42
#![feature(no_core)]
-
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
+use mini_core::*;
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
-
-static mut ONE: usize = 1;
-
-fn make_array() -> [u8; 3] {
- [42, 10, 5]
+fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) {
+ (
+ a as u8, a as u16, a as u32, a as usize, a as i8, a as i16, a as i32, a as isize, b as u8,
+ b as u32,
+ )
}
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
+ let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
unsafe {
- let ptr = ONE as *mut usize;
- let value = ptr as usize;
- libc::printf(b"%ld\n\0" as *const u8 as *const i8, value);
+ libc::printf(b"%d\n\0" as *const u8 as *const i8, c);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, d);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, j);
}
0
}
diff --git a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
index 3cc1e27..c1254c5 100644
--- a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
@@ -6,54 +6,13 @@
// 10
// 42
-#![feature(auto_traits, lang_items, no_core, intrinsics)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-#[lang = "copy"]
-pub unsafe trait Copy {}
-
-impl Copy for bool {}
-impl Copy for u8 {}
-impl Copy for u16 {}
-impl Copy for u32 {}
-impl Copy for u64 {}
-impl Copy for usize {}
-impl Copy for i8 {}
-impl Copy for i16 {}
-impl Copy for i32 {}
-impl Copy for isize {}
-impl Copy for f32 {}
-impl Copy for char {}
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
-
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "legacy_receiver"]
-trait LegacyReceiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) {
(
diff --git a/compiler/rustc_codegen_gcc/tests/run/slice.rs b/compiler/rustc_codegen_gcc/tests/run/slice.rs
index 825fcb8..449ccab 100644
--- a/compiler/rustc_codegen_gcc/tests/run/slice.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/slice.rs
@@ -5,26 +5,17 @@
// stdout: 5
#![feature(no_core)]
-
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
+use mini_core::*;
static mut TWO: usize = 2;
fn index_slice(s: &[u32]) -> u32 {
- unsafe {
- s[TWO]
- }
+ unsafe { s[TWO] }
}
#[no_mangle]
diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs
index c3c8121..1e36cf4 100644
--- a/compiler/rustc_codegen_gcc/tests/run/static.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/static.rs
@@ -9,70 +9,13 @@
// 12
// 1
-#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "destruct"]
-pub trait Destruct {}
-
-#[lang = "drop"]
-pub trait Drop {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-impl<T: ?Sized> Copy for *mut T {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-mod intrinsics {
- use super::Sized;
-
- #[rustc_nounwind]
- #[rustc_intrinsic]
- pub fn abort() -> !;
-}
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
-
-#[lang = "structural_peq"]
-pub trait StructuralPartialEq {}
-
-#[lang = "drop_in_place"]
-#[allow(unconditional_recursion)]
-pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
- // Code here does not matter - this is replaced by the
- // real drop glue by the compiler.
- drop_in_place(to_drop);
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
struct Test {
field: isize,
@@ -84,20 +27,14 @@ struct WithRef {
static mut CONSTANT: isize = 10;
-static mut TEST: Test = Test {
- field: 12,
-};
+static mut TEST: Test = Test { field: 12 };
-static mut TEST2: Test = Test {
- field: 14,
-};
+static mut TEST2: Test = Test { field: 14 };
-static mut WITH_REF: WithRef = WithRef {
- refe: unsafe { &TEST },
-};
+static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST } };
#[no_mangle]
-extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
+extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field);
diff --git a/compiler/rustc_codegen_gcc/tests/run/structs.rs b/compiler/rustc_codegen_gcc/tests/run/structs.rs
index 59b8f35..da73cbe 100644
--- a/compiler/rustc_codegen_gcc/tests/run/structs.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/structs.rs
@@ -5,44 +5,13 @@
// stdout: 1
// 2
-#![feature(auto_traits, lang_items, no_core, intrinsics)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
struct Test {
field: isize,
diff --git a/compiler/rustc_codegen_gcc/tests/run/tuple.rs b/compiler/rustc_codegen_gcc/tests/run/tuple.rs
index ed60a56..e0f2e95 100644
--- a/compiler/rustc_codegen_gcc/tests/run/tuple.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/tuple.rs
@@ -4,44 +4,13 @@
// status: 0
// stdout: 3
-#![feature(auto_traits, lang_items, no_core, intrinsics)]
-#![allow(internal_features)]
-
+#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
-/*
- * Core
- */
-
-// Because we don't have core yet.
-#[lang = "sized"]
-pub trait Sized {}
-
-#[lang = "copy"]
-trait Copy {
-}
-
-impl Copy for isize {}
-
-#[lang = "receiver"]
-trait Receiver {
-}
-
-#[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
-
-mod libc {
- #[link(name = "c")]
- extern "C" {
- pub fn printf(format: *const i8, ...) -> i32;
- }
-}
-
-/*
- * Code
- */
+extern crate mini_core;
+use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 76d431a..18d221d 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -119,14 +119,18 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar
tcx.output_filenames(()).split_dwarf_path(
tcx.sess.split_debuginfo(),
tcx.sess.opts.unstable_opts.split_dwarf_kind,
- Some(mod_name),
+ mod_name,
+ tcx.sess.invocation_temp.as_deref(),
)
} else {
None
};
- let output_obj_file =
- Some(tcx.output_filenames(()).temp_path(OutputType::Object, Some(mod_name)));
+ let output_obj_file = Some(tcx.output_filenames(()).temp_path_for_cgu(
+ OutputType::Object,
+ mod_name,
+ tcx.sess.invocation_temp.as_deref(),
+ ));
let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file };
target_machine_factory(
@@ -330,8 +334,11 @@ pub(crate) fn save_temp_bitcode(
return;
}
let ext = format!("{name}.bc");
- let cgu = Some(&module.name[..]);
- let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
+ let path = cgcx.output_filenames.temp_path_ext_for_cgu(
+ &ext,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
write_bitcode_to_file(module, &path)
}
@@ -694,11 +701,12 @@ pub(crate) unsafe fn optimize(
let llcx = &*module.module_llvm.llcx;
let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt);
- let module_name = module.name.clone();
- let module_name = Some(&module_name[..]);
-
if config.emit_no_opt_bc {
- let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
+ let out = cgcx.output_filenames.temp_path_ext_for_cgu(
+ "no-opt.bc",
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
write_bitcode_to_file(module, &out)
}
@@ -743,8 +751,11 @@ pub(crate) unsafe fn optimize(
if let Some(thin_lto_buffer) = thin_lto_buffer {
let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) };
module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec());
- let bc_summary_out =
- cgcx.output_filenames.temp_path(OutputType::ThinLinkBitcode, module_name);
+ let bc_summary_out = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::ThinLinkBitcode,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
if config.emit_thin_lto_summary
&& let Some(thin_link_bitcode_filename) = bc_summary_out.file_name()
{
@@ -801,8 +812,6 @@ pub(crate) unsafe fn codegen(
let llmod = module.module_llvm.llmod();
let llcx = &*module.module_llvm.llcx;
let tm = &*module.module_llvm.tm;
- let module_name = module.name.clone();
- let module_name = Some(&module_name[..]);
let _handlers =
DiagnosticHandlers::new(cgcx, dcx, llcx, &module, CodegenDiagnosticsStage::Codegen);
@@ -814,8 +823,16 @@ pub(crate) unsafe fn codegen(
// copy it to the .o file, and delete the bitcode if it wasn't
// otherwise requested.
- let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
- let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
+ let bc_out = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::Bitcode,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
+ let obj_out = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::Object,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
if config.bitcode_needed() {
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
@@ -857,7 +874,11 @@ pub(crate) unsafe fn codegen(
if config.emit_ir {
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name);
- let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
+ let out = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::LlvmAssembly,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
let out_c = path_to_c_string(&out);
extern "C" fn demangle_callback(
@@ -899,7 +920,11 @@ extern "C" fn demangle_callback(
if config.emit_asm {
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name);
- let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
+ let path = cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::Assembly,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
// We can't use the same module for asm and object code output,
// because that triggers various errors like invalid IR or broken
@@ -929,7 +954,9 @@ extern "C" fn demangle_callback(
.prof
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name);
- let dwo_out = cgcx.output_filenames.temp_path_dwo(module_name);
+ let dwo_out = cgcx
+ .output_filenames
+ .temp_path_dwo_for_cgu(&module.name, cgcx.invocation_temp.as_deref());
let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) {
// Don't change how DWARF is emitted when disabled.
(SplitDebuginfo::Off, _) => None,
@@ -994,6 +1021,7 @@ extern "C" fn demangle_callback(
config.emit_asm,
config.emit_ir,
&cgcx.output_filenames,
+ cgcx.invocation_temp.as_deref(),
))
}
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 35134e9..27f7f95 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -123,7 +123,7 @@ pub(crate) fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
/// Empty string, to be used where LLVM expects an instruction name, indicating
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
-const UNNAMED: *const c_char = c"".as_ptr();
+pub(crate) const UNNAMED: *const c_char = c"".as_ptr();
impl<'ll, CX: Borrow<SCx<'ll>>> BackendTypes for GenericBuilder<'_, 'll, CX> {
type Value = <GenericCx<'ll, CX> as BackendTypes>::Value;
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index 5e7ef27..e7c071d 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -10,7 +10,7 @@
use tracing::{debug, trace};
use crate::back::write::llvm_err;
-use crate::builder::SBuilder;
+use crate::builder::{SBuilder, UNNAMED};
use crate::context::SimpleCx;
use crate::declare::declare_simple_fn;
use crate::errors::{AutoDiffWithoutEnable, LlvmError};
@@ -51,6 +51,7 @@ fn has_sret(fnc: &Value) -> bool {
// using iterators and peek()?
fn match_args_from_caller_to_enzyme<'ll>(
cx: &SimpleCx<'ll>,
+ builder: &SBuilder<'ll, 'll>,
width: u32,
args: &mut Vec<&'ll llvm::Value>,
inputs: &[DiffActivity],
@@ -78,7 +79,9 @@ fn match_args_from_caller_to_enzyme<'ll>(
let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap();
let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap();
let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap();
+ let enzyme_dupv = cx.create_metadata("enzyme_dupv".to_string()).unwrap();
let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap();
+ let enzyme_dupnoneedv = cx.create_metadata("enzyme_dupnoneedv".to_string()).unwrap();
while activity_pos < inputs.len() {
let diff_activity = inputs[activity_pos as usize];
@@ -90,13 +93,34 @@ fn match_args_from_caller_to_enzyme<'ll>(
DiffActivity::Active => (enzyme_out, false),
DiffActivity::ActiveOnly => (enzyme_out, false),
DiffActivity::Dual => (enzyme_dup, true),
+ DiffActivity::Dualv => (enzyme_dupv, true),
DiffActivity::DualOnly => (enzyme_dupnoneed, true),
+ DiffActivity::DualvOnly => (enzyme_dupnoneedv, true),
DiffActivity::Duplicated => (enzyme_dup, true),
DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true),
- DiffActivity::FakeActivitySize => (enzyme_const, false),
+ DiffActivity::FakeActivitySize(_) => (enzyme_const, false),
};
let outer_arg = outer_args[outer_pos];
args.push(cx.get_metadata_value(activity));
+ if matches!(diff_activity, DiffActivity::Dualv) {
+ let next_outer_arg = outer_args[outer_pos + 1];
+ let elem_bytes_size: u64 = match inputs[activity_pos + 1] {
+ DiffActivity::FakeActivitySize(Some(s)) => s.into(),
+ _ => bug!("incorrect Dualv handling recognized."),
+ };
+ // stride: sizeof(T) * n_elems.
+ // n_elems is the next integer.
+ // Now we multiply `4 * next_outer_arg` to get the stride.
+ let mul = unsafe {
+ llvm::LLVMBuildMul(
+ builder.llbuilder,
+ cx.get_const_i64(elem_bytes_size),
+ next_outer_arg,
+ UNNAMED,
+ )
+ };
+ args.push(mul);
+ }
args.push(outer_arg);
if duplicated {
// We know that duplicated args by construction have a following argument,
@@ -114,7 +138,7 @@ fn match_args_from_caller_to_enzyme<'ll>(
} else {
let next_activity = inputs[activity_pos + 1];
// We analyze the MIR types and add this dummy activity if we visit a slice.
- next_activity == DiffActivity::FakeActivitySize
+ matches!(next_activity, DiffActivity::FakeActivitySize(_))
}
};
if slice {
@@ -125,7 +149,10 @@ fn match_args_from_caller_to_enzyme<'ll>(
// int2 >= int1, which means the shadow vector is large enough to store the gradient.
assert_eq!(cx.type_kind(next_outer_ty), TypeKind::Integer);
- for i in 0..(width as usize) {
+ let iterations =
+ if matches!(diff_activity, DiffActivity::Dualv) { 1 } else { width as usize };
+
+ for i in 0..iterations {
let next_outer_arg2 = outer_args[outer_pos + 2 * (i + 1)];
let next_outer_ty2 = cx.val_ty(next_outer_arg2);
assert_eq!(cx.type_kind(next_outer_ty2), TypeKind::Pointer);
@@ -136,7 +163,7 @@ fn match_args_from_caller_to_enzyme<'ll>(
}
args.push(cx.get_metadata_value(enzyme_const));
args.push(next_outer_arg);
- outer_pos += 2 + 2 * width as usize;
+ outer_pos += 2 + 2 * iterations;
activity_pos += 2;
} else {
// A duplicated pointer will have the following two outer_fn arguments:
@@ -360,6 +387,7 @@ fn generate_enzyme_call<'ll>(
let outer_args: Vec<&llvm::Value> = get_params(outer_fn);
match_args_from_caller_to_enzyme(
&cx,
+ &builder,
attrs.width,
&mut args,
&attrs.input_activity,
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 457e545..a6f277e 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -4,8 +4,8 @@
use libc::{c_char, c_uint};
use rustc_abi as abi;
+use rustc_abi::HasDataLayout;
use rustc_abi::Primitive::Pointer;
-use rustc_abi::{AddressSpace, HasDataLayout};
use rustc_ast::Mutability;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::*;
@@ -269,7 +269,8 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) ->
}
Scalar::Ptr(ptr, _size) => {
let (prov, offset) = ptr.into_parts();
- let (base_addr, base_addr_space) = match self.tcx.global_alloc(prov.alloc_id()) {
+ let global_alloc = self.tcx.global_alloc(prov.alloc_id());
+ let base_addr = match global_alloc {
GlobalAlloc::Memory(alloc) => {
// For ZSTs directly codegen an aligned pointer.
// This avoids generating a zero-sized constant value and actually needing a
@@ -301,12 +302,10 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) ->
format!("alloc_{hash:032x}").as_bytes(),
);
}
- (value, AddressSpace::DATA)
+ value
}
}
- GlobalAlloc::Function { instance, .. } => {
- (self.get_fn_addr(instance), self.data_layout().instruction_address_space)
- }
+ GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance),
GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self
.tcx
@@ -319,14 +318,15 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) ->
.unwrap_memory();
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
let value = self.static_addr_of_impl(init, alloc.inner().align, None);
- (value, AddressSpace::DATA)
+ value
}
GlobalAlloc::Static(def_id) => {
assert!(self.tcx.is_static(def_id));
assert!(!self.tcx.is_thread_local_static(def_id));
- (self.get_static(def_id), AddressSpace::DATA)
+ self.get_static(def_id)
}
};
+ let base_addr_space = global_alloc.address_space(self);
let llval = unsafe {
llvm::LLVMConstInBoundsGEP2(
self.type_i8(),
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index f52991b..d259113 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -3,7 +3,6 @@
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::fx::FxHashMap;
-use rustc_index::Idx;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::{Body, SourceScope};
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
@@ -43,8 +42,7 @@ pub(crate) fn compute_mir_scopes<'ll, 'tcx>(
let mut instantiated = DenseBitSet::new_empty(mir.source_scopes.len());
let mut discriminators = FxHashMap::default();
// Instantiate all scopes.
- for idx in 0..mir.source_scopes.len() {
- let scope = SourceScope::new(idx);
+ for scope in mir.source_scopes.indices() {
make_mir_scope(
cx,
instance,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 2eaaf12..7f3e486 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -910,7 +910,8 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
&& let Some(f) = output_filenames.split_dwarf_path(
tcx.sess.split_debuginfo(),
tcx.sess.opts.unstable_opts.split_dwarf_kind,
- Some(codegen_unit_name),
+ codegen_unit_name,
+ tcx.sess.invocation_temp.as_deref(),
) {
// We get a path relative to the working directory from split_dwarf_path
Some(tcx.sess.source_map().path_mapping().to_real_filename(f))
@@ -1314,31 +1315,21 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
ty: Ty<'tcx>,
) -> SmallVec<Option<&'ll DIType>> {
if let ty::Adt(def, args) = *ty.kind() {
- let generics = cx.tcx.generics_of(def.did());
- return get_template_parameters(cx, generics, args);
- }
-
- return smallvec![];
-}
-
-pub(super) fn get_template_parameters<'ll, 'tcx>(
- cx: &CodegenCx<'ll, 'tcx>,
- generics: &ty::Generics,
- args: ty::GenericArgsRef<'tcx>,
-) -> SmallVec<Option<&'ll DIType>> {
- if args.types().next().is_some() {
- let names = get_parameter_names(cx, generics);
- let template_params: SmallVec<_> = iter::zip(args, names)
- .filter_map(|(kind, name)| {
- kind.as_type().map(|ty| {
- let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
- let actual_type_di_node = type_di_node(cx, actual_type);
- Some(cx.create_template_type_parameter(name.as_str(), actual_type_di_node))
+ if args.types().next().is_some() {
+ let generics = cx.tcx.generics_of(def.did());
+ let names = get_parameter_names(cx, generics);
+ let template_params: SmallVec<_> = iter::zip(args, names)
+ .filter_map(|(kind, name)| {
+ kind.as_type().map(|ty| {
+ let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
+ let actual_type_di_node = type_di_node(cx, actual_type);
+ Some(cx.create_template_type_parameter(name.as_str(), actual_type_di_node))
+ })
})
- })
- .collect();
+ .collect();
- return template_params;
+ return template_params;
+ }
}
return smallvec![];
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 6792c30..7c70192 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -363,7 +363,6 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
state_specific_fields.into_iter().chain(common_fields).collect()
},
- // FIXME: this is a no-op. `build_generic_type_param_di_nodes` only works for Adts.
|cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty),
)
.di_node
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index ae2ab32..56fb12d 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -247,6 +247,16 @@ pub(super) fn stub<'ll, 'tcx>(
StubInfo { metadata, unique_type_id }
}
+struct AdtStackPopGuard<'ll, 'tcx, 'a> {
+ cx: &'a CodegenCx<'ll, 'tcx>,
+}
+
+impl<'ll, 'tcx, 'a> Drop for AdtStackPopGuard<'ll, 'tcx, 'a> {
+ fn drop(&mut self) {
+ debug_context(self.cx).adt_stack.borrow_mut().pop();
+ }
+}
+
/// This function enables creating debuginfo nodes that can recursively refer to themselves.
/// It will first insert the given stub into the type map and only then execute the `members`
/// and `generics` closures passed in. These closures have access to the stub so they can
@@ -261,6 +271,44 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
) -> DINodeCreationResult<'ll> {
assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None);
+ let mut _adt_stack_pop_guard = None;
+ if let UniqueTypeId::Ty(ty, ..) = stub_info.unique_type_id
+ && let ty::Adt(adt_def, args) = ty.kind()
+ {
+ let def_id = adt_def.did();
+ // If any sub type reference the original type definition and the sub type has a type
+ // parameter that strictly contains the original parameter, the original type is a recursive
+ // type that can expanding indefinitely. Example,
+ // ```
+ // enum Recursive<T> {
+ // Recurse(*const Recursive<Wrap<T>>),
+ // Item(T),
+ // }
+ // ```
+ let is_expanding_recursive =
+ debug_context(cx).adt_stack.borrow().iter().any(|(parent_def_id, parent_args)| {
+ if def_id == *parent_def_id {
+ args.iter().zip(parent_args.iter()).any(|(arg, parent_arg)| {
+ if let (Some(arg), Some(parent_arg)) = (arg.as_type(), parent_arg.as_type())
+ {
+ arg != parent_arg && arg.contains(parent_arg)
+ } else {
+ false
+ }
+ })
+ } else {
+ false
+ }
+ });
+ if is_expanding_recursive {
+ // FIXME: indicate that this is an expanding recursive type in stub metadata?
+ return DINodeCreationResult::new(stub_info.metadata, false);
+ } else {
+ debug_context(cx).adt_stack.borrow_mut().push((def_id, args));
+ _adt_stack_pop_guard = Some(AdtStackPopGuard { cx });
+ }
+ }
+
debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata);
let members: SmallVec<_> =
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index ae7d080..c508592 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -2,8 +2,8 @@
use std::cell::{OnceCell, RefCell};
use std::ops::Range;
-use std::ptr;
use std::sync::Arc;
+use std::{iter, ptr};
use libc::c_uint;
use metadata::create_subroutine_type;
@@ -66,6 +66,7 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
type_map: metadata::TypeMap<'ll, 'tcx>,
+ adt_stack: RefCell<Vec<(DefId, GenericArgsRef<'tcx>)>>,
namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
recursion_marker_type: OnceCell<&'ll DIType>,
}
@@ -80,6 +81,7 @@ pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
builder,
created_files: Default::default(),
type_map: Default::default(),
+ adt_stack: Default::default(),
namespace_map: RefCell::new(Default::default()),
recursion_marker_type: OnceCell::new(),
}
@@ -486,10 +488,40 @@ fn get_template_parameters<'ll, 'tcx>(
generics: &ty::Generics,
args: GenericArgsRef<'tcx>,
) -> &'ll DIArray {
- let template_params = metadata::get_template_parameters(cx, generics, args);
+ if args.types().next().is_none() {
+ return create_DIArray(DIB(cx), &[]);
+ }
+
+ // Again, only create type information if full debuginfo is enabled
+ let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
+ let names = get_parameter_names(cx, generics);
+ iter::zip(args, names)
+ .filter_map(|(kind, name)| {
+ kind.as_type().map(|ty| {
+ let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
+ let actual_type_metadata = type_di_node(cx, actual_type);
+ Some(cx.create_template_type_parameter(
+ name.as_str(),
+ actual_type_metadata,
+ ))
+ })
+ })
+ .collect()
+ } else {
+ vec![]
+ };
+
create_DIArray(DIB(cx), &template_params)
}
+ fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
+ let mut names = generics.parent.map_or_else(Vec::new, |def_id| {
+ get_parameter_names(cx, cx.tcx.generics_of(def_id))
+ });
+ names.extend(generics.own_params.iter().map(|param| param.name));
+ names
+ }
+
/// Returns a scope, plus `true` if that's a type scope for "class" methods,
/// otherwise `false` for plain namespace scopes.
fn get_containing_scope<'ll, 'tcx>(
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 1d05c4e..8de6892 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -112,8 +112,12 @@ pub fn link_binary(
codegen_results.crate_info.local_crate_name,
);
let crate_name = format!("{}", codegen_results.crate_info.local_crate_name);
- let out_filename =
- output.file_for_writing(outputs, OutputType::Exe, Some(crate_name.as_str()));
+ let out_filename = output.file_for_writing(
+ outputs,
+ OutputType::Exe,
+ &crate_name,
+ sess.invocation_temp.as_deref(),
+ );
match crate_type {
CrateType::Rlib => {
let _timer = sess.timer("link_rlib");
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index e816e71..0fd4ed8 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -306,14 +306,18 @@ pub fn new(
cgcx.output_filenames.split_dwarf_path(
cgcx.split_debuginfo,
cgcx.split_dwarf_kind,
- Some(module_name),
+ module_name,
+ cgcx.invocation_temp.as_deref(),
)
} else {
None
};
- let output_obj_file =
- Some(cgcx.output_filenames.temp_path(OutputType::Object, Some(module_name)));
+ let output_obj_file = Some(cgcx.output_filenames.temp_path_for_cgu(
+ OutputType::Object,
+ module_name,
+ cgcx.invocation_temp.as_deref(),
+ ));
TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }
}
}
@@ -344,6 +348,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub crate_types: Vec<CrateType>,
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
pub output_filenames: Arc<OutputFilenames>,
+ pub invocation_temp: Option<String>,
pub regular_module_config: Arc<ModuleConfig>,
pub metadata_module_config: Arc<ModuleConfig>,
pub allocator_module_config: Arc<ModuleConfig>,
@@ -582,8 +587,11 @@ fn produce_final_output_artifacts(
if let [module] = &compiled_modules.modules[..] {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
- let module_name = Some(&module.name[..]);
- let path = crate_output.temp_path(output_type, module_name);
+ let path = crate_output.temp_path_for_cgu(
+ output_type,
+ &module.name,
+ sess.invocation_temp.as_deref(),
+ );
let output = crate_output.path(output_type);
if !output_type.is_text_output() && output.is_tty() {
sess.dcx()
@@ -596,22 +604,15 @@ fn produce_final_output_artifacts(
ensure_removed(sess.dcx(), &path);
}
} else {
- let extension = crate_output
- .temp_path(output_type, None)
- .extension()
- .unwrap()
- .to_str()
- .unwrap()
- .to_owned();
-
if crate_output.outputs.contains_explicit_name(&output_type) {
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
// no good solution for this case, so warn the user.
- sess.dcx().emit_warn(errors::IgnoringEmitPath { extension });
+ sess.dcx()
+ .emit_warn(errors::IgnoringEmitPath { extension: output_type.extension() });
} else if crate_output.single_output_file.is_some() {
// 3) Multiple codegen units, with `-o some_name`. We have
// no good solution for this case, so warn the user.
- sess.dcx().emit_warn(errors::IgnoringOutput { extension });
+ sess.dcx().emit_warn(errors::IgnoringOutput { extension: output_type.extension() });
} else {
// 4) Multiple codegen units, but no explicit name. We
// just leave the `foo.0.x` files in place.
@@ -967,7 +968,12 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
let dwarf_obj_out = cgcx
.output_filenames
- .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, Some(&module.name))
+ .split_dwarf_path(
+ cgcx.split_debuginfo,
+ cgcx.split_dwarf_kind,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ )
.expect(
"saved dwarf object in work product but `split_dwarf_path` returned `None`",
);
@@ -977,7 +983,11 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
let mut load_from_incr_cache = |perform, output_type: OutputType| {
if perform {
let saved_file = module.source.saved_files.get(output_type.extension())?;
- let output_path = cgcx.output_filenames.temp_path(output_type, Some(&module.name));
+ let output_path = cgcx.output_filenames.temp_path_for_cgu(
+ output_type,
+ &module.name,
+ cgcx.invocation_temp.as_deref(),
+ );
load_from_incr_comp_dir(output_path, &saved_file)
} else {
None
@@ -1222,6 +1232,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
pointer_size: tcx.data_layout.pointer_size,
+ invocation_temp: sess.invocation_temp.clone(),
};
// This is the "main loop" of parallel work happening for parallel codegen.
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 1985b3b..12b7a48 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -10,7 +10,7 @@
use rustc_attr_parsing::OptimizeAttr;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
-use rustc_data_structures::sync::par_map;
+use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
@@ -640,8 +640,11 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
let metadata_cgu_name =
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
tcx.sess.time("write_compressed_metadata", || {
- let file_name =
- tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
+ let file_name = tcx.output_filenames(()).temp_path_for_cgu(
+ OutputType::Metadata,
+ &metadata_cgu_name,
+ tcx.sess.invocation_temp.as_deref(),
+ );
let data = create_compressed_metadata_file(
tcx.sess,
&metadata,
@@ -757,7 +760,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
let pre_compiled_cgus = par_map(cgus, |(i, _)| {
let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
- (i, module)
+ (i, IntoDynSyncSend(module))
});
total_codegen_time += start_time.elapsed();
@@ -777,7 +780,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
match cgu_reuse {
CguReuse::No => {
let (module, cost) = if let Some(cgu) = pre_compiled_cgus.remove(&i) {
- cgu
+ cgu.0
} else {
let start_time = Instant::now();
let module = backend.compile_codegen_unit(tcx, cgu.name());
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index ddb6118..b0c53ec 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -114,7 +114,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
AttributeKind::Repr(reprs) => {
codegen_fn_attrs.alignment = reprs
.iter()
- .find_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None });
+ .filter_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None })
+ .max();
}
_ => {}
@@ -345,20 +346,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
no_sanitize_span = Some(attr.span());
if let Some(list) = attr.meta_item_list() {
for item in list.iter() {
- match item.name_or_empty() {
- sym::address => {
+ match item.name() {
+ Some(sym::address) => {
codegen_fn_attrs.no_sanitize |=
SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
}
- sym::cfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
- sym::kcfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
- sym::memory => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY,
- sym::memtag => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG,
- sym::shadow_call_stack => {
+ Some(sym::cfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
+ Some(sym::kcfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
+ Some(sym::memory) => {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY
+ }
+ Some(sym::memtag) => {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG
+ }
+ Some(sym::shadow_call_stack) => {
codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK
}
- sym::thread => codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD,
- sym::hwaddress => {
+ Some(sym::thread) => {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD
+ }
+ Some(sym::hwaddress) => {
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
}
_ => {
@@ -419,9 +426,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
continue;
};
- let attrib_to_write = match meta_item.name_or_empty() {
- sym::prefix_nops => &mut prefix,
- sym::entry_nops => &mut entry,
+ let attrib_to_write = match meta_item.name() {
+ Some(sym::prefix_nops) => &mut prefix,
+ Some(sym::entry_nops) => &mut entry,
_ => {
tcx.dcx().emit_err(errors::UnexpectedParameterName {
span: item.span(),
@@ -785,8 +792,7 @@ fn lint_if_mixed(self, tcx: TyCtxt<'_>) {
fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
let attrs = tcx.get_attrs(id, sym::rustc_autodiff);
- let attrs =
- attrs.filter(|attr| attr.name_or_empty() == sym::rustc_autodiff).collect::<Vec<_>>();
+ let attrs = attrs.filter(|attr| attr.has_name(sym::rustc_autodiff)).collect::<Vec<_>>();
// check for exactly one autodiff attribute on placeholder functions.
// There should only be one, since we generate a new placeholder per ad macro.
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index b33de88..42cea5c8 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -277,13 +277,13 @@ pub struct BinaryOutputToTty {
#[derive(Diagnostic)]
#[diag(codegen_ssa_ignoring_emit_path)]
pub struct IgnoringEmitPath {
- pub extension: String,
+ pub extension: &'static str,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_ignoring_output)]
pub struct IgnoringOutput {
- pub extension: String,
+ pub extension: &'static str,
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 6721792..5b2ed69 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -2,7 +2,6 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@@ -105,13 +104,19 @@ pub fn into_compiled_module(
emit_asm: bool,
emit_ir: bool,
outputs: &OutputFilenames,
+ invocation_temp: Option<&str>,
) -> CompiledModule {
- let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name)));
- let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo(Some(&self.name)));
- let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name)));
- let assembly = emit_asm.then(|| outputs.temp_path(OutputType::Assembly, Some(&self.name)));
- let llvm_ir =
- emit_ir.then(|| outputs.temp_path(OutputType::LlvmAssembly, Some(&self.name)));
+ let object = emit_obj
+ .then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name, invocation_temp));
+ let dwarf_object =
+ emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name, invocation_temp));
+ let bytecode = emit_bc
+ .then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name, invocation_temp));
+ let assembly = emit_asm
+ .then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name, invocation_temp));
+ let llvm_ir = emit_ir.then(|| {
+ outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name, invocation_temp)
+ });
CompiledModule {
name: self.name.clone(),
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 2b74c84..b600b89 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -34,7 +34,7 @@
use crate::errors;
type QualifResults<'mir, 'tcx, Q> =
- rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
+ rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'tcx, Q>>;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum ConstConditionsHold {
diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs
index 8cee282..9f7fcc5 100644
--- a/compiler/rustc_const_eval/src/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs
@@ -22,17 +22,17 @@
/// qualified immediately after it is borrowed or its address escapes. The borrow must allow for
/// mutation, which includes shared borrows of places with interior mutability. The type of
/// borrowed place must contain the qualif.
-struct TransferFunction<'a, 'mir, 'tcx, Q> {
- ccx: &'a ConstCx<'mir, 'tcx>,
- state: &'a mut State,
+struct TransferFunction<'mir, 'tcx, Q> {
+ ccx: &'mir ConstCx<'mir, 'tcx>,
+ state: &'mir mut State,
_qualif: PhantomData<Q>,
}
-impl<'a, 'mir, 'tcx, Q> TransferFunction<'a, 'mir, 'tcx, Q>
+impl<'mir, 'tcx, Q> TransferFunction<'mir, 'tcx, Q>
where
Q: Qualif,
{
- fn new(ccx: &'a ConstCx<'mir, 'tcx>, state: &'a mut State) -> Self {
+ fn new(ccx: &'mir ConstCx<'mir, 'tcx>, state: &'mir mut State) -> Self {
TransferFunction { ccx, state, _qualif: PhantomData }
}
@@ -124,7 +124,7 @@ fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
}
}
-impl<'tcx, Q> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx, Q>
+impl<'tcx, Q> Visitor<'tcx> for TransferFunction<'_, 'tcx, Q>
where
Q: Qualif,
{
@@ -228,20 +228,20 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
}
/// The dataflow analysis used to propagate qualifs on arbitrary CFGs.
-pub(super) struct FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q> {
- ccx: &'a ConstCx<'mir, 'tcx>,
+pub(super) struct FlowSensitiveAnalysis<'mir, 'tcx, Q> {
+ ccx: &'mir ConstCx<'mir, 'tcx>,
_qualif: PhantomData<Q>,
}
-impl<'a, 'mir, 'tcx, Q> FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q>
+impl<'mir, 'tcx, Q> FlowSensitiveAnalysis<'mir, 'tcx, Q>
where
Q: Qualif,
{
- pub(super) fn new(_: Q, ccx: &'a ConstCx<'mir, 'tcx>) -> Self {
+ pub(super) fn new(_: Q, ccx: &'mir ConstCx<'mir, 'tcx>) -> Self {
FlowSensitiveAnalysis { ccx, _qualif: PhantomData }
}
- fn transfer_function(&self, state: &'a mut State) -> TransferFunction<'a, 'mir, 'tcx, Q> {
+ fn transfer_function(&self, state: &'mir mut State) -> TransferFunction<'mir, 'tcx, Q> {
TransferFunction::<Q>::new(self.ccx, state)
}
}
@@ -313,7 +313,7 @@ fn join(&mut self, other: &Self) -> bool {
}
}
-impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
+impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, 'tcx, Q>
where
Q: Qualif,
{
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index e2675e2..6472aaa 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -6,7 +6,7 @@
use rustc_errors::codes::*;
use rustc_errors::{
Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level,
- MultiSpan, SubdiagMessageOp, Subdiagnostic,
+ MultiSpan, Subdiagnostic,
};
use rustc_hir::ConstContext;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -290,11 +290,7 @@ pub struct FrameNote {
}
impl Subdiagnostic for FrameNote {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("times", self.times);
diag.arg("where_", self.where_);
diag.arg("instance", self.instance);
@@ -302,7 +298,7 @@ fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
if self.has_label && !self.span.is_dummy() {
span.push_span_label(self.span, fluent::const_eval_frame_note_last);
}
- let msg = f(diag, fluent::const_eval_frame_note.into());
+ let msg = diag.eagerly_translate(fluent::const_eval_frame_note);
diag.span_note(span, msg);
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index c1948e9..b69bc09 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -268,7 +268,7 @@ pub fn load_mir(
/// Call this on things you got out of the MIR (so it is as generic as the current
/// stack frame), to bring it into the proper environment for this interpreter.
- pub(super) fn instantiate_from_current_frame_and_normalize_erasing_regions<
+ pub fn instantiate_from_current_frame_and_normalize_erasing_regions<
T: TypeFoldable<TyCtxt<'tcx>>,
>(
&self,
@@ -279,9 +279,7 @@ pub(super) fn instantiate_from_current_frame_and_normalize_erasing_regions<
/// Call this on things you got out of the MIR (so it is as generic as the provided
/// stack frame), to bring it into the proper environment for this interpreter.
- pub(super) fn instantiate_from_frame_and_normalize_erasing_regions<
- T: TypeFoldable<TyCtxt<'tcx>>,
- >(
+ pub fn instantiate_from_frame_and_normalize_erasing_regions<T: TypeFoldable<TyCtxt<'tcx>>>(
&self,
frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
value: T,
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index e4b2fe5..8f0cb19 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -30,6 +30,7 @@
AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, err_ub, interp_ok,
};
use crate::const_eval;
+use crate::const_eval::DummyMachine;
use crate::errors::NestedStaticInThreadLocal;
pub trait CompileTimeMachine<'tcx, T> = Machine<
@@ -323,14 +324,17 @@ pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>>
interp_ok(())
}
-impl<'tcx, M: super::intern::CompileTimeMachine<'tcx, !>> InterpCx<'tcx, M> {
+impl<'tcx> InterpCx<'tcx, DummyMachine> {
/// A helper function that allocates memory for the layout given and gives you access to mutate
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
/// current `Memory` and interned as read-only into the global memory.
pub fn intern_with_temp_alloc(
&mut self,
layout: TyAndLayout<'tcx>,
- f: impl FnOnce(&mut InterpCx<'tcx, M>, &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, ()>,
+ f: impl FnOnce(
+ &mut InterpCx<'tcx, DummyMachine>,
+ &PlaceTy<'tcx, CtfeProvenance>,
+ ) -> InterpResult<'tcx, ()>,
) -> InterpResult<'tcx, AllocId> {
// `allocate` picks a fresh AllocId that we will associate with its data below.
let dest = self.allocate(layout, MemoryKind::Stack)?;
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index e03849c..da52d60 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -1,7 +1,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(box_patterns)]
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index fcaf275..f48c73b 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -14,7 +14,7 @@
jobserver_crate = { version = "0.1.28", package = "jobserver" }
measureme = "12.0.1"
rustc-hash = "2.0.0"
-rustc-rayon = { version = "0.5.1", features = ["indexmap"] }
+rustc-rayon-core = { version = "0.5.0" }
rustc-stable-hash = { version = "0.1.0", features = ["nightly"] }
rustc_arena = { path = "../rustc_arena" }
rustc_graphviz = { path = "../rustc_graphviz" }
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index 64c64bf..5f07cfe 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -1,13 +1,13 @@
use std::alloc::Allocator;
-#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
+#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")]
// This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
// is true. These types can be wrapped in a `FromDyn` to get a `Send` type. Wrapping a
// `Send` type in `IntoDynSyncSend` will create a `DynSend` type.
pub unsafe auto trait DynSend {}
-#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSync`. \
+#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSync`. \
Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Sync`")]
// This is an auto trait for types which can be shared across threads if `sync::is_dyn_thread_safe()`
// is true. These types can be wrapped in a `FromDyn` to get a `Sync` type. Wrapping a
@@ -180,6 +180,12 @@ pub fn from(val: T) -> Self {
}
#[inline(always)]
+ pub fn derive<O>(&self, val: O) -> FromDyn<O> {
+ // We already did the check for `sync::is_dyn_thread_safe()` when creating `Self`
+ FromDyn(val)
+ }
+
+ #[inline(always)]
pub fn into_inner(self) -> T {
self.0
}
@@ -200,6 +206,13 @@ fn deref(&self) -> &Self::Target {
}
}
+impl<T> std::ops::DerefMut for FromDyn<T> {
+ #[inline(always)]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
// A wrapper to convert a struct that is already a `Send` or `Sync` into
// an instance of `DynSend` and `DynSync`, since the compiler cannot infer
// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs
index 8ef8a3f..ba3c85e 100644
--- a/compiler/rustc_data_structures/src/sync/parallel.rs
+++ b/compiler/rustc_data_structures/src/sync/parallel.rs
@@ -7,7 +7,6 @@
use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
use parking_lot::Mutex;
-use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
use crate::FatalErrorMarker;
use crate::sync::{DynSend, DynSync, FromDyn, IntoDynSyncSend, mode};
@@ -97,11 +96,11 @@ macro_rules! parallel {
// This function only works when `mode::is_dyn_thread_safe()`.
pub fn scope<'scope, OP, R>(op: OP) -> R
where
- OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend,
+ OP: FnOnce(&rayon_core::Scope<'scope>) -> R + DynSend,
R: DynSend,
{
let op = FromDyn::from(op);
- rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner()
+ rayon_core::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner()
}
#[inline]
@@ -114,7 +113,7 @@ pub fn join<A, B, RA: DynSend, RB: DynSend>(oper_a: A, oper_b: B) -> (RA, RB)
let oper_a = FromDyn::from(oper_a);
let oper_b = FromDyn::from(oper_b);
let (a, b) = parallel_guard(|guard| {
- rayon::join(
+ rayon_core::join(
move || guard.run(move || FromDyn::from(oper_a.into_inner()())),
move || guard.run(move || FromDyn::from(oper_b.into_inner()())),
)
@@ -125,56 +124,103 @@ pub fn join<A, B, RA: DynSend, RB: DynSend>(oper_a: A, oper_b: B) -> (RA, RB)
}
}
-pub fn par_for_each_in<I, T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>>(
+fn par_slice<I: DynSend>(
+ items: &mut [I],
+ guard: &ParallelGuard,
+ for_each: impl Fn(&mut I) + DynSync + DynSend,
+) {
+ struct State<'a, F> {
+ for_each: FromDyn<F>,
+ guard: &'a ParallelGuard,
+ group: usize,
+ }
+
+ fn par_rec<I: DynSend, F: Fn(&mut I) + DynSync + DynSend>(
+ items: &mut [I],
+ state: &State<'_, F>,
+ ) {
+ if items.len() <= state.group {
+ for item in items {
+ state.guard.run(|| (state.for_each)(item));
+ }
+ } else {
+ let (left, right) = items.split_at_mut(items.len() / 2);
+ let mut left = state.for_each.derive(left);
+ let mut right = state.for_each.derive(right);
+ rayon_core::join(move || par_rec(*left, state), move || par_rec(*right, state));
+ }
+ }
+
+ let state = State {
+ for_each: FromDyn::from(for_each),
+ guard,
+ group: std::cmp::max(items.len() / 128, 1),
+ };
+ par_rec(items, &state)
+}
+
+pub fn par_for_each_in<I: DynSend, T: IntoIterator<Item = I>>(
t: T,
- for_each: impl Fn(I) + DynSync + DynSend,
+ for_each: impl Fn(&I) + DynSync + DynSend,
) {
parallel_guard(|guard| {
if mode::is_dyn_thread_safe() {
- let for_each = FromDyn::from(for_each);
- t.into_par_iter().for_each(|i| {
- guard.run(|| for_each(i));
- });
+ let mut items: Vec<_> = t.into_iter().collect();
+ par_slice(&mut items, guard, |i| for_each(&*i))
} else {
t.into_iter().for_each(|i| {
- guard.run(|| for_each(i));
+ guard.run(|| for_each(&i));
});
}
});
}
-pub fn try_par_for_each_in<
- T: IntoIterator + IntoParallelIterator<Item = <T as IntoIterator>::Item>,
- E: Send,
->(
+/// This runs `for_each` in parallel for each iterator item. If one or more of the
+/// `for_each` calls returns `Err`, the function will also return `Err`. The error returned
+/// will be non-deterministic, but this is expected to be used with `ErrorGuaranteed` which
+/// are all equivalent.
+pub fn try_par_for_each_in<T: IntoIterator, E: DynSend>(
t: T,
- for_each: impl Fn(<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend,
-) -> Result<(), E> {
+ for_each: impl Fn(&<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend,
+) -> Result<(), E>
+where
+ <T as IntoIterator>::Item: DynSend,
+{
parallel_guard(|guard| {
if mode::is_dyn_thread_safe() {
- let for_each = FromDyn::from(for_each);
- t.into_par_iter()
- .filter_map(|i| guard.run(|| for_each(i)))
- .reduce(|| Ok(()), Result::and)
+ let mut items: Vec<_> = t.into_iter().collect();
+
+ let error = Mutex::new(None);
+
+ par_slice(&mut items, guard, |i| {
+ if let Err(err) = for_each(&*i) {
+ *error.lock() = Some(err);
+ }
+ });
+
+ if let Some(err) = error.into_inner() { Err(err) } else { Ok(()) }
} else {
- t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and)
+ t.into_iter().filter_map(|i| guard.run(|| for_each(&i))).fold(Ok(()), Result::and)
}
})
}
-pub fn par_map<
- I,
- T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>,
- R: std::marker::Send,
- C: FromIterator<R> + FromParallelIterator<R>,
->(
+pub fn par_map<I: DynSend, T: IntoIterator<Item = I>, R: DynSend, C: FromIterator<R>>(
t: T,
map: impl Fn(I) -> R + DynSync + DynSend,
) -> C {
parallel_guard(|guard| {
if mode::is_dyn_thread_safe() {
let map = FromDyn::from(map);
- t.into_par_iter().filter_map(|i| guard.run(|| map(i))).collect()
+
+ let mut items: Vec<(Option<I>, Option<R>)> =
+ t.into_iter().map(|i| (Some(i), None)).collect();
+
+ par_slice(&mut items, guard, |i| {
+ i.1 = Some(map(i.0.take().unwrap()));
+ });
+
+ items.into_iter().filter_map(|i| i.1).collect()
} else {
t.into_iter().filter_map(|i| guard.run(|| map(i))).collect()
}
diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs
index baa66cd..3d44fb1 100644
--- a/compiler/rustc_data_structures/src/unord.rs
+++ b/compiler/rustc_data_structures/src/unord.rs
@@ -109,6 +109,16 @@ pub fn flat_map<U, F, O>(self, f: F) -> UnordItems<O, impl Iterator<Item = O>>
pub fn collect<C: From<UnordItems<T, I>>>(self) -> C {
self.into()
}
+
+ /// If the iterator has only one element, returns it, otherwise returns `None`.
+ #[track_caller]
+ pub fn get_only(mut self) -> Option<T> {
+ let item = self.0.next();
+ if self.0.next().is_some() {
+ return None;
+ }
+ item
+ }
}
impl<T> UnordItems<T, std::iter::Empty<T>> {
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 381309f..a03834c 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -3,7 +3,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index de64335..c823d11 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -4,6 +4,7 @@
edition = "2024"
[dependencies]
+jiff = { version = "0.2.5", default-features = false, features = ["std"] }
# tidy-alphabetical-start
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
@@ -50,7 +51,6 @@
rustc_ty_utils = { path = "../rustc_ty_utils" }
serde_json = "1.0.59"
shlex = "1.0"
-time = { version = "0.3.36", default-features = false, features = ["alloc", "formatting", "macros"] }
tracing = { version = "0.1.35" }
# tidy-alphabetical-end
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 7d9560a..40cc827 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -7,7 +7,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(decl_macro)]
@@ -30,7 +29,7 @@
use std::process::{self, Command, Stdio};
use std::sync::OnceLock;
use std::sync::atomic::{AtomicBool, Ordering};
-use std::time::{Instant, SystemTime};
+use std::time::Instant;
use std::{env, str};
use rustc_ast as ast;
@@ -66,8 +65,6 @@
use rustc_span::def_id::LOCAL_CRATE;
use rustc_target::json::ToJson;
use rustc_target::spec::{Target, TargetTuple};
-use time::OffsetDateTime;
-use time::macros::format_description;
use tracing::trace;
#[allow(unused_macros)]
@@ -1301,13 +1298,8 @@ fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<Pat
.or_else(|| std::env::current_dir().ok())
.unwrap_or_default(),
};
- let now: OffsetDateTime = SystemTime::now().into();
- let file_now = now
- .format(
- // Don't use a standard datetime format because Windows doesn't support `:` in paths
- &format_description!("[year]-[month]-[day]T[hour]_[minute]_[second]"),
- )
- .unwrap_or_default();
+ // Don't use a standard datetime format because Windows doesn't support `:` in paths
+ let file_now = jiff::Zoned::now().strftime("%Y-%m-%dT%H_%M_%S");
let pid = std::process::id();
path.push(format!("rustc-ice-{file_now}-{pid}.txt"));
Some(path)
diff --git a/compiler/rustc_error_codes/src/error_codes/E0755.md b/compiler/rustc_error_codes/src/error_codes/E0755.md
index 88b7f48..b67f078 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0755.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0755.md
@@ -5,7 +5,7 @@
```compile_fail,E0755
#![feature(ffi_pure)]
-#[ffi_pure] // error!
+#[unsafe(ffi_pure)] // error!
pub fn foo() {}
# fn main() {}
```
@@ -17,7 +17,7 @@
#![feature(ffi_pure)]
extern "C" {
- #[ffi_pure] // ok!
+ #[unsafe(ffi_pure)] // ok!
pub fn strlen(s: *const i8) -> isize;
}
# fn main() {}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0756.md b/compiler/rustc_error_codes/src/error_codes/E0756.md
index ffdc421..aadde03 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0756.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0756.md
@@ -6,7 +6,7 @@
```compile_fail,E0756
#![feature(ffi_const)]
-#[ffi_const] // error!
+#[unsafe(ffi_const)] // error!
pub fn foo() {}
# fn main() {}
```
@@ -18,7 +18,7 @@
#![feature(ffi_const)]
extern "C" {
- #[ffi_const] // ok!
+ #[unsafe(ffi_const)] // ok!
pub fn strlen(s: *const i8) -> i32;
}
# fn main() {}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0757.md b/compiler/rustc_error_codes/src/error_codes/E0757.md
index 41b06b2..fb75b02 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0757.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0757.md
@@ -6,8 +6,9 @@
#![feature(ffi_const, ffi_pure)]
extern "C" {
- #[ffi_const]
- #[ffi_pure] // error: `#[ffi_const]` function cannot be `#[ffi_pure]`
+ #[unsafe(ffi_const)]
+ #[unsafe(ffi_pure)]
+ //~^ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]`
pub fn square(num: i32) -> i32;
}
```
@@ -19,7 +20,7 @@
#![feature(ffi_const)]
extern "C" {
- #[ffi_const]
+ #[unsafe(ffi_const)]
pub fn square(num: i32) -> i32;
}
```
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index bd13c41..539ecfb 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -181,22 +181,9 @@ pub trait Subdiagnostic
Self: Sized,
{
/// Add a subdiagnostic to an existing diagnostic.
- fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
- self.add_to_diag_with(diag, &|_, m| m);
- }
-
- /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
- /// (to optionally perform eager translation).
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- );
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
}
-pub trait SubdiagMessageOp<G: EmissionGuarantee> =
- Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagMessage;
-
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
#[rustc_diagnostic_item = "LintDiagnostic"]
@@ -1227,15 +1214,21 @@ pub fn tool_only_span_suggestion(
/// interpolated variables).
#[rustc_lint_diagnostics]
pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
- let dcx = self.dcx;
- subdiagnostic.add_to_diag_with(self, &|diag, msg| {
- let args = diag.args.iter();
- let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
- dcx.eagerly_translate(msg, args)
- });
+ subdiagnostic.add_to_diag(self);
self
}
+ /// Fluent variables are not namespaced from each other, so when
+ /// `Diagnostic`s and `Subdiagnostic`s use the same variable name,
+ /// one value will clobber the other. Eagerly translating the
+ /// diagnostic uses the variables defined right then, before the
+ /// clobbering occurs.
+ pub fn eagerly_translate(&self, msg: impl Into<SubdiagMessage>) -> SubdiagMessage {
+ let args = self.args.iter();
+ let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into());
+ self.dcx.eagerly_translate(msg, args)
+ }
+
with_fn! { with_span,
/// Add a span.
#[rustc_lint_diagnostics]
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index cb2e176..8b59ba9 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -19,7 +19,7 @@
use crate::diagnostic::DiagLocation;
use crate::{
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, ErrCode, IntoDiagArg, Level,
- SubdiagMessageOp, Subdiagnostic, fluent_generated as fluent,
+ Subdiagnostic, fluent_generated as fluent,
};
pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
@@ -384,11 +384,7 @@ pub struct SingleLabelManySpans {
pub label: &'static str,
}
impl Subdiagnostic for SingleLabelManySpans {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.span_labels(self.spans, self.label);
}
}
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 75bb0e8..c0c5dba 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -47,7 +47,7 @@
pub use diagnostic::{
BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString,
Diagnostic, EmissionGuarantee, FatalAbort, IntoDiagArg, LintDiagnostic, StringPart, Subdiag,
- SubdiagMessageOp, Subdiagnostic,
+ Subdiagnostic,
};
pub use diagnostic_impls::{
DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 49f6d58..f5eaf7d 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -824,10 +824,10 @@ fn collapse_debuginfo_by_name(
return Err(item.span);
}
- match item.name_or_empty() {
- sym::no => Ok(CollapseMacroDebuginfo::No),
- sym::external => Ok(CollapseMacroDebuginfo::External),
- sym::yes => Ok(CollapseMacroDebuginfo::Yes),
+ match item.name() {
+ Some(sym::no) => Ok(CollapseMacroDebuginfo::No),
+ Some(sym::external) => Ok(CollapseMacroDebuginfo::External),
+ Some(sym::yes) => Ok(CollapseMacroDebuginfo::Yes),
_ => Err(item.path.span),
}
}
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index bcc2703..c70e259 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -238,18 +238,6 @@ fn can_skip(stream: &AttrTokenStream) -> bool {
Some(AttrTokenTree::Delimited(sp, spacing, delim, inner))
}
AttrTokenTree::Token(
- Token {
- kind:
- TokenKind::NtIdent(..)
- | TokenKind::NtLifetime(..)
- | TokenKind::Interpolated(..),
- ..
- },
- _,
- ) => {
- panic!("Nonterminal should have been flattened: {:?}", tree);
- }
- AttrTokenTree::Token(
Token { kind: TokenKind::OpenDelim(_) | TokenKind::CloseDelim(_), .. },
_,
) => {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 1b53947..1e26d66 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -2053,8 +2053,8 @@ fn flat_map_node<Node: InvocationCollectorNode<OutputTy: Default>>(
) -> Node::OutputTy {
loop {
return match self.take_first_attr(&mut node) {
- Some((attr, pos, derives)) => match attr.name_or_empty() {
- sym::cfg => {
+ Some((attr, pos, derives)) => match attr.name() {
+ Some(sym::cfg) => {
let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos);
if res {
continue;
@@ -2071,7 +2071,7 @@ fn flat_map_node<Node: InvocationCollectorNode<OutputTy: Default>>(
}
Default::default()
}
- sym::cfg_attr => {
+ Some(sym::cfg_attr) => {
self.expand_cfg_attr(&mut node, &attr, pos);
continue;
}
@@ -2144,8 +2144,8 @@ fn visit_node<Node: InvocationCollectorNode<OutputTy = Node> + DummyAstNode>(
) {
loop {
return match self.take_first_attr(node) {
- Some((attr, pos, derives)) => match attr.name_or_empty() {
- sym::cfg => {
+ Some((attr, pos, derives)) => match attr.name() {
+ Some(sym::cfg) => {
let span = attr.span;
if self.expand_cfg_true(node, attr, pos).0 {
continue;
@@ -2154,7 +2154,7 @@ fn visit_node<Node: InvocationCollectorNode<OutputTy = Node> + DummyAstNode>(
node.expand_cfg_false(self, pos, span);
continue;
}
- sym::cfg_attr => {
+ Some(sym::cfg_attr) => {
self.expand_cfg_attr(node, &attr, pos);
continue;
}
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index e60a9e8..b663e95 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -66,9 +66,7 @@ pub(super) fn failed_to_match_macro(
}
if let MatcherLoc::Token { token: expected_token } = &remaining_matcher
- && (matches!(expected_token.kind, TokenKind::Interpolated(_))
- || matches!(token.kind, TokenKind::Interpolated(_))
- || matches!(expected_token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_)))
+ && (matches!(expected_token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_)))
|| matches!(token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_))))
{
err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens");
@@ -162,7 +160,7 @@ fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
.is_none_or(|failure| failure.is_better_position(*approx_position))
{
self.best_failure = Some(BestFailure {
- token: token.clone(),
+ token: *token,
position_in_tokenstream: *approx_position,
msg,
remaining_matcher: self
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index d709fd7..0065f83 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -179,7 +179,7 @@ fn inner(
for tt in tts {
match tt {
TokenTree::Token(token) => {
- locs.push(MatcherLoc::Token { token: token.clone() });
+ locs.push(MatcherLoc::Token { token: *token });
}
TokenTree::Delimited(span, _, delimited) => {
let open_token = Token::new(token::OpenDelim(delimited.delim), span.open);
@@ -648,7 +648,7 @@ pub(super) fn parse_tt<'matcher, T: Tracker<'matcher>>(
// There are no possible next positions AND we aren't waiting for the black-box
// parser: syntax error.
return Failure(T::build_failure(
- parser.token.clone(),
+ parser.token,
parser.approx_token_stream_pos(),
"no rules expected this token in macro call",
));
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 77ec598..c138b09 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -12,7 +12,7 @@
use rustc_ast_pretty::pprust;
use rustc_attr_parsing::{AttributeKind, find_attr};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_errors::{Applicability, ErrorGuaranteed};
+use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
use rustc_feature::Features;
use rustc_hir as hir;
use rustc_lint_defs::BuiltinLintDiag;
@@ -27,19 +27,18 @@
use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, kw, sym};
use tracing::{debug, instrument, trace, trace_span};
-use super::diagnostics;
use super::macro_parser::{NamedMatches, NamedParseResult};
+use super::{SequenceRepetition, diagnostics};
use crate::base::{
DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension,
SyntaxExtensionKind, TTMacroExpander,
};
use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment};
-use crate::mbe;
use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
-use crate::mbe::macro_check;
use crate::mbe::macro_parser::NamedMatch::*;
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser};
use crate::mbe::transcribe::transcribe;
+use crate::mbe::{self, KleeneOp, macro_check};
pub(crate) struct ParserAnyMacro<'a> {
parser: Parser<'a>,
@@ -640,6 +639,37 @@ fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
}
}
+/// Checks if a `vis` nonterminal fragment is unnecessarily wrapped in an optional repetition.
+///
+/// When a `vis` fragment (which can already be empty) is wrapped in `$(...)?`,
+/// this suggests removing the redundant repetition syntax since it provides no additional benefit.
+fn check_redundant_vis_repetition(
+ err: &mut Diag<'_>,
+ sess: &Session,
+ seq: &SequenceRepetition,
+ span: &DelimSpan,
+) {
+ let is_zero_or_one: bool = seq.kleene.op == KleeneOp::ZeroOrOne;
+ let is_vis = seq.tts.first().map_or(false, |tt| {
+ matches!(tt, mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)))
+ });
+
+ if is_vis && is_zero_or_one {
+ err.note("a `vis` fragment can already be empty");
+ err.multipart_suggestion(
+ "remove the `$(` and `)?`",
+ vec![
+ (
+ sess.source_map().span_extend_to_prev_char_before(span.open, '$', true),
+ "".to_string(),
+ ),
+ (span.close.with_hi(seq.kleene.span.hi()), "".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
+}
+
/// Checks that the lhs contains no repetition which could match an empty token
/// tree, because then the matcher would hang indefinitely.
fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> Result<(), ErrorGuaranteed> {
@@ -654,8 +684,10 @@ fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> Result<(),
TokenTree::Sequence(span, seq) => {
if is_empty_token_tree(sess, seq) {
let sp = span.entire();
- let guar = sess.dcx().span_err(sp, "repetition matches empty token tree");
- return Err(guar);
+ let mut err =
+ sess.dcx().struct_span_err(sp, "repetition matches empty token tree");
+ check_redundant_vis_repetition(&mut err, sess, seq, span);
+ return Err(err.emit());
}
check_lhs_no_empty_seq(sess, &seq.tts)?
}
@@ -778,7 +810,7 @@ fn build_recur<'tt>(sets: &mut FirstSets<'tt>, tts: &'tt [TokenTree]) -> TokenSe
// token could be the separator token itself.
if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) {
- first.add_one_maybe(TtHandle::from_token(sep.clone()));
+ first.add_one_maybe(TtHandle::from_token(*sep));
}
// Reverse scan: Sequence comes before `first`.
@@ -841,7 +873,7 @@ fn first(&self, tts: &'tt [mbe::TokenTree]) -> TokenSet<'tt> {
// If the sequence contents can be empty, then the first
// token could be the separator token itself.
if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) {
- first.add_one_maybe(TtHandle::from_token(sep.clone()));
+ first.add_one_maybe(TtHandle::from_token(*sep));
}
assert!(first.maybe_empty);
@@ -917,7 +949,7 @@ fn clone(&self) -> Self {
// This variant *must* contain a `mbe::TokenTree::Token`, and not
// any other variant of `mbe::TokenTree`.
TtHandle::Token(mbe::TokenTree::Token(tok)) => {
- TtHandle::Token(mbe::TokenTree::Token(tok.clone()))
+ TtHandle::Token(mbe::TokenTree::Token(*tok))
}
_ => unreachable!(),
@@ -1093,7 +1125,7 @@ fn check_matcher_core<'tt>(
let mut new;
let my_suffix = if let Some(sep) = &seq_rep.separator {
new = suffix_first.clone();
- new.add_one_maybe(TtHandle::from_token(sep.clone()));
+ new.add_one_maybe(TtHandle::from_token(*sep));
&new
} else {
&suffix_first
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 0ea5362..3f03725 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -283,7 +283,7 @@ fn parse_tree<'a>(
}
// `tree` is an arbitrary token. Keep it.
- tokenstream::TokenTree::Token(token, _) => TokenTree::Token(token.clone()),
+ tokenstream::TokenTree::Token(token, _) => TokenTree::Token(*token),
// `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to
// descend into the delimited set and further parse it.
@@ -321,7 +321,7 @@ fn parse_kleene_op(
match iter.next() {
Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(token) {
Some(op) => Ok(Ok((op, token.span))),
- None => Ok(Err(token.clone())),
+ None => Ok(Err(*token)),
},
tree => Err(tree.map_or(span, tokenstream::TokenTree::span)),
}
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 6e47ed6..3918631 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,5 +1,4 @@
use std::mem;
-use std::sync::Arc;
use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::token::{
@@ -165,7 +164,7 @@ pub(super) fn transcribe<'a>(
if repeat_idx < repeat_len {
frame.idx = 0;
if let Some(sep) = sep {
- result.push(TokenTree::Token(sep.clone(), Spacing::Alone));
+ result.push(TokenTree::Token(*sep, Spacing::Alone));
}
continue;
}
@@ -307,7 +306,9 @@ pub(super) fn transcribe<'a>(
let tt = match cur_matched {
MatchedSingle(ParseNtResult::Tt(tt)) => {
// `tt`s are emitted into the output stream directly as "raw tokens",
- // without wrapping them into groups.
+ // without wrapping them into groups. Other variables are emitted into
+ // the output stream as groups with `Delimiter::Invisible` to maintain
+ // parsing priorities.
maybe_use_metavar_location(psess, &stack, sp, tt, &mut marker)
}
MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => {
@@ -325,6 +326,11 @@ pub(super) fn transcribe<'a>(
MatchedSingle(ParseNtResult::Item(item)) => {
mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item))
}
+ MatchedSingle(ParseNtResult::Block(block)) => mk_delimited(
+ block.span,
+ MetaVarKind::Block,
+ TokenStream::from_ast(block),
+ ),
MatchedSingle(ParseNtResult::Stmt(stmt)) => {
let stream = if let StmtKind::Empty = stmt.kind {
// FIXME: Properly collect tokens for empty statements.
@@ -385,15 +391,6 @@ pub(super) fn transcribe<'a>(
MatchedSingle(ParseNtResult::Vis(vis)) => {
mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis))
}
- MatchedSingle(ParseNtResult::Nt(nt)) => {
- // Other variables are emitted into the output stream as groups with
- // `Delimiter::Invisible` to maintain parsing priorities.
- // `Interpolated` is currently used for such groups in rustc parser.
- marker.visit_span(&mut sp);
- let use_span = nt.use_span();
- with_metavar_spans(|mspans| mspans.insert(use_span, sp));
- TokenTree::token_alone(token::Interpolated(Arc::clone(nt)), sp)
- }
MatchedSeq(..) => {
// We were unable to descend far enough. This is an error.
return Err(dcx.create_err(VarStillRepeating { span: sp, ident }));
@@ -441,7 +438,7 @@ pub(super) fn transcribe<'a>(
// Nothing much to do here. Just push the token to the result, being careful to
// preserve syntax context.
mbe::TokenTree::Token(token) => {
- let mut token = token.clone();
+ let mut token = *token;
mut_visit::visit_token(&mut marker, &mut token);
let tt = TokenTree::Token(token, Spacing::Alone);
result.push(tt);
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index ee6306e..4edaf68 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -1,5 +1,4 @@
use std::ops::{Bound, Range};
-use std::sync::Arc;
use ast::token::IdentIsRaw;
use pm::bridge::{
@@ -18,7 +17,7 @@
use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
use rustc_session::parse::ParseSess;
use rustc_span::def_id::CrateNum;
-use rustc_span::{BytePos, FileName, Pos, SourceFile, Span, Symbol, sym};
+use rustc_span::{BytePos, FileName, Pos, Span, Symbol, sym};
use smallvec::{SmallVec, smallvec};
use crate::base::ExtCtxt;
@@ -309,15 +308,6 @@ fn from_internal((stream, rustc): (TokenStream, &mut Rustc<'_, '_>)) -> Self {
}));
}
- Interpolated(nt) => {
- let stream = TokenStream::from_nonterminal_ast(&nt);
- trees.push(TokenTree::Group(Group {
- delimiter: pm::Delimiter::None,
- stream: Some(stream),
- span: DelimSpan::from_single(span),
- }))
- }
-
OpenDelim(..) | CloseDelim(..) => unreachable!(),
Eof => unreachable!(),
}
@@ -467,7 +457,6 @@ fn psess(&self) -> &ParseSess {
impl server::Types for Rustc<'_, '_> {
type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream;
- type SourceFile = Arc<SourceFile>;
type Span = Span;
type Symbol = Symbol;
}
@@ -673,28 +662,6 @@ fn into_trees(
}
}
-impl server::SourceFile for Rustc<'_, '_> {
- fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
- Arc::ptr_eq(file1, file2)
- }
-
- fn path(&mut self, file: &Self::SourceFile) -> String {
- match &file.name {
- FileName::Real(name) => name
- .local_path()
- .expect("attempting to get a file path in an imported file in `proc_macro::SourceFile::path`")
- .to_str()
- .expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
- .to_string(),
- _ => file.name.prefer_local().to_string(),
- }
- }
-
- fn is_real(&mut self, file: &Self::SourceFile) -> bool {
- file.is_real_file()
- }
-}
-
impl server::Span for Rustc<'_, '_> {
fn debug(&mut self, span: Self::Span) -> String {
if self.ecx.ecfg.span_debug {
@@ -704,8 +671,29 @@ fn debug(&mut self, span: Self::Span) -> String {
}
}
- fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
- self.psess().source_map().lookup_char_pos(span.lo()).file
+ fn file(&mut self, span: Self::Span) -> String {
+ self.psess()
+ .source_map()
+ .lookup_char_pos(span.lo())
+ .file
+ .name
+ .prefer_remapped_unconditionaly()
+ .to_string()
+ }
+
+ fn local_file(&mut self, span: Self::Span) -> Option<String> {
+ self.psess()
+ .source_map()
+ .lookup_char_pos(span.lo())
+ .file
+ .name
+ .clone()
+ .into_local_path()
+ .map(|p| {
+ p.to_str()
+ .expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
+ .to_string()
+ })
}
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 8968c17..fcc11dd 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -95,6 +95,8 @@ macro_rules! declare_features {
(accepted, c_unwind, "1.81.0", Some(74990)),
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
(accepted, cfg_attr_multi, "1.33.0", Some(54881)),
+ /// Allows the use of `#[cfg(<true/false>)]`.
+ (accepted, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)),
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
(accepted, cfg_doctest, "1.40.0", Some(62210)),
/// Enables `#[cfg(panic = "...")]` config key.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 1e33e2e..3b44172 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -6,6 +6,7 @@
use AttributeGate::*;
use AttributeType::*;
use rustc_data_structures::fx::FxHashMap;
+use rustc_span::edition::Edition;
use rustc_span::{Symbol, sym};
use crate::{Features, Stability};
@@ -65,9 +66,12 @@ pub enum AttributeSafety {
/// Normal attribute that does not need `#[unsafe(...)]`
Normal,
- /// Unsafe attribute that requires safety obligations
- /// to be discharged
- Unsafe,
+ /// Unsafe attribute that requires safety obligations to be discharged.
+ ///
+ /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition
+ /// is less than the one stored in `unsafe_since`. This handles attributes that were safe in
+ /// earlier editions, but become unsafe in later ones.
+ Unsafe { unsafe_since: Option<Edition> },
}
#[derive(Clone, Copy)]
@@ -187,12 +191,23 @@ macro_rules! template {
}
macro_rules! ungated {
+ (unsafe($edition:ident) $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
+ BuiltinAttribute {
+ name: sym::$attr,
+ encode_cross_crate: $encode_cross_crate,
+ type_: $typ,
+ safety: AttributeSafety::Unsafe { unsafe_since: Some(Edition::$edition) },
+ template: $tpl,
+ gate: Ungated,
+ duplicates: $duplicates,
+ }
+ };
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
encode_cross_crate: $encode_cross_crate,
type_: $typ,
- safety: AttributeSafety::Unsafe,
+ safety: AttributeSafety::Unsafe { unsafe_since: None },
template: $tpl,
gate: Ungated,
duplicates: $duplicates,
@@ -217,7 +232,7 @@ macro_rules! gated {
name: sym::$attr,
encode_cross_crate: $encode_cross_crate,
type_: $typ,
- safety: AttributeSafety::Unsafe,
+ safety: AttributeSafety::Unsafe { unsafe_since: None },
template: $tpl,
duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::$gate, $msg, Features::$gate),
@@ -228,7 +243,7 @@ macro_rules! gated {
name: sym::$attr,
encode_cross_crate: $encode_cross_crate,
type_: $typ,
- safety: AttributeSafety::Unsafe,
+ safety: AttributeSafety::Unsafe { unsafe_since: None },
template: $tpl,
duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::$attr, $msg, Features::$attr),
@@ -423,9 +438,9 @@ pub struct BuiltinAttribute {
),
ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
- ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
- ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
- ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
+ ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
+ ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
+ ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
@@ -752,7 +767,7 @@ pub struct BuiltinAttribute {
),
rustc_attr!(
rustc_macro_transparency, Normal,
- template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing,
+ template!(NameValueStr: "transparent|semiopaque|opaque"), ErrorFollowing,
EncodeCrossCrate::Yes, "used internally for testing macro hygiene",
),
rustc_attr!(
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 98213af..e09ae3c 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -391,8 +391,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, async_trait_bounds, "1.85.0", Some(62290)),
/// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)),
- /// Allows the use of `#[cfg(<true/false>)]`.
- (unstable, cfg_boolean_literals, "1.83.0", Some(131204)),
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
(unstable, cfg_contract_checks, "1.86.0", Some(128044)),
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
@@ -477,6 +475,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
(incomplete, ergonomic_clones, "1.87.0", Some(132290)),
/// Allows exhaustive pattern matching on types that contain uninhabited types.
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
+ /// Disallows `extern` without an explicit ABI.
+ (unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)),
/// Allows explicit tail calls via `become` expression.
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
@@ -565,6 +565,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
(incomplete, mut_ref, "1.79.0", Some(123076)),
/// Allows using `#[naked]` on functions.
(unstable, naked_functions, "1.9.0", Some(90957)),
+ /// Allows using `#[naked]` on `extern "Rust"` functions.
+ (unstable, naked_functions_rustic_abi, "CURRENT_RUSTC_VERSION", Some(138997)),
/// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions.
(unstable, naked_functions_target_feature, "1.86.0", Some(138568)),
/// Allows specifying the as-needed link modifier
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index b04fd1b..c96bb48 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -25,7 +25,10 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
path.to_path_buf()
} else {
// `/a/b/c/foo/bar.rs` contains the current macro invocation
+ #[cfg(bootstrap)]
let mut source_file_path = span.source_file().path();
+ #[cfg(not(bootstrap))]
+ let mut source_file_path = span.local_file().unwrap();
// `/a/b/c/foo/`
source_file_path.pop();
// `/a/b/c/foo/../locales/en-US/example.ftl`
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index dc00b52..9372ab5 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -267,11 +267,16 @@ pub fn def_path_data(self, name: Option<Symbol>) -> DefPathData {
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::TyParam
- | DefKind::ExternCrate => DefPathData::TypeNs(Some(name.unwrap())),
+ | DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
- // An associated type names will be missing for an RPITIT. It will
- // later be given a name with `synthetic` in it, if necessary.
- DefKind::AssocTy => DefPathData::TypeNs(name),
+ // An associated type name will be missing for an RPITIT.
+ DefKind::AssocTy => {
+ if let Some(name) = name {
+ DefPathData::TypeNs(name)
+ } else {
+ DefPathData::AnonAssocTy
+ }
+ }
// It's not exactly an anon const, but wrt DefPathData, there
// is no difference.
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index c52954a..bf7b1ee 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -47,12 +47,9 @@ fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id());
let local_hash = def_path_hash.local_hash();
- let index = {
- let index = DefIndex::from(self.index_to_key.len());
- debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
- self.index_to_key.push(key);
- index
- };
+ let index = self.index_to_key.push(key);
+ debug!("DefPathTable::insert() - {key:?} <-> {index:?}");
+
self.def_path_hashes.push(local_hash);
debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
@@ -271,9 +268,8 @@ pub enum DefPathData {
Use,
/// A global asm item.
GlobalAsm,
- /// Something in the type namespace. Will be empty for RPITIT associated
- /// types, which are given a synthetic name later, if necessary.
- TypeNs(Option<Symbol>),
+ /// Something in the type namespace.
+ TypeNs(Symbol),
/// Something in the value namespace.
ValueNs(Symbol),
/// Something in the macro namespace.
@@ -291,6 +287,8 @@ pub enum DefPathData {
/// An existential `impl Trait` type node.
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
OpaqueTy,
+ /// An anonymous associated type from an RPITIT.
+ AnonAssocTy,
/// A synthetic body for a coroutine's by-move body.
SyntheticCoroutineBody,
}
@@ -413,9 +411,7 @@ impl DefPathData {
pub fn get_opt_name(&self) -> Option<Symbol> {
use self::DefPathData::*;
match *self {
- TypeNs(name) => name,
-
- ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
+ TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
Impl
| ForeignMod
@@ -426,6 +422,7 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
| Ctor
| AnonConst
| OpaqueTy
+ | AnonAssocTy
| SyntheticCoroutineBody => None,
}
}
@@ -433,14 +430,9 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
pub fn name(&self) -> DefPathDataName {
use self::DefPathData::*;
match *self {
- TypeNs(name) => {
- if let Some(name) = name {
- DefPathDataName::Named(name)
- } else {
- DefPathDataName::Anon { namespace: sym::synthetic }
- }
+ TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
+ DefPathDataName::Named(name)
}
- ValueNs(name) | MacroNs(name) | LifetimeNs(name) => DefPathDataName::Named(name),
// Note that this does not show up in user print-outs.
CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
Impl => DefPathDataName::Anon { namespace: kw::Impl },
@@ -451,6 +443,7 @@ pub fn name(&self) -> DefPathDataName {
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
+ AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc },
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
}
}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index c9c4936..d02c767 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -42,7 +42,7 @@ pub enum IsAnonInPath {
}
/// A lifetime. The valid field combinations are non-obvious. The following
-/// example shows some of them. See also the comments on `LifetimeName`.
+/// example shows some of them. See also the comments on `LifetimeKind`.
/// ```
/// #[repr(C)]
/// struct S<'a>(&'a u32); // res=Param, name='a, IsAnonInPath::No
@@ -84,7 +84,7 @@ pub struct Lifetime {
pub ident: Ident,
/// Semantics of this lifetime.
- pub res: LifetimeName,
+ pub kind: LifetimeKind,
/// Is the lifetime anonymous and in a path? Used only for error
/// suggestions. See `Lifetime::suggestion` for example use.
@@ -130,7 +130,7 @@ pub fn ident(&self) -> Ident {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
-pub enum LifetimeName {
+pub enum LifetimeKind {
/// User-given names or fresh (synthetic) names.
Param(LocalDefId),
@@ -160,16 +160,16 @@ pub enum LifetimeName {
Static,
}
-impl LifetimeName {
+impl LifetimeKind {
fn is_elided(&self) -> bool {
match self {
- LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true,
+ LifetimeKind::ImplicitObjectLifetimeDefault | LifetimeKind::Infer => true,
// It might seem surprising that `Fresh` counts as not *elided*
// -- but this is because, as far as the code in the compiler is
// concerned -- `Fresh` variants act equivalently to "some fresh name".
// They correspond to early-bound regions on an impl, in other words.
- LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false,
+ LifetimeKind::Error | LifetimeKind::Param(..) | LifetimeKind::Static => false,
}
}
}
@@ -184,10 +184,10 @@ impl Lifetime {
pub fn new(
hir_id: HirId,
ident: Ident,
- res: LifetimeName,
+ kind: LifetimeKind,
is_anon_in_path: IsAnonInPath,
) -> Lifetime {
- let lifetime = Lifetime { hir_id, ident, res, is_anon_in_path };
+ let lifetime = Lifetime { hir_id, ident, kind, is_anon_in_path };
// Sanity check: elided lifetimes form a strict subset of anonymous lifetimes.
#[cfg(debug_assertions)]
@@ -202,7 +202,7 @@ pub fn new(
}
pub fn is_elided(&self) -> bool {
- self.res.is_elided()
+ self.kind.is_elided()
}
pub fn is_anonymous(&self) -> bool {
@@ -1014,7 +1014,7 @@ pub struct WhereRegionPredicate<'hir> {
impl<'hir> WhereRegionPredicate<'hir> {
/// Returns `true` if `param_def_id` matches the `lifetime` of this predicate.
fn is_param_bound(&self, param_def_id: LocalDefId) -> bool {
- self.lifetime.res == LifetimeName::Param(param_def_id)
+ self.lifetime.kind == LifetimeKind::Param(param_def_id)
}
}
@@ -1237,7 +1237,7 @@ fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => {
Some((*comment, *kind))
}
- Attribute::Unparsed(_) if self.name_or_empty() == sym::doc => {
+ Attribute::Unparsed(_) if self.has_name(sym::doc) => {
self.value_str().map(|s| (s, CommentKind::Line))
}
_ => None,
@@ -1262,8 +1262,8 @@ pub fn id(&self) -> AttrId {
}
#[inline]
- pub fn name_or_empty(&self) -> Symbol {
- AttributeExt::name_or_empty(self)
+ pub fn name(&self) -> Option<Symbol> {
+ AttributeExt::name(self)
}
#[inline]
@@ -1302,6 +1302,11 @@ pub fn has_name(&self, name: Symbol) -> bool {
}
#[inline]
+ pub fn has_any_name(&self, names: &[Symbol]) -> bool {
+ AttributeExt::has_any_name(self, names)
+ }
+
+ #[inline]
pub fn span(&self) -> Span {
AttributeExt::span(self)
}
@@ -1756,7 +1761,7 @@ pub enum PatKind<'hir> {
Never,
/// A tuple pattern (e.g., `(a, b)`).
- /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
+ /// If the `..` pattern fragment is present, then `DotDotPos` denotes its position.
/// `0 <= position <= subpats.len()`
Tuple(&'hir [Pat<'hir>], DotDotPos),
diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs
index 62ef02d..fcd0eaf 100644
--- a/compiler/rustc_hir/src/hir/tests.rs
+++ b/compiler/rustc_hir/src/hir/tests.rs
@@ -57,7 +57,7 @@ fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
Lifetime {
hir_id: HirId::INVALID,
ident: Ident::new(sym::name, DUMMY_SP),
- res: LifetimeName::Static,
+ kind: LifetimeKind::Static,
is_anon_in_path: IsAnonInPath::No,
}
},
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 93d20df..3c2897e 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -6,7 +6,7 @@
//! 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR.
//! - Example: find all items with a `#[foo]` attribute on them.
//! - How: Use the `hir_crate_items` or `hir_module_items` query to traverse over item-like ids
-//! (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir().item*(id)` to filter and
+//! (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir_item*(id)` to filter and
//! access actual item-like thing, respectively.
//! - Pro: Efficient; just walks the lists of item ids and gives users control whether to access
//! the hir_owners themselves or not.
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 90fab01..b9f4a8c 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -182,6 +182,7 @@ pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
+ UnsafeUnpin, sym::unsafe_unpin, unsafe_unpin_trait, Target::Trait, GenericRequirement::Exact(0);
FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0);
FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
@@ -235,6 +236,8 @@ pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
+ UnsafePinned, sym::unsafe_pinned, unsafe_pinned_type, Target::Struct, GenericRequirement::None;
+
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);
@@ -439,6 +442,8 @@ pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
DefaultTrait3, sym::default_trait3, default_trait3_trait, Target::Trait, GenericRequirement::None;
DefaultTrait2, sym::default_trait2, default_trait2_trait, Target::Trait, GenericRequirement::None;
DefaultTrait1, sym::default_trait1, default_trait1_trait, Target::Trait, GenericRequirement::None;
+
+ ContractCheckEnsures, sym::contract_check_ensures, contract_check_ensures_fn, Target::Fn, GenericRequirement::None;
}
/// The requirement imposed on the generics of a lang item
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 6bc0f79..a84857e 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -4,7 +4,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(closure_track_caller)]
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index b3eade8..99e495d 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -2,8 +2,8 @@
use rustc_infer::traits::PredicateObligations;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::Limit;
-use rustc_span::Span;
use rustc_span::def_id::{LOCAL_CRATE, LocalDefId};
+use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::traits::ObligationCtxt;
use tracing::{debug, instrument};
@@ -259,7 +259,11 @@ pub fn silence_errors(mut self) -> Self {
}
}
-pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
+pub fn report_autoderef_recursion_limit_error<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ span: Span,
+ ty: Ty<'tcx>,
+) -> ErrorGuaranteed {
// We've reached the recursion limit, error gracefully.
let suggested_limit = match tcx.recursion_limit() {
Limit(0) => Limit(2),
@@ -270,5 +274,5 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa
ty,
suggested_limit,
crate_name: tcx.crate_name(LOCAL_CRATE),
- });
+ })
}
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index f50746d..4f338c6 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -443,13 +443,13 @@ fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) -> Self::Resu
let impl_def_id = tcx.local_parent(parent);
for assoc in tcx.associated_items(impl_def_id).in_definition_order() {
match assoc.kind {
- ty::AssocKind::Const | ty::AssocKind::Fn => {
+ ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => {
if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local())
{
return Some(span);
}
}
- ty::AssocKind::Type => {}
+ ty::AssocKind::Type { .. } => {}
}
}
@@ -740,7 +740,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
for &assoc_item in assoc_items.in_definition_order() {
match assoc_item.kind {
- ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
+ ty::AssocKind::Type { .. } if assoc_item.defaultness(tcx).has_value() => {
let trait_args = GenericArgs::identity_for_item(tcx, def_id);
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
@@ -942,7 +942,7 @@ fn check_impl_items_against_trait<'tcx>(
if res.is_ok() {
match ty_impl_item.kind {
- ty::AssocKind::Fn => {
+ ty::AssocKind::Fn { .. } => {
compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait(
tcx,
ty_impl_item,
@@ -952,8 +952,8 @@ fn check_impl_items_against_trait<'tcx>(
.instantiate_identity(),
);
}
- ty::AssocKind::Const => {}
- ty::AssocKind::Type => {}
+ ty::AssocKind::Const { .. } => {}
+ ty::AssocKind::Type { .. } => {}
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 29a9931..06a7b1f 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -43,9 +43,11 @@ pub(super) fn compare_impl_item(
debug!(?impl_trait_ref);
match impl_item.kind {
- ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
- ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
- ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref),
+ ty::AssocKind::Fn { .. } => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
+ ty::AssocKind::Type { .. } => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
+ ty::AssocKind::Const { .. } => {
+ compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref)
+ }
}
}
@@ -606,7 +608,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// with placeholders, which imply nothing about outlives bounds, and then
// prove below that the hidden types are well formed.
let universe = infcx.create_next_universe();
- let mut idx = 0;
+ let mut idx = ty::BoundVar::ZERO;
let mapping: FxIndexMap<_, _> = collector
.types
.iter()
@@ -623,10 +625,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx,
ty::Placeholder {
universe,
- bound: ty::BoundTy {
- var: ty::BoundVar::from_usize(idx),
- kind: ty::BoundTyKind::Anon,
- },
+ bound: ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon },
},
),
)
@@ -654,7 +653,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
cause.span,
E0053,
"method `{}` has an incompatible return type for trait",
- trait_m.name
+ trait_m.name()
);
infcx.err_ctxt().note_type_err(
&mut diag,
@@ -1032,11 +1031,11 @@ fn report_trait_method_mismatch<'tcx>(
impl_err_span,
E0053,
"method `{}` has an incompatible type for trait",
- trait_m.name
+ trait_m.name()
);
match &terr {
TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
- if trait_m.fn_has_self_parameter =>
+ if trait_m.is_method() =>
{
let ty = trait_sig.inputs()[0];
let sugg = get_self_string(ty, |ty| ty == impl_trait_ref.self_ty());
@@ -1255,7 +1254,7 @@ fn compare_self_type<'tcx>(
get_self_string(self_arg_ty, can_eq_self)
};
- match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) {
+ match (trait_m.is_method(), impl_m.is_method()) {
(false, false) | (true, true) => {}
(false, true) => {
@@ -1266,14 +1265,14 @@ fn compare_self_type<'tcx>(
impl_m_span,
E0185,
"method `{}` has a `{}` declaration in the impl, but not in the trait",
- trait_m.name,
+ trait_m.name(),
self_descr
);
err.span_label(impl_m_span, format!("`{self_descr}` used in impl"));
if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
err.span_label(span, format!("trait method declared without `{self_descr}`"));
} else {
- err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
+ err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
}
return Err(err.emit_unless(delay));
}
@@ -1286,14 +1285,14 @@ fn compare_self_type<'tcx>(
impl_m_span,
E0186,
"method `{}` has a `{}` declaration in the trait, but not in the impl",
- trait_m.name,
+ trait_m.name(),
self_descr
);
err.span_label(impl_m_span, format!("expected `{self_descr}` in impl"));
if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
err.span_label(span, format!("`{self_descr}` used in trait"));
} else {
- err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
+ err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
}
return Err(err.emit_unless(delay));
@@ -1363,7 +1362,7 @@ fn compare_number_of_generics<'tcx>(
let mut err_occurred = None;
for (kind, trait_count, impl_count) in matchings {
if impl_count != trait_count {
- let arg_spans = |kind: ty::AssocKind, generics: &hir::Generics<'_>| {
+ let arg_spans = |item: &ty::AssocItem, generics: &hir::Generics<'_>| {
let mut spans = generics
.params
.iter()
@@ -1373,7 +1372,7 @@ fn compare_number_of_generics<'tcx>(
} => {
// A fn can have an arbitrary number of extra elided lifetimes for the
// same signature.
- !matches!(kind, ty::AssocKind::Fn)
+ !item.is_fn()
}
_ => true,
})
@@ -1386,7 +1385,7 @@ fn compare_number_of_generics<'tcx>(
};
let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
let trait_item = tcx.hir_expect_trait_item(def_id);
- let arg_spans: Vec<Span> = arg_spans(trait_.kind, trait_item.generics);
+ let arg_spans: Vec<Span> = arg_spans(&trait_, trait_item.generics);
let impl_trait_spans: Vec<Span> = trait_item
.generics
.params
@@ -1412,7 +1411,7 @@ fn compare_number_of_generics<'tcx>(
_ => None,
})
.collect();
- let spans = arg_spans(impl_.kind, impl_item.generics);
+ let spans = arg_spans(&impl_, impl_item.generics);
let span = spans.first().copied();
let mut err = tcx.dcx().struct_span_err(
@@ -1421,7 +1420,7 @@ fn compare_number_of_generics<'tcx>(
"{} `{}` has {} {kind} parameter{} but its trait \
declaration has {} {kind} parameter{}",
item_kind,
- trait_.name,
+ trait_.name(),
impl_count,
pluralize!(impl_count),
trait_count,
@@ -1512,7 +1511,7 @@ fn compare_number_of_method_arguments<'tcx>(
impl_span,
E0050,
"method `{}` has {} but the declaration in trait `{}` has {}",
- trait_m.name,
+ trait_m.name(),
potentially_plural_count(impl_number_args, "parameter"),
tcx.def_path_str(trait_m.def_id),
trait_number_args
@@ -1527,7 +1526,7 @@ fn compare_number_of_method_arguments<'tcx>(
),
);
} else {
- err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
+ err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
}
err.span_label(
@@ -1581,7 +1580,7 @@ fn compare_synthetic_generics<'tcx>(
impl_span,
E0643,
"method `{}` has incompatible signature for trait",
- trait_m.name
+ trait_m.name()
);
err.span_label(trait_span, "declaration in trait here");
if impl_synthetic {
@@ -1703,7 +1702,7 @@ fn compare_generic_param_kinds<'tcx>(
trait_item: ty::AssocItem,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
- assert_eq!(impl_item.kind, trait_item.kind);
+ assert_eq!(impl_item.as_tag(), trait_item.as_tag());
let ty_const_params_of = |def_id| {
tcx.generics_of(def_id).own_params.iter().filter(|param| {
@@ -1741,7 +1740,7 @@ fn compare_generic_param_kinds<'tcx>(
E0053,
"{} `{}` has an incompatible generic parameter for trait `{}`",
impl_item.descr(),
- trait_item.name,
+ trait_item.name(),
&tcx.def_path_str(tcx.parent(trait_item.def_id))
);
@@ -1877,7 +1876,7 @@ fn compare_const_predicate_entailment<'tcx>(
cause.span,
E0326,
"implemented const `{}` has an incompatible type for trait",
- trait_ct.name
+ trait_ct.name()
);
let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
@@ -2235,16 +2234,19 @@ fn param_env_with_gat_bounds<'tcx>(
// of the RPITITs associated with the same body. This is because checking
// the item bounds of RPITITs often involves nested RPITITs having to prove
// bounds about themselves.
- let impl_tys_to_install = match impl_ty.opt_rpitit_info {
- None => vec![impl_ty],
- Some(
- ty::ImplTraitInTraitData::Impl { fn_def_id }
- | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
- ) => tcx
+ let impl_tys_to_install = match impl_ty.kind {
+ ty::AssocKind::Type {
+ data:
+ ty::AssocTypeData::Rpitit(
+ ty::ImplTraitInTraitData::Impl { fn_def_id }
+ | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
+ ),
+ } => tcx
.associated_types_for_impl_traits_in_associated_fn(fn_def_id)
.iter()
.map(|def_id| tcx.associated_item(*def_id))
.collect(),
+ _ => vec![impl_ty],
};
for impl_ty in impl_tys_to_install {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index ed8ca27..89fb351 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -217,15 +217,11 @@ pub(crate) fn check_intrinsic_type(
};
(n_tps, 0, 0, inputs, output, hir::Safety::Unsafe)
} else if intrinsic_name == sym::contract_check_ensures {
- // contract_check_ensures::<'a, Ret, C>(&'a Ret, C)
- // where C: impl Fn(&'a Ret) -> bool,
+ // contract_check_ensures::<Ret, C>(Ret, C) -> Ret
+ // where C: for<'a> Fn(&'a Ret) -> bool,
//
- // so: two type params, one lifetime param, 0 const params, two inputs, no return
-
- let p = generics.param_at(0, tcx);
- let r = ty::Region::new_early_param(tcx, p.to_early_bound_region_data());
- let ref_ret = Ty::new_imm_ref(tcx, r, param(1));
- (2, 1, 0, vec![ref_ret, param(2)], tcx.types.unit, hir::Safety::Safe)
+ // so: two type params, 0 lifetime param, 0 const params, two inputs, no return
+ (2, 0, 0, vec![param(0), param(1)], param(1), hir::Safety::Safe)
} else {
let safety = intrinsic_operation_unsafety(tcx, intrinsic_id);
let (n_tps, n_cts, inputs, output) = match intrinsic_name {
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 30921b6..5fbd771 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -205,7 +205,7 @@ fn missing_items_err(
let missing_items_msg = missing_items
.clone()
- .map(|trait_item| trait_item.name.to_string())
+ .map(|trait_item| trait_item.name().to_string())
.collect::<Vec<_>>()
.join("`, `");
@@ -236,7 +236,7 @@ fn missing_items_err(
let code = format!("{padding}{snippet}\n{padding}");
if let Some(span) = tcx.hir_span_if_local(trait_item.def_id) {
missing_trait_item_label
- .push(errors::MissingTraitItemLabel { span, item: trait_item.name });
+ .push(errors::MissingTraitItemLabel { span, item: trait_item.name() });
missing_trait_item.push(errors::MissingTraitItemSuggestion {
span: sugg_sp,
code,
@@ -407,14 +407,14 @@ fn fn_sig_suggestion<'tcx>(
.enumerate()
.map(|(i, ty)| {
Some(match ty.kind() {
- ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(),
+ ty::Param(_) if assoc.is_method() && i == 0 => "self".to_string(),
ty::Ref(reg, ref_ty, mutability) if i == 0 => {
let reg = format!("{reg} ");
let reg = match ®[..] {
"'_ " | " " => "",
reg => reg,
};
- if assoc.fn_has_self_parameter {
+ if assoc.is_method() {
match ref_ty.kind() {
ty::Param(param) if param.name == kw::SelfUpper => {
format!("&{}{}self", reg, mutability.prefix_str())
@@ -427,7 +427,7 @@ fn fn_sig_suggestion<'tcx>(
}
}
_ => {
- if assoc.fn_has_self_parameter && i == 0 {
+ if assoc.is_method() && i == 0 {
format!("self: {ty}")
} else {
format!("_: {ty}")
@@ -489,7 +489,7 @@ fn suggestion_signature<'tcx>(
);
match assoc.kind {
- ty::AssocKind::Fn => fn_sig_suggestion(
+ ty::AssocKind::Fn { .. } => fn_sig_suggestion(
tcx,
tcx.liberate_late_bound_regions(
assoc.def_id,
@@ -499,14 +499,14 @@ fn suggestion_signature<'tcx>(
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
assoc,
),
- ty::AssocKind::Type => {
+ ty::AssocKind::Type { .. } => {
let (generics, where_clauses) = bounds_from_generic_predicates(
tcx,
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
);
- format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
+ format!("type {}{generics} = /* Type */{where_clauses};", assoc.name())
}
- ty::AssocKind::Const => {
+ ty::AssocKind::Const { name } => {
let ty = tcx.type_of(assoc.def_id).instantiate_identity();
let val = tcx
.infer_ctxt()
@@ -514,7 +514,7 @@ fn suggestion_signature<'tcx>(
.err_ctxt()
.ty_kind_suggestion(tcx.param_env(assoc.def_id), ty)
.unwrap_or_else(|| "value".to_string());
- format!("const {}: {} = {};", assoc.name, ty, val)
+ format!("const {}: {} = {};", name, ty, val)
}
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 6292d03..33d5a86 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -408,7 +408,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
let gat_def_id = gat_item.def_id.expect_local();
let gat_item = tcx.associated_item(gat_def_id);
// If this item is not an assoc ty, or has no args, then it's not a GAT
- if gat_item.kind != ty::AssocKind::Type {
+ if !gat_item.is_type() {
continue;
}
let gat_generics = tcx.generics_of(gat_def_id);
@@ -432,7 +432,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
let item_required_bounds = match tcx.associated_item(item_def_id).kind {
// In our example, this corresponds to `into_iter` method
- ty::AssocKind::Fn => {
+ ty::AssocKind::Fn { .. } => {
// For methods, we check the function signature's return type for any GATs
// to constrain. In the `into_iter` case, we see that the return type
// `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
@@ -453,7 +453,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
)
}
// In our example, this corresponds to the `Iter` and `Item` associated types
- ty::AssocKind::Type => {
+ ty::AssocKind::Type { .. } => {
// If our associated item is a GAT with missing bounds, add them to
// the param-env here. This allows this GAT to propagate missing bounds
// to other GATs.
@@ -474,7 +474,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
gat_generics,
)
}
- ty::AssocKind::Const => None,
+ ty::AssocKind::Const { .. } => None,
};
if let Some(item_required_bounds) = item_required_bounds {
@@ -1076,7 +1076,7 @@ fn check_associated_item(
};
match item.kind {
- ty::AssocKind::Const => {
+ ty::AssocKind::Const { .. } => {
let ty = tcx.type_of(item.def_id).instantiate_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
@@ -1089,7 +1089,7 @@ fn check_associated_item(
);
Ok(())
}
- ty::AssocKind::Fn => {
+ ty::AssocKind::Fn { .. } => {
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
let hir_sig = sig_if_method.expect("bad signature for method");
check_fn_or_method(
@@ -1101,7 +1101,7 @@ fn check_associated_item(
);
check_method_receiver(wfcx, hir_sig, item, self_ty)
}
- ty::AssocKind::Type => {
+ ty::AssocKind::Type { .. } => {
if let ty::AssocItemContainer::Trait = item.container {
check_associated_type_bounds(wfcx, item, span)
}
@@ -1716,7 +1716,7 @@ fn check_method_receiver<'tcx>(
) -> Result<(), ErrorGuaranteed> {
let tcx = wfcx.tcx();
- if !method.fn_has_self_parameter {
+ if !method.is_method() {
return Ok(());
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index dc61657..2426391 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -51,7 +51,7 @@ fn impls_have_common_items(
for &item1 in impl_items1.in_definition_order() {
let collision = impl_items2
- .filter_by_name_unhygienic(item1.name)
+ .filter_by_name_unhygienic(item1.name())
.any(|&item2| self.compare_hygienically(item1, item2));
if collision {
@@ -64,7 +64,7 @@ fn impls_have_common_items(
fn compare_hygienically(&self, item1: ty::AssocItem, item2: ty::AssocItem) -> bool {
// Symbols and namespace match, compare hygienically.
- item1.kind.namespace() == item2.kind.namespace()
+ item1.namespace() == item2.namespace()
&& item1.ident(self.tcx).normalize_to_macros_2_0()
== item2.ident(self.tcx).normalize_to_macros_2_0()
}
@@ -113,7 +113,7 @@ fn check_for_common_items_in_impls(
let mut res = Ok(());
for &item1 in impl_items1.in_definition_order() {
let collision = impl_items2
- .filter_by_name_unhygienic(item1.name)
+ .filter_by_name_unhygienic(item1.name())
.find(|&&item2| self.compare_hygienically(item1, item2));
if let Some(item2) = collision {
@@ -230,11 +230,11 @@ struct ConnectedRegion {
let mut ids = impl_items
.in_definition_order()
.filter_map(|item| {
- let entry = connected_region_ids.entry(item.name);
+ let entry = connected_region_ids.entry(item.name());
if let IndexEntry::Occupied(e) = &entry {
Some(*e.get())
} else {
- idents_to_add.push(item.name);
+ idents_to_add.push(item.name());
None
}
})
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index deded69..4520fbe 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -44,7 +44,7 @@
use tracing::{debug, instrument};
use crate::errors;
-use crate::hir_ty_lowering::errors::assoc_kind_str;
+use crate::hir_ty_lowering::errors::assoc_tag_str;
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
pub(crate) mod dump;
@@ -450,7 +450,7 @@ fn lower_assoc_shared(
item_def_id: DefId,
item_segment: &rustc_hir::PathSegment<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
@@ -525,7 +525,7 @@ fn lower_assoc_shared(
inferred_sugg,
bound,
mpart_sugg,
- what: assoc_kind_str(kind),
+ what: assoc_tag_str(assoc_tag),
}))
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 9bcda35..59ab36d 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -16,7 +16,7 @@
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
use rustc_hir::{
- self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node,
+ self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node,
};
use rustc_macros::extension;
use rustc_middle::hir::nested_filter;
@@ -646,14 +646,14 @@ fn visit_precise_capturing_arg(
arg: &'tcx hir::PreciseCapturingArg<'tcx>,
) -> Self::Result {
match *arg {
- hir::PreciseCapturingArg::Lifetime(lt) => match lt.res {
- LifetimeName::Param(def_id) => {
+ hir::PreciseCapturingArg::Lifetime(lt) => match lt.kind {
+ LifetimeKind::Param(def_id) => {
self.resolve_lifetime_ref(def_id, lt);
}
- LifetimeName::Error => {}
- LifetimeName::ImplicitObjectLifetimeDefault
- | LifetimeName::Infer
- | LifetimeName::Static => {
+ LifetimeKind::Error => {}
+ LifetimeKind::ImplicitObjectLifetimeDefault
+ | LifetimeKind::Infer
+ | LifetimeKind::Static => {
self.tcx.dcx().emit_err(errors::BadPreciseCapture {
span: lt.ident.span,
kind: "lifetime",
@@ -774,26 +774,26 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
);
}
});
- match lifetime.res {
- LifetimeName::ImplicitObjectLifetimeDefault => {
+ match lifetime.kind {
+ LifetimeKind::ImplicitObjectLifetimeDefault => {
// If the user does not write *anything*, we
// use the object lifetime defaulting
// rules. So e.g., `Box<dyn Debug>` becomes
// `Box<dyn Debug + 'static>`.
self.resolve_object_lifetime_default(&*lifetime)
}
- LifetimeName::Infer => {
+ LifetimeKind::Infer => {
// If the user writes `'_`, we use the *ordinary* elision
// rules. So the `'_` in e.g., `Box<dyn Debug + '_>` will be
// resolved the same as the `'_` in `&'_ Foo`.
//
// cc #48468
}
- LifetimeName::Param(..) | LifetimeName::Static => {
+ LifetimeKind::Param(..) | LifetimeKind::Static => {
// If the user wrote an explicit name, use that.
self.visit_lifetime(&*lifetime);
}
- LifetimeName::Error => {}
+ LifetimeKind::Error => {}
}
}
hir::TyKind::Ref(lifetime_ref, ref mt) => {
@@ -873,17 +873,17 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
#[instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
- match lifetime_ref.res {
- hir::LifetimeName::Static => {
+ match lifetime_ref.kind {
+ hir::LifetimeKind::Static => {
self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
}
- hir::LifetimeName::Param(param_def_id) => {
+ hir::LifetimeKind::Param(param_def_id) => {
self.resolve_lifetime_ref(param_def_id, lifetime_ref)
}
// If we've already reported an error, just ignore `lifetime_ref`.
- hir::LifetimeName::Error => {}
+ hir::LifetimeKind::Error => {}
// Those will be resolved by typechecking.
- hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {}
+ hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer => {}
}
}
@@ -1063,15 +1063,15 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL
for bound in bound.bounds {
if let hir::GenericBound::Outlives(lifetime) = bound {
- set.insert(lifetime.res);
+ set.insert(lifetime.kind);
}
}
}
match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
- Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
- Set1::One(hir::LifetimeName::Param(param_def_id)) => {
+ Set1::One(hir::LifetimeKind::Static) => ObjectLifetimeDefault::Static,
+ Set1::One(hir::LifetimeKind::Param(param_def_id)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
_ => ObjectLifetimeDefault::Ambiguous,
@@ -1241,7 +1241,7 @@ fn resolve_lifetime_ref(
// Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
// regular fns.
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
- && let hir::LifetimeName::Param(param_id) = lifetime_ref.res
+ && let hir::LifetimeKind::Param(param_id) = lifetime_ref.kind
&& let Some(generics) =
self.tcx.hir_get_generics(self.tcx.local_parent(param_id))
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
@@ -1811,7 +1811,7 @@ fn visit_segment_args(
self.tcx,
type_def_id,
constraint.ident,
- ty::AssocKind::Fn,
+ ty::AssocTag::Fn,
) {
bound_vars.extend(
self.tcx
@@ -1843,7 +1843,7 @@ fn visit_segment_args(
self.tcx,
type_def_id,
constraint.ident,
- ty::AssocKind::Type,
+ ty::AssocTag::Type,
)
.map(|(bound_vars, _)| bound_vars);
self.with(scope, |this| {
@@ -1875,13 +1875,13 @@ fn supertrait_hrtb_vars(
tcx: TyCtxt<'tcx>,
def_id: DefId,
assoc_ident: Ident,
- assoc_kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
let trait_defines_associated_item_named = |trait_def_id: DefId| {
tcx.associated_items(trait_def_id).find_by_ident_and_kind(
tcx,
assoc_ident,
- assoc_kind,
+ assoc_tag,
trait_def_id,
)
};
@@ -1894,8 +1894,8 @@ fn supertrait_hrtb_vars(
let Some((def_id, bound_vars)) = stack.pop() else {
break None;
};
- // See issue #83753. If someone writes an associated type on a non-trait, just treat it as
- // there being no supertrait HRTBs.
+ // See issue #83753. If someone writes an associated type on a non-trait, just treat it
+ // as there being no supertrait HRTBs.
match tcx.def_kind(def_id) {
DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
_ => break None,
@@ -2067,7 +2067,7 @@ fn try_append_return_type_notation_params(
self.tcx,
trait_def_id,
item_segment.ident,
- ty::AssocKind::Fn,
+ ty::AssocTag::Fn,
)
});
@@ -2112,7 +2112,7 @@ fn try_append_return_type_notation_params(
self.tcx,
trait_def_id,
item_segment.ident,
- ty::AssocKind::Fn,
+ ty::AssocTag::Fn,
) else {
return;
};
@@ -2440,7 +2440,7 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
}
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
- if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
+ if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
self.regions.insert(def_id);
}
}
@@ -2453,7 +2453,7 @@ struct AllCollector {
impl<'tcx> Visitor<'tcx> for AllCollector {
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
- if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
+ if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind {
self.regions.insert(def_id);
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 772197a..50e20a1 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -32,9 +32,11 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
for &assoc_id in tcx.associated_item_def_ids(impl_def_id) {
let assoc = tcx.associated_item(assoc_id);
match assoc.kind {
- ty::AssocKind::Const | ty::AssocKind::Fn => locator.check(assoc_id.expect_local()),
+ ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => {
+ locator.check(assoc_id.expect_local())
+ }
// Associated types don't have bodies, so they can't constrain hidden types
- ty::AssocKind::Type => {}
+ ty::AssocKind::Type { .. } => {}
}
}
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index 610b293..526ee30 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -4,7 +4,7 @@
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan, pluralize};
use rustc_hir as hir;
-use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
+use rustc_middle::ty::{self as ty, AssocItems, TyCtxt};
use rustc_span::def_id::DefId;
use tracing::debug;
@@ -486,13 +486,13 @@ fn get_unbound_associated_types(&self) -> Vec<String> {
let items: &AssocItems = self.tcx.associated_items(self.def_id);
items
.in_definition_order()
- .filter(|item| item.kind == AssocKind::Type)
+ .filter(|item| item.is_type())
.filter(|item| {
!self
.gen_args
.constraints
.iter()
- .any(|constraint| constraint.ident.name == item.name)
+ .any(|constraint| constraint.ident.name == item.name())
})
.filter(|item| !item.is_impl_trait_in_trait())
.map(|item| self.tcx.item_ident(item.def_id).to_string())
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 24d05b4..bf91eb1 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -431,16 +431,16 @@ pub(super) fn lower_assoc_item_constraint(
) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx();
- let assoc_kind = if constraint.gen_args.parenthesized
+ let assoc_tag = if constraint.gen_args.parenthesized
== hir::GenericArgsParentheses::ReturnTypeNotation
{
- ty::AssocKind::Fn
+ ty::AssocTag::Fn
} else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
constraint.kind
{
- ty::AssocKind::Const
+ ty::AssocTag::Const
} else {
- ty::AssocKind::Type
+ ty::AssocTag::Type
};
// Given something like `U: Trait<T = X>`, we want to produce a predicate like
@@ -453,7 +453,7 @@ pub(super) fn lower_assoc_item_constraint(
// trait SuperTrait<A> { type T; }
let candidate = if self.probe_trait_that_defines_assoc_item(
trait_ref.def_id(),
- assoc_kind,
+ assoc_tag,
constraint.ident,
) {
// Simple case: The assoc item is defined in the current trait.
@@ -464,7 +464,7 @@ pub(super) fn lower_assoc_item_constraint(
self.probe_single_bound_for_assoc_item(
|| traits::supertraits(tcx, trait_ref),
AssocItemQSelf::Trait(trait_ref.def_id()),
- assoc_kind,
+ assoc_tag,
constraint.ident,
path_span,
Some(constraint),
@@ -474,7 +474,7 @@ pub(super) fn lower_assoc_item_constraint(
let assoc_item = self
.probe_assoc_item(
constraint.ident,
- assoc_kind,
+ assoc_tag,
hir_ref_id,
constraint.span,
candidate.def_id(),
@@ -493,7 +493,7 @@ pub(super) fn lower_assoc_item_constraint(
})
.or_insert(constraint.span);
- let projection_term = if let ty::AssocKind::Fn = assoc_kind {
+ let projection_term = if let ty::AssocTag::Fn = assoc_tag {
let bound_vars = tcx.late_bound_vars(constraint.hir_id);
ty::Binder::bind_with_vars(
self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
@@ -542,7 +542,7 @@ pub(super) fn lower_assoc_item_constraint(
};
match constraint.kind {
- hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => {
+ hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => {
return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
span: constraint.span,
}));
@@ -679,7 +679,7 @@ pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<
trait_def_id,
hir_ty.span,
item_segment,
- ty::AssocKind::Type,
+ ty::AssocTag::Type,
);
return Ty::new_error(tcx, guar);
};
@@ -771,7 +771,7 @@ fn resolve_type_relative_return_type_notation(
)
},
AssocItemQSelf::SelfTyAlias,
- ty::AssocKind::Fn,
+ ty::AssocTag::Fn,
assoc_ident,
span,
None,
@@ -783,7 +783,7 @@ fn resolve_type_relative_return_type_notation(
) => self.probe_single_ty_param_bound_for_assoc_item(
param_did.expect_local(),
qself.span,
- ty::AssocKind::Fn,
+ ty::AssocTag::Fn,
assoc_ident,
span,
)?,
@@ -823,7 +823,7 @@ fn resolve_type_relative_return_type_notation(
let trait_def_id = bound.def_id();
let assoc_ty = self
- .probe_assoc_item(assoc_ident, ty::AssocKind::Fn, qpath_hir_id, span, trait_def_id)
+ .probe_assoc_item(assoc_ident, ty::AssocTag::Fn, qpath_hir_id, span, trait_def_id)
.expect("failed to find associated type");
Ok((bound, assoc_ty.def_id))
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index e64cd8e..88f7458 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -201,7 +201,7 @@ pub(super) fn lower_trait_object_ty(
tcx.associated_items(pred.trait_ref.def_id)
.in_definition_order()
// We only care about associated types.
- .filter(|item| item.kind == ty::AssocKind::Type)
+ .filter(|item| item.is_type())
// No RPITITs -- they're not dyn-compatible for now.
.filter(|item| !item.is_impl_trait_in_trait())
// If the associated type has a `where Self: Sized` bound,
@@ -415,7 +415,7 @@ pub(super) fn lower_trait_object_ty(
self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime)
} else {
let reason =
- if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res {
+ if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind {
if let hir::Node::Ty(hir::Ty {
kind: hir::TyKind::Ref(parent_lifetime, _),
..
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 5a0524d..3759a22 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -116,7 +116,7 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
&self,
all_candidates: impl Fn() -> I,
qself: AssocItemQSelf,
- assoc_kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
assoc_ident: Ident,
span: Span,
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
@@ -134,14 +134,14 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
}) {
return self.complain_about_assoc_kind_mismatch(
assoc_item,
- assoc_kind,
+ assoc_tag,
assoc_ident,
span,
constraint,
);
}
- let assoc_kind_str = assoc_kind_str(assoc_kind);
+ let assoc_kind_str = assoc_tag_str(assoc_tag);
let qself_str = qself.to_string(tcx);
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
@@ -168,7 +168,11 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
let all_candidate_names: Vec<_> = all_candidates()
.flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
.filter_map(|item| {
- (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name)
+ if !item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag {
+ item.opt_name()
+ } else {
+ None
+ }
})
.collect();
@@ -200,7 +204,7 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
.iter()
.flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
.filter_map(|item| {
- (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name)
+ (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name())
})
.collect();
@@ -213,7 +217,7 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
.filter(|trait_def_id| {
tcx.associated_items(trait_def_id)
.filter_by_name_unhygienic(suggested_name)
- .any(|item| item.kind == assoc_kind)
+ .any(|item| item.as_tag() == assoc_tag)
})
.collect::<Vec<_>>()[..]
{
@@ -330,14 +334,14 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
fn complain_about_assoc_kind_mismatch(
&self,
assoc_item: &ty::AssocItem,
- assoc_kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
ident: Ident,
span: Span,
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
) -> ErrorGuaranteed {
let tcx = self.tcx();
- let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind
+ let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind
&& let Some(constraint) = constraint
&& let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
{
@@ -375,17 +379,17 @@ fn complain_about_assoc_kind_mismatch(
hir::Term::Ty(ty) => ty.span,
hir::Term::Const(ct) => ct.span(),
};
- (span, Some(ident.span), assoc_item.kind, assoc_kind)
+ (span, Some(ident.span), assoc_item.as_tag(), assoc_tag)
} else {
- (ident.span, None, assoc_kind, assoc_item.kind)
+ (ident.span, None, assoc_tag, assoc_item.as_tag())
};
self.dcx().emit_err(errors::AssocKindMismatch {
span,
- expected: assoc_kind_str(expected),
- got: assoc_kind_str(got),
+ expected: assoc_tag_str(expected),
+ got: assoc_tag_str(got),
expected_because_label,
- assoc_kind: assoc_kind_str(assoc_item.kind),
+ assoc_kind: assoc_tag_str(assoc_item.as_tag()),
def_span: tcx.def_span(assoc_item.def_id),
bound_on_assoc_const_label,
wrap_in_braces_sugg,
@@ -398,9 +402,9 @@ pub(super) fn report_ambiguous_assoc(
types: &[String],
traits: &[String],
name: Symbol,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> ErrorGuaranteed {
- let kind_str = assoc_kind_str(kind);
+ let kind_str = assoc_tag_str(assoc_tag);
let mut err =
struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
if self
@@ -569,7 +573,7 @@ pub(crate) fn complain_about_inherent_assoc_not_found(
candidates: Vec<(DefId, (DefId, DefId))>,
fulfillment_errors: Vec<FulfillmentError<'tcx>>,
span: Span,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> ErrorGuaranteed {
// FIXME(fmease): This was copied in parts from an old version of `rustc_hir_typeck::method::suggest`.
// Either
@@ -579,14 +583,14 @@ pub(crate) fn complain_about_inherent_assoc_not_found(
let tcx = self.tcx();
- let kind_str = assoc_kind_str(kind);
+ let assoc_tag_str = assoc_tag_str(assoc_tag);
let adt_did = self_ty.ty_adt_def().map(|def| def.did());
let add_def_label = |err: &mut Diag<'_>| {
if let Some(did) = adt_did {
err.span_label(
tcx.def_span(did),
format!(
- "associated {kind_str} `{name}` not found for this {}",
+ "associated {assoc_tag_str} `{name}` not found for this {}",
tcx.def_descr(did)
),
);
@@ -615,11 +619,11 @@ pub(crate) fn complain_about_inherent_assoc_not_found(
self.dcx(),
name.span,
E0220,
- "associated {kind_str} `{name}` not found for `{self_ty}` in the current scope"
+ "associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope"
);
err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
err.note(format!(
- "the associated {kind_str} was found for\n{type_candidates}{additional_types}",
+ "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}",
));
add_def_label(&mut err);
return err.emit();
@@ -700,7 +704,7 @@ pub(crate) fn complain_about_inherent_assoc_not_found(
let mut err = self.dcx().struct_span_err(
name.span,
- format!("the associated {kind_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
+ format!("the associated {assoc_tag_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
);
if !bounds.is_empty() {
err.note(format!(
@@ -710,7 +714,7 @@ pub(crate) fn complain_about_inherent_assoc_not_found(
}
err.span_label(
name.span,
- format!("associated {kind_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
+ format!("associated {assoc_tag_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
);
for (span, mut bounds) in bound_spans {
@@ -761,7 +765,7 @@ pub(crate) fn check_for_required_assoc_tys(
// `issue-22560.rs`.
let mut dyn_compatibility_violations = Ok(());
for (assoc_item, trait_ref) in &missing_assoc_types {
- names.entry(trait_ref).or_default().push(assoc_item.name);
+ names.entry(trait_ref).or_default().push(assoc_item.name());
names_len += 1;
let violations =
@@ -812,7 +816,7 @@ pub(crate) fn check_for_required_assoc_tys(
let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind(
tcx,
ident,
- ty::AssocKind::Type,
+ ty::AssocTag::Type,
trait_def,
);
@@ -852,16 +856,17 @@ pub(crate) fn check_for_required_assoc_tys(
let mut names: UnordMap<_, usize> = Default::default();
for (item, _) in &missing_assoc_types {
types_count += 1;
- *names.entry(item.name).or_insert(0) += 1;
+ *names.entry(item.name()).or_insert(0) += 1;
}
let mut dupes = false;
let mut shadows = false;
for (item, trait_ref) in &missing_assoc_types {
- let prefix = if names[&item.name] > 1 {
+ let name = item.name();
+ let prefix = if names[&name] > 1 {
let trait_def_id = trait_ref.def_id();
dupes = true;
format!("{}::", tcx.def_path_str(trait_def_id))
- } else if bound_names.get(&item.name).is_some_and(|x| *x != item) {
+ } else if bound_names.get(&name).is_some_and(|x| *x != item) {
let trait_def_id = trait_ref.def_id();
shadows = true;
format!("{}::", tcx.def_path_str(trait_def_id))
@@ -871,7 +876,7 @@ pub(crate) fn check_for_required_assoc_tys(
let mut is_shadowed = false;
- if let Some(assoc_item) = bound_names.get(&item.name)
+ if let Some(assoc_item) = bound_names.get(&name)
&& *assoc_item != item
{
is_shadowed = true;
@@ -880,17 +885,14 @@ pub(crate) fn check_for_required_assoc_tys(
if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" };
err.span_label(
tcx.def_span(assoc_item.def_id),
- format!("`{}{}` shadowed here{}", prefix, item.name, rename_message),
+ format!("`{}{}` shadowed here{}", prefix, name, rename_message),
);
}
let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
- err.span_label(
- sp,
- format!("`{}{}` defined here{}", prefix, item.name, rename_message),
- );
+ err.span_label(sp, format!("`{}{}` defined here{}", prefix, name, rename_message));
}
}
if potential_assoc_types.len() == missing_assoc_types.len() {
@@ -903,7 +905,7 @@ pub(crate) fn check_for_required_assoc_tys(
{
let types: Vec<_> = missing_assoc_types
.iter()
- .map(|(item, _)| format!("{} = Type", item.name))
+ .map(|(item, _)| format!("{} = Type", item.name()))
.collect();
let code = if let Some(snippet) = snippet.strip_suffix('>') {
// The user wrote `Trait<'a>` or similar and we don't have a type we can
@@ -938,16 +940,17 @@ pub(crate) fn check_for_required_assoc_tys(
let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
for (item, _) in &missing_assoc_types {
types_count += 1;
- *names.entry(item.name).or_insert(0) += 1;
+ *names.entry(item.name()).or_insert(0) += 1;
}
let mut label = vec![];
for (item, trait_ref) in &missing_assoc_types {
- let postfix = if names[&item.name] > 1 {
+ let name = item.name();
+ let postfix = if names[&name] > 1 {
format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
} else {
String::new()
};
- label.push(format!("`{}`{}", item.name, postfix));
+ label.push(format!("`{}`{}", name, postfix));
}
if !label.is_empty() {
err.span_label(
@@ -1022,12 +1025,13 @@ pub(crate) fn maybe_report_similar_assoc_fn(
.map(|simple_ty| tcx.incoherent_impls(simple_ty))
})
&& let name = Symbol::intern(&format!("{ident2}_{ident3}"))
- && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = inherent_impls
+ && let Some(item) = inherent_impls
.iter()
.flat_map(|inherent_impl| {
tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
})
.next()
+ && item.is_fn()
{
Err(struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type")
.with_span_suggestion_verbose(
@@ -1629,10 +1633,10 @@ fn generics_args_err_extend<'a>(
}
}
-pub(crate) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
- match kind {
- ty::AssocKind::Fn => "function",
- ty::AssocKind::Const => "constant",
- ty::AssocKind::Type => "type",
+pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str {
+ match assoc_tag {
+ ty::AssocTag::Fn => "function",
+ ty::AssocTag::Const => "constant",
+ ty::AssocTag::Type => "type",
}
}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 8e62dce..483b61a 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -501,8 +501,8 @@ fn maybe_suggest_typoed_method(
let names: Vec<_> = tcx
.associated_items(trait_def_id)
.in_definition_order()
- .filter(|assoc| assoc.kind.namespace() == Namespace::ValueNS)
- .map(|cand| cand.name)
+ .filter(|assoc| assoc.namespace() == Namespace::ValueNS)
+ .map(|cand| cand.name())
.collect();
if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
diag.span_suggestion_verbose(
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 83aa0d9..7605c6c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -38,8 +38,8 @@
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
use rustc_middle::ty::{
- self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
- TypeVisitableExt, TypingMode, Upcast, fold_regions,
+ self, AssocTag, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty,
+ TyCtxt, TypeVisitableExt, TypingMode, Upcast, fold_regions,
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@@ -51,7 +51,7 @@
use rustc_trait_selection::traits::{self, ObligationCtxt};
use tracing::{debug, instrument};
-use self::errors::assoc_kind_str;
+use self::errors::assoc_tag_str;
use crate::check::check_abi_fn_ptr;
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoVariantNamed};
use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
@@ -168,7 +168,7 @@ fn lower_assoc_shared(
item_def_id: DefId,
item_segment: &hir::PathSegment<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed>;
fn lower_fn_sig(
@@ -251,10 +251,10 @@ enum LowerAssocMode {
}
impl LowerAssocMode {
- fn kind(self) -> ty::AssocKind {
+ fn assoc_tag(self) -> ty::AssocTag {
match self {
- LowerAssocMode::Type { .. } => ty::AssocKind::Type,
- LowerAssocMode::Const => ty::AssocKind::Const,
+ LowerAssocMode::Type { .. } => ty::AssocTag::Type,
+ LowerAssocMode::Const => ty::AssocTag::Const,
}
}
@@ -268,7 +268,8 @@ fn def_kind(self) -> DefKind {
fn permit_variants(self) -> bool {
match self {
LowerAssocMode::Type { permit_variants } => permit_variants,
- // FIXME(mgca): Support paths like `Option::<T>::None` or `Option::<T>::Some` which resolve to const ctors/fn items respectively
+ // FIXME(mgca): Support paths like `Option::<T>::None` or `Option::<T>::Some` which
+ // resolve to const ctors/fn items respectively.
LowerAssocMode::Const => false,
}
}
@@ -932,12 +933,12 @@ fn lower_mono_trait_ref(
fn probe_trait_that_defines_assoc_item(
&self,
trait_def_id: DefId,
- assoc_kind: ty::AssocKind,
+ assoc_tag: AssocTag,
assoc_ident: Ident,
) -> bool {
self.tcx()
.associated_items(trait_def_id)
- .find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_kind, trait_def_id)
+ .find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_tag, trait_def_id)
.is_some()
}
@@ -975,7 +976,7 @@ fn probe_single_ty_param_bound_for_assoc_item(
&self,
ty_param_def_id: LocalDefId,
ty_param_span: Span,
- kind: ty::AssocKind,
+ assoc_tag: AssocTag,
assoc_ident: Ident,
span: Span,
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
@@ -993,7 +994,7 @@ fn probe_single_ty_param_bound_for_assoc_item(
traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_ident)
},
AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
- kind,
+ assoc_tag,
assoc_ident,
span,
None,
@@ -1010,7 +1011,7 @@ fn probe_single_bound_for_assoc_item<I>(
&self,
all_candidates: impl Fn() -> I,
qself: AssocItemQSelf,
- assoc_kind: ty::AssocKind,
+ assoc_tag: AssocTag,
assoc_ident: Ident,
span: Span,
constraint: Option<&hir::AssocItemConstraint<'tcx>>,
@@ -1021,14 +1022,14 @@ fn probe_single_bound_for_assoc_item<I>(
let tcx = self.tcx();
let mut matching_candidates = all_candidates().filter(|r| {
- self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_ident)
+ self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_tag, assoc_ident)
});
let Some(bound) = matching_candidates.next() else {
let reported = self.complain_about_assoc_item_not_found(
all_candidates,
qself,
- assoc_kind,
+ assoc_tag,
assoc_ident,
span,
constraint,
@@ -1040,7 +1041,7 @@ fn probe_single_bound_for_assoc_item<I>(
if let Some(bound2) = matching_candidates.next() {
debug!(?bound2);
- let assoc_kind_str = errors::assoc_kind_str(assoc_kind);
+ let assoc_kind_str = errors::assoc_tag_str(assoc_tag);
let qself_str = qself.to_string(tcx);
let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem {
span,
@@ -1059,14 +1060,15 @@ fn probe_single_bound_for_assoc_item<I>(
},
);
- // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!).
+ // FIXME(#97583): Print associated item bindings properly (i.e., not as equality
+ // predicates!).
// FIXME: Turn this into a structured, translateable & more actionable suggestion.
let mut where_bounds = vec![];
for bound in [bound, bound2].into_iter().chain(matching_candidates) {
let bound_id = bound.def_id();
let bound_span = tcx
.associated_items(bound_id)
- .find_by_ident_and_kind(tcx, assoc_ident, assoc_kind, bound_id)
+ .find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, bound_id)
.and_then(|item| tcx.hir_span_if_local(item.def_id));
if let Some(bound_span) = bound_span {
@@ -1265,7 +1267,7 @@ fn lower_assoc_path_shared(
qself_ty,
hir_ref_id,
span,
- mode.kind(),
+ mode.assoc_tag(),
)? {
return Ok(LoweredAssoc::Term(did, args));
}
@@ -1296,7 +1298,7 @@ fn lower_assoc_path_shared(
)
},
AssocItemQSelf::SelfTyAlias,
- mode.kind(),
+ mode.assoc_tag(),
assoc_ident,
span,
None,
@@ -1308,12 +1310,12 @@ fn lower_assoc_path_shared(
) => self.probe_single_ty_param_bound_for_assoc_item(
param_did.expect_local(),
qself.span,
- mode.kind(),
+ mode.assoc_tag(),
assoc_ident,
span,
)?,
_ => {
- let kind_str = assoc_kind_str(mode.kind());
+ let kind_str = assoc_tag_str(mode.assoc_tag());
let reported = if variant_resolution.is_some() {
// Variant in type position
let msg = format!("expected {kind_str}, found variant `{assoc_ident}`");
@@ -1420,7 +1422,7 @@ fn lower_assoc_path_shared(
&[qself_ty.to_string()],
&traits,
assoc_ident.name,
- mode.kind(),
+ mode.assoc_tag(),
)
};
return Err(reported);
@@ -1429,10 +1431,15 @@ fn lower_assoc_path_shared(
let trait_did = bound.def_id();
let assoc_item = self
- .probe_assoc_item(assoc_ident, mode.kind(), hir_ref_id, span, trait_did)
+ .probe_assoc_item(assoc_ident, mode.assoc_tag(), hir_ref_id, span, trait_did)
.expect("failed to find associated item");
- let (def_id, args) =
- self.lower_assoc_shared(span, assoc_item.def_id, assoc_segment, bound, mode.kind())?;
+ let (def_id, args) = self.lower_assoc_shared(
+ span,
+ assoc_item.def_id,
+ assoc_segment,
+ bound,
+ mode.assoc_tag(),
+ )?;
let result = LoweredAssoc::Term(def_id, args);
if let Some(variant_def_id) = variant_resolution {
@@ -1469,20 +1476,21 @@ fn probe_inherent_assoc_shared(
self_ty: Ty<'tcx>,
block: HirId,
span: Span,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> Result<Option<(DefId, GenericArgsRef<'tcx>)>, ErrorGuaranteed> {
let tcx = self.tcx();
if !tcx.features().inherent_associated_types() {
- match kind {
- // Don't attempt to look up inherent associated types when the feature is not enabled.
- // Theoretically it'd be fine to do so since we feature-gate their definition site.
- // However, due to current limitations of the implementation (caused by us performing
- // selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle
- // errors (#108491) which mask the feature-gate error, needlessly confusing users
- // who use IATs by accident (#113265).
- ty::AssocKind::Type => return Ok(None),
- ty::AssocKind::Const => {
+ match assoc_tag {
+ // Don't attempt to look up inherent associated types when the feature is not
+ // enabled. Theoretically it'd be fine to do so since we feature-gate their
+ // definition site. However, due to current limitations of the implementation
+ // (caused by us performing selection during HIR ty lowering instead of in the
+ // trait solver), IATs can lead to cycle errors (#108491) which mask the
+ // feature-gate error, needlessly confusing users who use IATs by accident
+ // (#113265).
+ ty::AssocTag::Type => return Ok(None),
+ ty::AssocTag::Const => {
// We also gate the mgca codepath for type-level uses of inherent consts
// with the inherent_associated_types feature gate since it relies on the
// same machinery and has similar rough edges.
@@ -1494,7 +1502,7 @@ fn probe_inherent_assoc_shared(
)
.emit());
}
- ty::AssocKind::Fn => unreachable!(),
+ ty::AssocTag::Fn => unreachable!(),
}
}
@@ -1503,7 +1511,8 @@ fn probe_inherent_assoc_shared(
.inherent_impls(adt_did)
.iter()
.filter_map(|&impl_| {
- let (item, scope) = self.probe_assoc_item_unchecked(name, kind, block, impl_)?;
+ let (item, scope) =
+ self.probe_assoc_item_unchecked(name, assoc_tag, block, impl_)?;
Some((impl_, (item.def_id, scope)))
})
.collect();
@@ -1542,7 +1551,7 @@ fn probe_inherent_assoc_shared(
self_ty,
|self_ty| {
self.select_inherent_assoc_candidates(
- infcx, name, span, self_ty, param_env, candidates, kind,
+ infcx, name, span, self_ty, param_env, candidates, assoc_tag,
)
},
)?;
@@ -1570,7 +1579,7 @@ fn select_inherent_assoc_candidates(
self_ty: Ty<'tcx>,
param_env: ParamEnv<'tcx>,
candidates: Vec<(DefId, (DefId, DefId))>,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
let tcx = self.tcx();
let mut fulfillment_errors = Vec::new();
@@ -1621,7 +1630,7 @@ fn select_inherent_assoc_candidates(
candidates,
fulfillment_errors,
span,
- kind,
+ assoc_tag,
)),
&[applicable_candidate] => Ok(applicable_candidate),
@@ -1640,12 +1649,12 @@ fn select_inherent_assoc_candidates(
fn probe_assoc_item(
&self,
ident: Ident,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
block: HirId,
span: Span,
scope: DefId,
) -> Option<ty::AssocItem> {
- let (item, scope) = self.probe_assoc_item_unchecked(ident, kind, block, scope)?;
+ let (item, scope) = self.probe_assoc_item_unchecked(ident, assoc_tag, block, scope)?;
self.check_assoc_item(item.def_id, ident, scope, block, span);
Some(item)
}
@@ -1657,7 +1666,7 @@ fn probe_assoc_item(
fn probe_assoc_item_unchecked(
&self,
ident: Ident,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
block: HirId,
scope: DefId,
) -> Option<(ty::AssocItem, /*scope*/ DefId)> {
@@ -1670,7 +1679,7 @@ fn probe_assoc_item_unchecked(
let item = tcx
.associated_items(scope)
.filter_by_name_unhygienic(ident.name)
- .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
+ .find(|i| i.as_tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
Some((*item, def_scope))
}
@@ -1722,9 +1731,9 @@ fn probe_traits_that_match_assoc_ty(
tcx.associated_items(*trait_def_id)
.in_definition_order()
.any(|i| {
- i.kind.namespace() == Namespace::TypeNS
+ i.namespace() == Namespace::TypeNS
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
- && matches!(i.kind, ty::AssocKind::Type)
+ && i.is_type()
})
// Consider only accessible traits
&& tcx.visibility(*trait_def_id)
@@ -1770,7 +1779,7 @@ fn lower_qpath_ty(
item_def_id,
trait_segment,
item_segment,
- ty::AssocKind::Type,
+ ty::AssocTag::Type,
) {
Ok((item_def_id, item_args)) => {
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
@@ -1795,7 +1804,7 @@ fn lower_qpath_const(
item_def_id,
trait_segment,
item_segment,
- ty::AssocKind::Const,
+ ty::AssocTag::Const,
) {
Ok((item_def_id, item_args)) => {
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
@@ -1813,7 +1822,7 @@ fn lower_qpath_shared(
item_def_id: DefId,
trait_segment: &hir::PathSegment<'tcx>,
item_segment: &hir::PathSegment<'tcx>,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {
let tcx = self.tcx();
@@ -1821,7 +1830,12 @@ fn lower_qpath_shared(
debug!(?trait_def_id);
let Some(self_ty) = opt_self_ty else {
- return Err(self.error_missing_qpath_self_ty(trait_def_id, span, item_segment, kind));
+ return Err(self.error_missing_qpath_self_ty(
+ trait_def_id,
+ span,
+ item_segment,
+ assoc_tag,
+ ));
};
debug!(?self_ty);
@@ -1840,7 +1854,7 @@ fn error_missing_qpath_self_ty(
trait_def_id: DefId,
span: Span,
item_segment: &hir::PathSegment<'tcx>,
- kind: ty::AssocKind,
+ assoc_tag: ty::AssocTag,
) -> ErrorGuaranteed {
let tcx = self.tcx();
let path_str = tcx.def_path_str(trait_def_id);
@@ -1877,7 +1891,13 @@ fn error_missing_qpath_self_ty(
// FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
// references the trait. Relevant for the first case in
// `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
- self.report_ambiguous_assoc(span, &type_names, &[path_str], item_segment.ident.name, kind)
+ self.report_ambiguous_assoc(
+ span,
+ &type_names,
+ &[path_str],
+ item_segment.ident.name,
+ assoc_tag,
+ )
}
pub fn prohibit_generic_args<'a>(
@@ -2862,7 +2882,7 @@ pub(super) fn suggest_trait_fn_ty_for_impl_fn_infer(
let assoc = tcx.associated_items(trait_ref.def_id).find_by_ident_and_kind(
tcx,
*ident,
- ty::AssocKind::Fn,
+ ty::AssocTag::Fn,
trait_ref.def_id,
)?;
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index c30b39d..cbdc501 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -112,14 +112,14 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
.flat_map(|def_id| {
let item = tcx.associated_item(def_id);
match item.kind {
- ty::AssocKind::Type => {
+ ty::AssocKind::Type { .. } => {
if item.defaultness(tcx).has_value() {
cgp::parameters_for(tcx, tcx.type_of(def_id).instantiate_identity(), true)
} else {
vec![]
}
}
- ty::AssocKind::Fn | ty::AssocKind::Const => vec![],
+ ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => vec![],
}
})
.collect();
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index e7ecd72..e1ad812 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -59,7 +59,6 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index e5ab317..ff4385c 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1871,10 +1871,11 @@ fn print_ty_pat(&mut self, pat: &hir::TyPat<'_>) {
fn print_pat(&mut self, pat: &hir::Pat<'_>) {
self.maybe_print_comment(pat.span.lo());
self.ann.pre(self, AnnNode::Pat(pat));
- // Pat isn't normalized, but the beauty of it
- // is that it doesn't matter
+ // Pat isn't normalized, but the beauty of it is that it doesn't matter.
match pat.kind {
- PatKind::Missing => unreachable!(),
+ // Printing `_` isn't ideal for a missing pattern, but it's easy and good enough.
+ // E.g. `fn(u32)` gets printed as `fn(_: u32)`.
+ PatKind::Missing => self.word("_"),
PatKind::Wild => self.word("_"),
PatKind::Never => self.word("!"),
PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => {
@@ -2164,7 +2165,9 @@ fn print_fn(
s.end();
});
if decl.c_variadic {
- self.word(", ");
+ if !decl.inputs.is_empty() {
+ self.word(", ");
+ }
print_arg(self, None);
self.word("...");
}
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 8f5fddd..b19d9ef 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -1042,30 +1042,31 @@ fn check_ref_cast(
m_cast: ty::TypeAndMut<'tcx>,
) -> Result<CastKind, CastError<'tcx>> {
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
- if m_expr.mutbl >= m_cast.mutbl {
- if let ty::Array(ety, _) = m_expr.ty.kind() {
- // Due to the limitations of LLVM global constants,
- // region pointers end up pointing at copies of
- // vector elements instead of the original values.
- // To allow raw pointers to work correctly, we
- // need to special-case obtaining a raw pointer
- // from a region pointer to a vector.
+ if m_expr.mutbl >= m_cast.mutbl
+ && let ty::Array(ety, _) = m_expr.ty.kind()
+ && fcx.can_eq(fcx.param_env, *ety, m_cast.ty)
+ {
+ // Due to the limitations of LLVM global constants,
+ // region pointers end up pointing at copies of
+ // vector elements instead of the original values.
+ // To allow raw pointers to work correctly, we
+ // need to special-case obtaining a raw pointer
+ // from a region pointer to a vector.
- // Coerce to a raw pointer so that we generate RawPtr in MIR.
- let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
- fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
- .unwrap_or_else(|_| {
- bug!(
+ // Coerce to a raw pointer so that we generate RawPtr in MIR.
+ let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
+ fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
+ .unwrap_or_else(|_| {
+ bug!(
"could not cast from reference to array to pointer to array ({:?} to {:?})",
self.expr_ty,
array_ptr_type,
)
- });
+ });
- // this will report a type mismatch if needed
- fcx.demand_eqtype(self.span, *ety, m_cast.ty);
- return Ok(CastKind::ArrayPtrCast);
- }
+ // this will report a type mismatch if needed
+ fcx.demand_eqtype(self.span, *ety, m_cast.ty);
+ return Ok(CastKind::ArrayPtrCast);
}
Err(CastError::IllegalCast)
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index f1571cf4..fd89942 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -103,15 +103,6 @@ fn coerce_mutbls<'tcx>(
if from_mutbl >= to_mutbl { Ok(()) } else { Err(TypeError::Mutability) }
}
-/// Do not require any adjustments, i.e. coerce `x -> x`.
-fn identity(_: Ty<'_>) -> Vec<Adjustment<'_>> {
- vec![]
-}
-
-fn simple<'tcx>(kind: Adjust) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
- move |target| vec![Adjustment { kind, target }]
-}
-
/// This always returns `Ok(...)`.
fn success<'tcx>(
adj: Vec<Adjustment<'tcx>>,
@@ -131,7 +122,7 @@ fn new(
Coerce { fcx, cause, allow_two_phase, use_lub: false, coerce_never }
}
- fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
+ fn unify_raw(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
self.commit_if_ok(|_| {
let at = self.at(&self.cause, self.fcx.param_env);
@@ -161,13 +152,30 @@ fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
})
}
+ /// Unify two types (using sub or lub).
+ fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
+ self.unify_raw(a, b)
+ .and_then(|InferOk { value: ty, obligations }| success(vec![], ty, obligations))
+ }
+
/// Unify two types (using sub or lub) and produce a specific coercion.
- fn unify_and<F>(&self, a: Ty<'tcx>, b: Ty<'tcx>, f: F) -> CoerceResult<'tcx>
- where
- F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
- {
- self.unify(a, b)
- .and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations))
+ fn unify_and(
+ &self,
+ a: Ty<'tcx>,
+ b: Ty<'tcx>,
+ adjustments: impl IntoIterator<Item = Adjustment<'tcx>>,
+ final_adjustment: Adjust,
+ ) -> CoerceResult<'tcx> {
+ self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| {
+ success(
+ adjustments
+ .into_iter()
+ .chain(std::iter::once(Adjustment { target: ty, kind: final_adjustment }))
+ .collect(),
+ ty,
+ obligations,
+ )
+ })
}
#[instrument(skip(self))]
@@ -180,10 +188,14 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
// Coercing from `!` to any type is allowed:
if a.is_never() {
if self.coerce_never {
- return success(simple(Adjust::NeverToAny)(b), b, PredicateObligations::new());
+ return success(
+ vec![Adjustment { kind: Adjust::NeverToAny, target: b }],
+ b,
+ PredicateObligations::new(),
+ );
} else {
// Otherwise the only coercion we can do is unification.
- return self.unify_and(a, b, identity);
+ return self.unify(a, b);
}
}
@@ -191,7 +203,7 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
// we have no information about the source type. This will always
// ultimately fall back to some form of subtyping.
if a.is_ty_var() {
- return self.coerce_from_inference_variable(a, b, identity);
+ return self.coerce_from_inference_variable(a, b);
}
// Consider coercing the subtype to a DST
@@ -247,7 +259,7 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
ty::FnPtr(a_sig_tys, a_hdr) => {
// We permit coercion of fn pointers to drop the
// unsafe qualifier.
- self.coerce_from_fn_pointer(a, a_sig_tys.with(a_hdr), b)
+ self.coerce_from_fn_pointer(a_sig_tys.with(a_hdr), b)
}
ty::Closure(closure_def_id_a, args_a) => {
// Non-capturing closures are coercible to
@@ -257,7 +269,7 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
}
_ => {
// Otherwise, just use unification rules.
- self.unify_and(a, b, identity)
+ self.unify(a, b)
}
}
}
@@ -265,12 +277,7 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
/// Coercing *from* an inference variable. In this case, we have no information
/// about the source type, so we can't really do a true coercion and we always
/// fall back to subtyping (`unify_and`).
- fn coerce_from_inference_variable(
- &self,
- a: Ty<'tcx>,
- b: Ty<'tcx>,
- make_adjustments: impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
- ) -> CoerceResult<'tcx> {
+ fn coerce_from_inference_variable(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
debug!("coerce_from_inference_variable(a={:?}, b={:?})", a, b);
assert!(a.is_ty_var() && self.shallow_resolve(a) == a);
assert!(self.shallow_resolve(b) == b);
@@ -298,12 +305,11 @@ fn coerce_from_inference_variable(
"coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}",
target_ty, obligations
);
- let adjustments = make_adjustments(target_ty);
- InferResult::Ok(InferOk { value: (adjustments, target_ty), obligations })
+ success(vec![], target_ty, obligations)
} else {
// One unresolved type variable: just apply subtyping, we may be able
// to do something useful.
- self.unify_and(a, b, make_adjustments)
+ self.unify(a, b)
}
}
@@ -331,7 +337,7 @@ fn coerce_borrowed_pointer(
coerce_mutbls(mt_a.mutbl, mutbl_b)?;
(r_a, mt_a)
}
- _ => return self.unify_and(a, b, identity),
+ _ => return self.unify(a, b),
};
let span = self.cause.span;
@@ -437,7 +443,7 @@ fn coerce_borrowed_pointer(
referent_ty,
mutbl_b, // [1] above
);
- match self.unify(derefd_ty_a, b) {
+ match self.unify_raw(derefd_ty_a, b) {
Ok(ok) => {
found = Some(ok);
break;
@@ -579,13 +585,13 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe
// We only have the latter, so we use an inference variable
// for the former and let type inference do the rest.
let coerce_target = self.next_ty_var(self.cause.span);
- let mut coercion = self.unify_and(coerce_target, target, |target| {
- let unsize = Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), target };
- match reborrow {
- None => vec![unsize],
- Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone(), unsize],
- }
- })?;
+
+ let mut coercion = self.unify_and(
+ coerce_target,
+ target,
+ reborrow.into_iter().flat_map(|(deref, autoref)| [deref, autoref]),
+ Adjust::Pointer(PointerCoercion::Unsize),
+ )?;
let mut selcx = traits::SelectionContext::new(self);
@@ -708,7 +714,7 @@ fn coerce_dyn_star(
&& let ty::Dynamic(b_data, _, ty::DynStar) = b.kind()
&& a_data.principal_def_id() == b_data.principal_def_id()
{
- return self.unify_and(a, b, |_| vec![]);
+ return self.unify(a, b);
}
// Check the obligations of the cast -- for example, when casting
@@ -808,23 +814,15 @@ fn coerce_pin_ref(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
// To complete the reborrow, we need to make sure we can unify the inner types, and if so we
// add the adjustments.
- self.unify_and(a, b, |_inner_ty| {
- vec![Adjustment { kind: Adjust::ReborrowPin(mut_b), target: b }]
- })
+ self.unify_and(a, b, [], Adjust::ReborrowPin(mut_b))
}
- fn coerce_from_safe_fn<F, G>(
+ fn coerce_from_safe_fn(
&self,
- a: Ty<'tcx>,
fn_ty_a: ty::PolyFnSig<'tcx>,
b: Ty<'tcx>,
- to_unsafe: F,
- normal: G,
- ) -> CoerceResult<'tcx>
- where
- F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
- G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
- {
+ adjustment: Option<Adjust>,
+ ) -> CoerceResult<'tcx> {
self.commit_if_ok(|snapshot| {
let outer_universe = self.infcx.universe();
@@ -833,9 +831,19 @@ fn coerce_from_safe_fn<F, G>(
&& hdr_b.safety.is_unsafe()
{
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
- self.unify_and(unsafe_a, b, to_unsafe)
+ self.unify_and(
+ unsafe_a,
+ b,
+ adjustment
+ .map(|kind| Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }),
+ Adjust::Pointer(PointerCoercion::UnsafeFnPointer),
+ )
} else {
- self.unify_and(a, b, normal)
+ let a = Ty::new_fn_ptr(self.tcx, fn_ty_a);
+ match adjustment {
+ Some(adjust) => self.unify_and(a, b, [], adjust),
+ None => self.unify(a, b),
+ }
};
// FIXME(#73154): This is a hack. Currently LUB can generate
@@ -852,7 +860,6 @@ fn coerce_from_safe_fn<F, G>(
fn coerce_from_fn_pointer(
&self,
- a: Ty<'tcx>,
fn_ty_a: ty::PolyFnSig<'tcx>,
b: Ty<'tcx>,
) -> CoerceResult<'tcx> {
@@ -861,15 +868,9 @@ fn coerce_from_fn_pointer(
//!
let b = self.shallow_resolve(b);
- debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
+ debug!(?fn_ty_a, ?b, "coerce_from_fn_pointer");
- self.coerce_from_safe_fn(
- a,
- fn_ty_a,
- b,
- simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer)),
- identity,
- )
+ self.coerce_from_safe_fn(fn_ty_a, b, None)
}
fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
@@ -916,30 +917,16 @@ fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
self.at(&self.cause, self.param_env).normalize(a_sig);
obligations.extend(o1);
- let a_fn_pointer = Ty::new_fn_ptr(self.tcx, a_sig);
let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn(
- a_fn_pointer,
a_sig,
b,
- |unsafe_ty| {
- vec![
- Adjustment {
- kind: Adjust::Pointer(PointerCoercion::ReifyFnPointer),
- target: a_fn_pointer,
- },
- Adjustment {
- kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer),
- target: unsafe_ty,
- },
- ]
- },
- simple(Adjust::Pointer(PointerCoercion::ReifyFnPointer)),
+ Some(Adjust::Pointer(PointerCoercion::ReifyFnPointer)),
)?;
obligations.extend(o2);
Ok(InferOk { value, obligations })
}
- _ => self.unify_and(a, b, identity),
+ _ => self.unify(a, b),
}
}
@@ -983,10 +970,11 @@ fn coerce_closure_to_fn(
self.unify_and(
pointer_ty,
b,
- simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety))),
+ [],
+ Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety)),
)
}
- _ => self.unify_and(a, b, identity),
+ _ => self.unify(a, b),
}
}
@@ -1001,7 +989,7 @@ fn coerce_raw_ptr(
let (is_ref, mt_a) = match *a.kind() {
ty::Ref(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }),
ty::RawPtr(ty, mutbl) => (false, ty::TypeAndMut { ty, mutbl }),
- _ => return self.unify_and(a, b, identity),
+ _ => return self.unify(a, b),
};
coerce_mutbls(mt_a.mutbl, mutbl_b)?;
@@ -1011,16 +999,16 @@ fn coerce_raw_ptr(
// representation, we still register an Adjust::DerefRef so that
// regionck knows that the region for `a` must be valid here.
if is_ref {
- self.unify_and(a_raw, b, |target| {
- vec![
- Adjustment { kind: Adjust::Deref(None), target: mt_a.ty },
- Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), target },
- ]
- })
+ self.unify_and(
+ a_raw,
+ b,
+ [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }],
+ Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)),
+ )
} else if mt_a.mutbl != mutbl_b {
- self.unify_and(a_raw, b, simple(Adjust::Pointer(PointerCoercion::MutToConstPointer)))
+ self.unify_and(a_raw, b, [], Adjust::Pointer(PointerCoercion::MutToConstPointer))
} else {
- self.unify_and(a_raw, b, identity)
+ self.unify(a_raw, b)
}
}
}
@@ -1118,9 +1106,9 @@ pub(crate) fn deref_steps_for_suggestion(
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
// We don't ever need two-phase here since we throw out the result of the coercion.
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
- coerce
- .autoderef(DUMMY_SP, expr_ty)
- .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
+ coerce.autoderef(DUMMY_SP, expr_ty).find_map(|(ty, steps)| {
+ self.probe(|_| coerce.unify_raw(ty, target)).ok().map(|_| steps)
+ })
}
/// Given a type, this function will calculate and return the type given
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index fec4599..d1bc54e 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1089,14 +1089,8 @@ pub(crate) fn get_conversion_methods_for_diagnostic(
/// This function checks whether the method is not static and does not accept other parameters than `self`.
fn has_only_self_parameter(&self, method: &AssocItem) -> bool {
- match method.kind {
- ty::AssocKind::Fn => {
- method.fn_has_self_parameter
- && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len()
- == 1
- }
- _ => false,
- }
+ method.is_method()
+ && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() == 1
}
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index dfaa374..9e73054 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -5,7 +5,7 @@
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagSymbolList, EmissionGuarantee, IntoDiagArg, MultiSpan,
- SubdiagMessageOp, Subdiagnostic,
+ Subdiagnostic,
};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{self, Ty};
@@ -270,11 +270,7 @@ pub(crate) struct SuggestAnnotations {
pub suggestions: Vec<SuggestAnnotation>,
}
impl Subdiagnostic for SuggestAnnotations {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
if self.suggestions.is_empty() {
return;
}
@@ -337,11 +333,7 @@ pub(crate) struct TypeMismatchFruTypo {
}
impl Subdiagnostic for TypeMismatchFruTypo {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("expr", self.expr.as_deref().unwrap_or("NONE"));
// Only explain that `a ..b` is a range if it's split up
@@ -599,11 +591,7 @@ pub(crate) struct RemoveSemiForCoerce {
}
impl Subdiagnostic for RemoveSemiForCoerce {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut multispan: MultiSpan = self.semi.into();
multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr);
multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret);
@@ -778,20 +766,16 @@ pub(crate) enum CastUnknownPointerSub {
}
impl rustc_errors::Subdiagnostic for CastUnknownPointerSub {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
CastUnknownPointerSub::To(span) => {
- let msg = f(diag, crate::fluent_generated::hir_typeck_label_to);
+ let msg = diag.eagerly_translate(fluent::hir_typeck_label_to);
diag.span_label(span, msg);
- let msg = f(diag, crate::fluent_generated::hir_typeck_note);
+ let msg = diag.eagerly_translate(fluent::hir_typeck_note);
diag.note(msg);
}
CastUnknownPointerSub::From(span) => {
- let msg = f(diag, crate::fluent_generated::hir_typeck_label_from);
+ let msg = diag.eagerly_translate(fluent::hir_typeck_label_from);
diag.span_label(span, msg);
}
}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index de2f039..d6a7bfc 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1600,11 +1600,7 @@ fn check_expr_method_call(
Ok(method)
}
Err(error) => {
- if segment.ident.name == kw::Empty {
- span_bug!(rcvr.span, "empty method name")
- } else {
- Err(self.report_method_error(expr.hir_id, rcvr_t, error, expected, false))
- }
+ Err(self.report_method_error(expr.hir_id, rcvr_t, error, expected, false))
}
};
@@ -2588,9 +2584,7 @@ fn report_private_fields(
.into_iter()
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
// Only assoc fn with no receivers.
- .filter(|item| {
- matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter
- })
+ .filter(|item| item.is_fn() && !item.is_method())
.filter_map(|item| {
// Only assoc fns that return `Self`
let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
@@ -2603,8 +2597,9 @@ fn report_private_fields(
return None;
}
let input_len = fn_sig.inputs().skip_binder().len();
- let order = !item.name.as_str().starts_with("new");
- Some((order, item.name, input_len))
+ let name = item.name();
+ let order = !name.as_str().starts_with("new");
+ Some((order, name, input_len))
})
.collect::<Vec<_>>();
items.sort_by_key(|(order, _, _)| *order);
@@ -2942,9 +2937,7 @@ fn check_expr_field(
return Ty::new_error(self.tcx(), guar);
}
- let guar = if field.name == kw::Empty {
- self.dcx().span_bug(field.span, "field name with no name")
- } else if self.method_exists_for_diagnostic(
+ let guar = if self.method_exists_for_diagnostic(
field,
base_ty,
expr.hir_id,
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 27df8f0..f5e0f01 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -1000,6 +1000,8 @@ fn walk_pat(
// determines whether to borrow *at the level of the deref pattern* rather than
// borrowing the bound place (since that inner place is inside the temporary that
// stores the result of calling `deref()`/`deref_mut()` so can't be captured).
+ // HACK: this could be a fake pattern corresponding to a deref inserted by match
+ // ergonomics, in which case `pat.hir_id` will be the id of the subpattern.
let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern);
let mutability =
if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
@@ -1227,9 +1229,9 @@ fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> Result<Ty<'tcx>, Cx::Error> {
// actually this is somewhat "disjoint" from the code below
// that aims to account for `ref x`.
if let Some(vec) = self.cx.typeck_results().pat_adjustments().get(pat.hir_id) {
- if let Some(first_ty) = vec.first() {
- debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
- return Ok(*first_ty);
+ if let Some(first_adjust) = vec.first() {
+ debug!("pat_ty(pat={:?}) found adjustment `{:?}`", pat, first_adjust);
+ return Ok(first_adjust.source);
}
} else if let PatKind::Ref(subpat, _) = pat.kind
&& self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id)
@@ -1502,16 +1504,21 @@ fn cat_projection(
let mut projections = base_place.place.projections;
let node_ty = self.cx.typeck_results().node_type(node);
- // Opaque types can't have field projections, but we can instead convert
- // the current place in-place (heh) to the hidden type, and then apply all
- // follow up projections on that.
- if node_ty != place_ty
- && self
- .cx
- .try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty)
- .is_impl_trait()
- {
- projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
+ if !self.cx.tcx().next_trait_solver_globally() {
+ // Opaque types can't have field projections, but we can instead convert
+ // the current place in-place (heh) to the hidden type, and then apply all
+ // follow up projections on that.
+ if node_ty != place_ty
+ && self
+ .cx
+ .try_structurally_resolve_type(
+ self.cx.tcx().hir_span(base_place.hir_id),
+ place_ty,
+ )
+ .is_impl_trait()
+ {
+ projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
+ }
}
projections.push(Projection { kind, ty });
PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections)
@@ -1675,12 +1682,31 @@ fn cat_pattern<F>(
// Then we see that to get the same result, we must start with
// `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
// and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
- for _ in
- 0..self.cx.typeck_results().pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len())
- {
+ let typeck_results = self.cx.typeck_results();
+ let adjustments: &[adjustment::PatAdjustment<'tcx>] =
+ typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
+ let mut adjusts = adjustments.iter().peekable();
+ while let Some(adjust) = adjusts.next() {
debug!("applying adjustment to place_with_id={:?}", place_with_id);
- place_with_id = self.cat_deref(pat.hir_id, place_with_id)?;
+ place_with_id = match adjust.kind {
+ adjustment::PatAdjust::BuiltinDeref => self.cat_deref(pat.hir_id, place_with_id)?,
+ adjustment::PatAdjust::OverloadedDeref => {
+ // This adjustment corresponds to an overloaded deref; it borrows the scrutinee to
+ // call `Deref::deref` or `DerefMut::deref_mut`. Invoke the callback before setting
+ // `place_with_id` to the temporary storing the result of the deref.
+ // HACK(dianne): giving the callback a fake deref pattern makes sure it behaves the
+ // same as it would if this were an explicit deref pattern.
+ op(&place_with_id, &hir::Pat { kind: PatKind::Deref(pat), ..*pat })?;
+ let target_ty = match adjusts.peek() {
+ Some(&&next_adjust) => next_adjust.source,
+ // At the end of the deref chain, we get `pat`'s scrutinee.
+ None => self.pat_ty_unadjusted(pat)?,
+ };
+ self.pat_deref_temp(pat.hir_id, pat, target_ty)?
+ }
+ };
}
+ drop(typeck_results); // explicitly release borrow of typeck results, just in case.
let place_with_id = place_with_id; // lose mutability
debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);
@@ -1783,14 +1809,8 @@ fn cat_pattern<F>(
self.cat_pattern(subplace, subpat, op)?;
}
PatKind::Deref(subpat) => {
- let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpat);
- let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
- let re_erased = self.cx.tcx().lifetimes.re_erased;
let ty = self.pat_ty_adjusted(subpat)?;
- let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability);
- // A deref pattern generates a temporary.
- let base = self.cat_rvalue(pat.hir_id, ty);
- let place = self.cat_deref(pat.hir_id, base)?;
+ let place = self.pat_deref_temp(pat.hir_id, subpat, ty)?;
self.cat_pattern(place, subpat, op)?;
}
@@ -1843,6 +1863,23 @@ fn cat_pattern<F>(
Ok(())
}
+ /// Represents the place of the temp that stores the scrutinee of a deref pattern's interior.
+ fn pat_deref_temp(
+ &self,
+ hir_id: HirId,
+ inner: &hir::Pat<'_>,
+ target_ty: Ty<'tcx>,
+ ) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
+ let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(inner);
+ let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
+ let re_erased = self.cx.tcx().lifetimes.re_erased;
+ let ty = Ty::new_ref(self.cx.tcx(), re_erased, target_ty, mutability);
+ // A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ...
+ let base = self.cat_rvalue(hir_id, ty);
+ // ... and the inner pattern matches on the place behind that reference.
+ self.cat_deref(hir_id, base)
+ }
+
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool {
if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() {
// Note that if a non-exhaustive SingleVariant is defined in another crate, we need
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 91190a3..87d92b3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -27,9 +27,9 @@
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
+use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
-use rustc_span::{Span, kw};
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::traits::{
self, NormalizeExt, ObligationCauseCode, StructurallyNormalizeExt,
@@ -833,7 +833,6 @@ pub(crate) fn resolve_ty_and_res_fully_qualified_call(
let trait_missing_method =
matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
- assert_ne!(item_name.name, kw::Empty);
self.report_method_error(
hir_id,
ty.normalized,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 81eb851..da0e8e3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -616,7 +616,7 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
if let Some((DefKind::AssocFn, def_id)) =
self.typeck_results.borrow().type_dependent_def(call_expr.hir_id)
&& let Some(assoc) = tcx.opt_associated_item(def_id)
- && assoc.fn_has_self_parameter
+ && assoc.is_method()
{
Some(*receiver)
} else {
@@ -642,8 +642,7 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
TraitsInScope,
|mut ctxt| ctxt.probe_for_similar_candidate(),
)
- && let ty::AssocKind::Fn = assoc.kind
- && assoc.fn_has_self_parameter
+ && assoc.is_method()
{
let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args);
@@ -684,10 +683,11 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
.all(|(expected, found)| self.may_coerce(*expected, *found))
&& fn_sig.inputs()[1..].len() == input_types.len()
{
+ let assoc_name = assoc.name();
err.span_suggestion_verbose(
call_name.span,
- format!("you might have meant to use `{}`", assoc.name),
- assoc.name,
+ format!("you might have meant to use `{}`", assoc_name),
+ assoc_name,
Applicability::MaybeIncorrect,
);
return;
@@ -707,7 +707,7 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
tcx.def_span(assoc.def_id),
format!(
"there's is a method with similar name `{}`, but the arguments don't match",
- assoc.name,
+ assoc.name(),
),
);
return;
@@ -719,7 +719,7 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
format!(
"there's is a method with similar name `{}`, but their argument count \
doesn't match",
- assoc.name,
+ assoc.name(),
),
);
return;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index e14f152..934820e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -314,7 +314,7 @@ fn lower_assoc_shared(
item_def_id: DefId,
item_segment: &rustc_hir::PathSegment<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
- _kind: ty::AssocKind,
+ _assoc_tag: ty::AssocTag,
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
let trait_ref = self.instantiate_binder_with_fresh_vars(
span,
@@ -488,7 +488,7 @@ fn parse_never_type_options_attr(
item.span(),
format!(
"unknown or duplicate never type option: `{}` (supported: `fallback`, `diverging_block_default`)",
- item.name_or_empty()
+ item.name().unwrap()
),
);
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 912098c..91eb198 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -381,9 +381,10 @@ pub(crate) fn suggest_deref_ref_or_into(
let mut suggestions = methods
.iter()
.filter_map(|conversion_method| {
+ let conversion_method_name = conversion_method.name();
let receiver_method_ident = expr.method_ident();
if let Some(method_ident) = receiver_method_ident
- && method_ident.name == conversion_method.name
+ && method_ident.name == conversion_method_name
{
return None; // do not suggest code that is already there (#53348)
}
@@ -391,20 +392,20 @@ pub(crate) fn suggest_deref_ref_or_into(
let method_call_list = [sym::to_vec, sym::to_string];
let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = expr.kind
&& receiver_method.ident.name == sym::clone
- && method_call_list.contains(&conversion_method.name)
+ && method_call_list.contains(&conversion_method_name)
// If receiver is `.clone()` and found type has one of those methods,
// we guess that the user wants to convert from a slice type (`&[]` or `&str`)
// to an owned type (`Vec` or `String`). These conversions clone internally,
// so we remove the user's `clone` call.
{
- vec![(receiver_method.ident.span, conversion_method.name.to_string())]
+ vec![(receiver_method.ident.span, conversion_method_name.to_string())]
} else if expr.precedence() < ExprPrecedence::Unambiguous {
vec![
(expr.span.shrink_to_lo(), "(".to_string()),
- (expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)),
+ (expr.span.shrink_to_hi(), format!(").{}()", conversion_method_name)),
]
} else {
- vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
+ vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method_name))]
};
let struct_pat_shorthand_field =
self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr);
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 1d86ff1..af8ec37 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -1,7 +1,6 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
@@ -266,7 +265,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer(()), span, .. }) = node.ty()
{
if let Some(item) = tcx.opt_associated_item(def_id.into())
- && let ty::AssocKind::Const = item.kind
+ && let ty::AssocKind::Const { .. } = item.kind
&& let ty::AssocItemContainer::Impl = item.container
&& let Some(trait_item_def_id) = item.trait_item_def_id
{
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index ddfd27c..1b67e23 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -379,7 +379,7 @@ pub(super) fn lookup_method_in_trait(
};
let def_id = method_item.def_id;
- if method_item.kind != ty::AssocKind::Fn {
+ if !method_item.is_fn() {
span_bug!(tcx.def_span(def_id), "expected `{m_name}` to be an associated function");
}
@@ -529,7 +529,7 @@ pub(crate) fn resolve_fully_qualified_call(
}
}
- let def_kind = pick.item.kind.as_def_kind();
+ let def_kind = pick.item.as_def_kind();
tcx.check_stability(pick.item.def_id, Some(expr_id), span, Some(method_name.span));
Ok((def_kind, pick.item.def_id))
}
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 0a01ec8..1d3a081 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -992,7 +992,7 @@ fn assemble_extension_candidates_for_all_traits(&mut self) {
fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool {
match method.kind {
- ty::AssocKind::Fn => self.probe(|_| {
+ ty::AssocKind::Fn { .. } => self.probe(|_| {
let args = self.fresh_args_for_item(self.span, method.def_id);
let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args);
let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty);
@@ -1583,7 +1583,7 @@ fn pick_method(
},
None,
) {
- self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
+ self.private_candidate.set(Some((pick.item.as_def_kind(), pick.item.def_id)));
}
}
None
@@ -1671,16 +1671,7 @@ impl<'tcx> Pick<'tcx> {
/// Do not use for type checking.
pub(crate) fn differs_from(&self, other: &Self) -> bool {
let Self {
- item:
- AssocItem {
- def_id,
- name: _,
- kind: _,
- container: _,
- trait_item_def_id: _,
- fn_has_self_parameter: _,
- opt_rpitit_info: _,
- },
+ item: AssocItem { def_id, kind: _, container: _, trait_item_def_id: _ },
kind: _,
import_ids: _,
autoderefs: _,
@@ -1703,7 +1694,7 @@ pub(crate) fn maybe_emit_unstable_name_collision_hint(
if self.unstable_candidates.is_empty() {
return;
}
- let def_kind = self.item.kind.as_def_kind();
+ let def_kind = self.item.as_def_kind();
tcx.node_span_lint(lint::builtin::UNSTABLE_NAME_COLLISIONS, scope_expr_id, span, |lint| {
lint.primary_message(format!(
"{} {} with this name may be added to the standard library in the future",
@@ -1712,7 +1703,7 @@ pub(crate) fn maybe_emit_unstable_name_collision_hint(
));
match (self.item.kind, self.item.container) {
- (ty::AssocKind::Fn, _) => {
+ (ty::AssocKind::Fn { .. }, _) => {
// FIXME: This should be a `span_suggestion` instead of `help`
// However `self.span` only
// highlights the method name, so we can't use it. Also consider reusing
@@ -1723,17 +1714,12 @@ pub(crate) fn maybe_emit_unstable_name_collision_hint(
tcx.def_path_str(self.item.def_id),
));
}
- (ty::AssocKind::Const, ty::AssocItemContainer::Trait) => {
+ (ty::AssocKind::Const { name }, ty::AssocItemContainer::Trait) => {
let def_id = self.item.container_id(tcx);
lint.span_suggestion(
span,
"use the fully qualified path to the associated const",
- format!(
- "<{} as {}>::{}",
- self.self_ty,
- tcx.def_path_str(def_id),
- self.item.name
- ),
+ format!("<{} as {}>::{}", self.self_ty, tcx.def_path_str(def_id), name),
Applicability::MachineApplicable,
);
}
@@ -2222,7 +2208,7 @@ pub(crate) fn probe_for_similar_candidate(
let best_name = {
let names = applicable_close_candidates
.iter()
- .map(|cand| cand.name)
+ .map(|cand| cand.name())
.collect::<Vec<Symbol>>();
find_best_match_for_name_with_substrings(
&names,
@@ -2234,10 +2220,12 @@ pub(crate) fn probe_for_similar_candidate(
applicable_close_candidates
.iter()
.find(|cand| self.matches_by_doc_alias(cand.def_id))
- .map(|cand| cand.name)
+ .map(|cand| cand.name())
});
Ok(best_name.and_then(|best_name| {
- applicable_close_candidates.into_iter().find(|method| method.name == best_name)
+ applicable_close_candidates
+ .into_iter()
+ .find(|method| method.name() == best_name)
}))
}
})
@@ -2252,10 +2240,10 @@ fn has_applicable_self(&self, item: &ty::AssocItem) -> bool {
// In Path mode (i.e., resolving a value like `T::next`), consider any
// associated value (i.e., methods, constants) but not types.
match self.mode {
- Mode::MethodCall => item.fn_has_self_parameter,
+ Mode::MethodCall => item.is_method(),
Mode::Path => match item.kind {
- ty::AssocKind::Type => false,
- ty::AssocKind::Fn | ty::AssocKind::Const => true,
+ ty::AssocKind::Type { .. } => false,
+ ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => true,
},
}
// FIXME -- check for types that deref to `Self`,
@@ -2277,7 +2265,7 @@ fn xform_self_ty(
impl_ty: Ty<'tcx>,
args: GenericArgsRef<'tcx>,
) -> (Ty<'tcx>, Option<Ty<'tcx>>) {
- if item.kind == ty::AssocKind::Fn && self.mode == Mode::MethodCall {
+ if item.is_fn() && self.mode == Mode::MethodCall {
let sig = self.xform_method_sig(item.def_id, args);
(sig.inputs()[0], Some(sig.output()))
} else {
@@ -2328,8 +2316,8 @@ fn xform_method_sig(&self, method: DefId, args: GenericArgsRef<'tcx>) -> ty::FnS
/// Determine if the given associated item type is relevant in the current context.
fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool {
match (self.mode, kind) {
- (Mode::MethodCall, ty::AssocKind::Fn) => true,
- (Mode::Path, ty::AssocKind::Const | ty::AssocKind::Fn) => true,
+ (Mode::MethodCall, ty::AssocKind::Fn { .. }) => true,
+ (Mode::Path, ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. }) => true,
_ => false,
}
}
@@ -2346,8 +2334,9 @@ fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
let attrs = self.fcx.tcx.hir_attrs(hir_id);
for attr in attrs {
- if sym::doc == attr.name_or_empty() {
- } else if sym::rustc_confusables == attr.name_or_empty() {
+ if attr.has_name(sym::doc) {
+ // do nothing
+ } else if attr.has_name(sym::rustc_confusables) {
let Some(confusables) = attr.meta_item_list() else {
continue;
};
@@ -2367,7 +2356,7 @@ fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
continue;
};
for v in values {
- if v.name_or_empty() != sym::alias {
+ if !v.has_name(sym::alias) {
continue;
}
if let Some(nested) = v.meta_item_list() {
@@ -2411,7 +2400,7 @@ fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
}
match edit_distance_with_substrings(
name.as_str(),
- x.name.as_str(),
+ x.name().as_str(),
max_dist,
) {
Some(d) => d > 0,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 68f13d6..6a9fd7c 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -713,7 +713,7 @@ fn report_no_match_method_error(
&& let Some(candidate) = tcx.associated_items(impl_def_id).find_by_ident_and_kind(
self.tcx,
item_ident,
- ty::AssocKind::Type,
+ ty::AssocTag::Type,
impl_def_id,
)
&& let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def()
@@ -1442,7 +1442,7 @@ fn report_no_match_method_error(
if let Some(assoc) = self.associated_value(*def_id, item_ident) {
// Check for both mode is the same so we avoid suggesting
// incorrect associated item.
- match (mode, assoc.fn_has_self_parameter, source) {
+ match (mode, assoc.is_method(), source) {
(Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
// We check that the suggest type is actually
// different from the received one
@@ -1722,7 +1722,7 @@ fn report_no_match_method_error(
// that had unsatisfied trait bounds
if unsatisfied_predicates.is_empty()
// ...or if we already suggested that name because of `rustc_confusable` annotation.
- && Some(similar_candidate.name) != confusable_suggested
+ && Some(similar_candidate.name()) != confusable_suggested
{
self.find_likely_intended_associated_item(
&mut err,
@@ -1819,12 +1819,13 @@ fn find_likely_intended_associated_item(
mode: Mode,
) {
let tcx = self.tcx;
- let def_kind = similar_candidate.kind.as_def_kind();
+ let def_kind = similar_candidate.as_def_kind();
let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id);
+ let similar_candidate_name = similar_candidate.name();
let msg = format!(
"there is {an} {} `{}` with a similar name",
self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
- similar_candidate.name,
+ similar_candidate_name,
);
// Methods are defined within the context of a struct and their first parameter
// is always `self`, which represents the instance of the struct the method is
@@ -1834,7 +1835,7 @@ fn find_likely_intended_associated_item(
let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id);
let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args);
let fn_sig = self.instantiate_binder_with_fresh_vars(span, infer::FnCall, fn_sig);
- if similar_candidate.fn_has_self_parameter {
+ if similar_candidate.is_method() {
if let Some(args) = args
&& fn_sig.inputs()[1..].len() == args.len()
{
@@ -1843,7 +1844,7 @@ fn find_likely_intended_associated_item(
err.span_suggestion_verbose(
span,
msg,
- similar_candidate.name,
+ similar_candidate_name,
Applicability::MaybeIncorrect,
);
} else {
@@ -1865,7 +1866,7 @@ fn find_likely_intended_associated_item(
err.span_suggestion_verbose(
span,
msg,
- similar_candidate.name,
+ similar_candidate_name,
Applicability::MaybeIncorrect,
);
} else {
@@ -1878,7 +1879,7 @@ fn find_likely_intended_associated_item(
err.span_suggestion_verbose(
span,
msg,
- similar_candidate.name,
+ similar_candidate_name,
Applicability::MaybeIncorrect,
);
} else {
@@ -1902,7 +1903,7 @@ pub(crate) fn confusable_method_name(
{
if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::Confusables{symbols, ..} => symbols)
&& candidates.contains(&item_name.name)
- && let ty::AssocKind::Fn = inherent_method.kind
+ && inherent_method.is_fn()
{
let args =
ty::GenericArgs::identity_for_item(self.tcx, inherent_method.def_id)
@@ -1918,6 +1919,7 @@ pub(crate) fn confusable_method_name(
infer::FnCall,
fn_sig,
);
+ let name = inherent_method.name();
if let Some(ref args) = call_args
&& fn_sig.inputs()[1..]
.iter()
@@ -1927,20 +1929,17 @@ pub(crate) fn confusable_method_name(
{
err.span_suggestion_verbose(
item_name.span,
- format!("you might have meant to use `{}`", inherent_method.name),
- inherent_method.name,
+ format!("you might have meant to use `{}`", name),
+ name,
Applicability::MaybeIncorrect,
);
- return Some(inherent_method.name);
+ return Some(name);
} else if let None = call_args {
err.span_note(
self.tcx.def_span(inherent_method.def_id),
- format!(
- "you might have meant to use method `{}`",
- inherent_method.name,
- ),
+ format!("you might have meant to use method `{}`", name),
);
- return Some(inherent_method.name);
+ return Some(name);
}
}
}
@@ -2116,8 +2115,7 @@ fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>, expr_id: hir::H
// Only assoc fn with no receivers and only if
// they are resolvable
.filter(|item| {
- matches!(item.kind, ty::AssocKind::Fn)
- && !item.fn_has_self_parameter
+ matches!(item.kind, ty::AssocKind::Fn { has_self: false, .. })
&& self
.probe_for_name(
Mode::Path,
@@ -2261,7 +2259,7 @@ fn suggest_associated_call_syntax(
};
let assoc = self.associated_value(assoc_did, item_name)?;
- if assoc.kind != ty::AssocKind::Fn {
+ if !assoc.is_fn() {
return None;
}
@@ -3208,7 +3206,7 @@ fn note_derefed_ty_has_method(
// If this method receives `&self`, then the provided
// argument _should_ coerce, so it's valid to suggest
// just changing the path.
- && pick.item.fn_has_self_parameter
+ && pick.item.is_method()
&& let Some(self_ty) =
self.tcx.fn_sig(pick.item.def_id).instantiate_identity().inputs().skip_binder().get(0)
&& self_ty.is_ref()
@@ -3560,7 +3558,7 @@ fn suggest_traits_to_import(
|| (("Pin::new" == *pre)
&& ((sym::as_ref == item_name.name) || !unpin))
|| inputs_len.is_some_and(|inputs_len| {
- pick.item.kind == ty::AssocKind::Fn
+ pick.item.is_fn()
&& self
.tcx
.fn_sig(pick.item.def_id)
@@ -3618,7 +3616,7 @@ fn suggest_traits_to_import(
&& pick.autoderefs == 0
// Check that the method of the same name that was found on the new `Pin<T>`
// receiver has the same number of arguments that appear in the user's code.
- && inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len)
+ && inputs_len.is_some_and(|inputs_len| pick.item.is_fn() && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len)
{
let indent = self
.tcx
@@ -3756,7 +3754,7 @@ fn suggest_traits_to_import(
&& self
.associated_value(info.def_id, item_name)
.filter(|item| {
- if let ty::AssocKind::Fn = item.kind {
+ if item.is_fn() {
let id = item
.def_id
.as_local()
@@ -4279,17 +4277,17 @@ fn print_disambiguation_help<'tcx>(
item: ty::AssocItem,
) -> Option<String> {
let trait_impl_type = trait_ref.self_ty().peel_refs();
- let trait_ref = if item.fn_has_self_parameter {
+ let trait_ref = if item.is_method() {
trait_ref.print_only_trait_name().to_string()
} else {
format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name())
};
Some(
- if matches!(item.kind, ty::AssocKind::Fn)
+ if item.is_fn()
&& let SelfSource::MethodCall(receiver) = source
&& let Some(args) = args
{
- let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
+ let def_kind_descr = tcx.def_kind_descr(item.as_def_kind(), item.def_id);
let item_name = item.ident(tcx);
let first_input =
tcx.fn_sig(item.def_id).instantiate_identity().skip_binder().inputs().get(0);
@@ -4304,7 +4302,7 @@ fn print_disambiguation_help<'tcx>(
let args = if let Some(first_arg_type) = first_arg_type
&& (first_arg_type == tcx.types.self_param
|| first_arg_type == trait_impl_type
- || item.fn_has_self_parameter)
+ || item.is_method())
{
Some(receiver)
} else {
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 93f77b8..0e42a84 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -372,7 +372,7 @@ fn check_overloaded_binop(
.associated_item_def_ids(def_id)
.iter()
.find(|item_def_id| {
- self.tcx.associated_item(*item_def_id).name == sym::Output
+ self.tcx.associated_item(*item_def_id).name() == sym::Output
})
.cloned()
});
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index fbc783c..e5e4fc7 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -9,11 +9,13 @@
Applicability, Diag, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err,
};
use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def_id::DefId;
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{
self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatExpr,
PatExprKind, PatKind, expr_needs_parens,
};
+use rustc_hir_analysis::autoderef::report_autoderef_recursion_limit_error;
use rustc_infer::infer;
use rustc_middle::traits::PatternOriginExpr;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@@ -29,11 +31,12 @@
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
use tracing::{debug, instrument, trace};
use ty::VariantDef;
+use ty::adjustment::{PatAdjust, PatAdjustment};
use super::report_unexpected_variant_res;
use crate::expectation::Expectation;
use crate::gather_locals::DeclOrigin;
-use crate::{FnCtxt, LoweredTy, errors};
+use crate::{FnCtxt, errors};
const CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\
This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
@@ -161,12 +164,35 @@ fn demand_eqtype_pat(
/// Mode for adjusting the expected type and binding mode.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum AdjustMode {
- /// Peel off all immediate reference types.
- Peel,
+ /// Peel off all immediate reference types. If the `deref_patterns` feature is enabled, this
+ /// also peels smart pointer ADTs.
+ Peel { kind: PeelKind },
/// Pass on the input binding mode and expected type.
Pass,
}
+/// Restrictions on what types to peel when adjusting the expected type and binding mode.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum PeelKind {
+ /// Only peel reference types. This is used for explicit `deref!(_)` patterns, which dereference
+ /// any number of `&`/`&mut` references, plus a single smart pointer.
+ ExplicitDerefPat,
+ /// Implicitly peel any number of references, and if `deref_patterns` is enabled, smart pointer
+ /// ADTs. In order to peel only as much as necessary for the pattern to match, the `until_adt`
+ /// field contains the ADT def that the pattern is a constructor for, if applicable, so that we
+ /// don't peel it. See [`ResolvedPat`] for more information.
+ Implicit { until_adt: Option<DefId> },
+}
+
+impl AdjustMode {
+ const fn peel_until_adt(opt_adt_def: Option<DefId>) -> AdjustMode {
+ AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: opt_adt_def } }
+ }
+ const fn peel_all() -> AdjustMode {
+ AdjustMode::peel_until_adt(None)
+ }
+}
+
/// `ref mut` bindings (explicit or match-ergonomics) are not allowed behind an `&` reference.
/// Normally, the borrow checker enforces this, but for (currently experimental) match ergonomics,
/// we track this when typing patterns for two purposes:
@@ -242,6 +268,47 @@ enum InheritedRefMatchRule {
},
}
+/// When checking patterns containing paths, we need to know the path's resolution to determine
+/// whether to apply match ergonomics and implicitly dereference the scrutinee. For instance, when
+/// the `deref_patterns` feature is enabled and we're matching against a scrutinee of type
+/// `Cow<'a, Option<u8>>`, we insert an implicit dereference to allow the pattern `Some(_)` to type,
+/// but we must not dereference it when checking the pattern `Cow::Borrowed(_)`.
+///
+/// `ResolvedPat` contains the information from resolution needed to determine match ergonomics
+/// adjustments, and to finish checking the pattern once we know its adjusted type.
+#[derive(Clone, Copy, Debug)]
+struct ResolvedPat<'tcx> {
+ /// The type of the pattern, to be checked against the type of the scrutinee after peeling. This
+ /// is also used to avoid peeling the scrutinee's constructors (see the `Cow` example above).
+ ty: Ty<'tcx>,
+ kind: ResolvedPatKind<'tcx>,
+}
+
+#[derive(Clone, Copy, Debug)]
+enum ResolvedPatKind<'tcx> {
+ Path { res: Res, pat_res: Res, segments: &'tcx [hir::PathSegment<'tcx>] },
+ Struct { variant: &'tcx VariantDef },
+ TupleStruct { res: Res, variant: &'tcx VariantDef },
+}
+
+impl<'tcx> ResolvedPat<'tcx> {
+ fn adjust_mode(&self) -> AdjustMode {
+ if let ResolvedPatKind::Path { res, .. } = self.kind
+ && matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _))
+ {
+ // These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
+ // Peeling the reference types too early will cause type checking failures.
+ // Although it would be possible to *also* peel the types of the constants too.
+ AdjustMode::Pass
+ } else {
+ // The remaining possible resolutions for path, struct, and tuple struct patterns are
+ // ADT constructors. As such, we may peel references freely, but we must not peel the
+ // ADT itself from the scrutinee if it's a smart pointer.
+ AdjustMode::peel_until_adt(self.ty.ty_adt_def().map(|adt| adt.did()))
+ }
+ }
+}
+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Experimental pattern feature: after matching against a shared reference, do we limit the
/// default binding mode in subpatterns to be `ref` when it would otherwise be `ref mut`?
@@ -318,16 +385,35 @@ pub(crate) fn check_pat_top(
/// Conversely, inside this module, `check_pat_top` should never be used.
#[instrument(level = "debug", skip(self, pat_info))]
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
+ // For patterns containing paths, we need the path's resolution to determine whether to
+ // implicitly dereference the scrutinee before matching.
let opt_path_res = match pat.kind {
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
- Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
+ Some(self.resolve_pat_path(*hir_id, *span, qpath))
}
+ PatKind::Struct(ref qpath, ..) => Some(self.resolve_pat_struct(pat, qpath)),
+ PatKind::TupleStruct(ref qpath, ..) => Some(self.resolve_pat_tuple_struct(pat, qpath)),
_ => None,
};
- let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res));
+ let adjust_mode = self.calc_adjust_mode(pat, opt_path_res);
let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info);
self.write_ty(pat.hir_id, ty);
+ // If we implicitly inserted overloaded dereferences before matching, check the pattern to
+ // see if the dereferenced types need `DerefMut` bounds.
+ if let Some(derefed_tys) = self.typeck_results.borrow().pat_adjustments().get(pat.hir_id)
+ && derefed_tys.iter().any(|adjust| adjust.kind == PatAdjust::OverloadedDeref)
+ {
+ self.register_deref_mut_bounds_if_needed(
+ pat.span,
+ pat,
+ derefed_tys.iter().filter_map(|adjust| match adjust.kind {
+ PatAdjust::OverloadedDeref => Some(adjust.source),
+ PatAdjust::BuiltinDeref => None,
+ }),
+ );
+ }
+
// (note_1): In most of the cases where (note_1) is referenced
// (literals and constants being the exception), we relate types
// using strict equality, even though subtyping would be sufficient.
@@ -375,7 +461,7 @@ fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<
fn check_pat_inner(
&self,
pat: &'tcx Pat<'tcx>,
- opt_path_res: Option<(Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>])>,
+ opt_path_res: Option<Result<ResolvedPat<'tcx>, ErrorGuaranteed>>,
adjust_mode: AdjustMode,
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx>,
@@ -389,7 +475,7 @@ fn check_pat_inner(
}
// Resolve type if needed.
- let expected = if let AdjustMode::Peel = adjust_mode
+ let expected = if let AdjustMode::Peel { .. } = adjust_mode
&& pat.default_binding_modes
{
self.try_structurally_resolve_type(pat.span, expected)
@@ -402,7 +488,7 @@ fn check_pat_inner(
match pat.kind {
// Peel off a `&` or `&mut` from the scrutinee type. See the examples in
// `tests/ui/rfcs/rfc-2005-default-binding-mode`.
- _ if let AdjustMode::Peel = adjust_mode
+ _ if let AdjustMode::Peel { .. } = adjust_mode
&& pat.default_binding_modes
&& let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() =>
{
@@ -415,7 +501,7 @@ fn check_pat_inner(
.pat_adjustments_mut()
.entry(pat.hir_id)
.or_default()
- .push(expected);
+ .push(PatAdjustment { kind: PatAdjust::BuiltinDeref, source: expected });
let mut binding_mode = ByRef::Yes(match pat_info.binding_mode {
// If default binding mode is by value, make it `ref` or `ref mut`
@@ -442,19 +528,68 @@ fn check_pat_inner(
// Recurse with the new expected type.
self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info)
}
+ // If `deref_patterns` is enabled, peel a smart pointer from the scrutinee type. See the
+ // examples in `tests/ui/pattern/deref_patterns/`.
+ _ if self.tcx.features().deref_patterns()
+ && let AdjustMode::Peel { kind: PeelKind::Implicit { until_adt } } = adjust_mode
+ && pat.default_binding_modes
+ // For simplicity, only apply overloaded derefs if `expected` is a known ADT.
+ // FIXME(deref_patterns): we'll get better diagnostics for users trying to
+ // implicitly deref generics if we allow them here, but primitives, tuples, and
+ // inference vars definitely should be stopped. Figure out what makes most sense.
+ && let ty::Adt(scrutinee_adt, _) = *expected.kind()
+ // Don't peel if the pattern type already matches the scrutinee. E.g., stop here if
+ // matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern.
+ && until_adt != Some(scrutinee_adt.did())
+ // At this point, the pattern isn't able to match `expected` without peeling. Check
+ // that it implements `Deref` before assuming it's a smart pointer, to get a normal
+ // type error instead of a missing impl error if not. This only checks for `Deref`,
+ // not `DerefPure`: we require that too, but we want a trait error if it's missing.
+ && let Some(deref_trait) = self.tcx.lang_items().deref_trait()
+ && self
+ .type_implements_trait(deref_trait, [expected], self.param_env)
+ .may_apply() =>
+ {
+ debug!("scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref");
+ // The scrutinee is a smart pointer; implicitly dereference it. This adds a
+ // requirement that `expected: DerefPure`.
+ let mut inner_ty = self.deref_pat_target(pat.span, expected);
+ // Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any
+ // `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`.
+
+ let mut typeck_results = self.typeck_results.borrow_mut();
+ let mut pat_adjustments_table = typeck_results.pat_adjustments_mut();
+ let pat_adjustments = pat_adjustments_table.entry(pat.hir_id).or_default();
+ // We may reach the recursion limit if a user matches on a type `T` satisfying
+ // `T: Deref<Target = T>`; error gracefully in this case.
+ // FIXME(deref_patterns): If `deref_patterns` stabilizes, it may make sense to move
+ // this check out of this branch. Alternatively, this loop could be implemented with
+ // autoderef and this check removed. For now though, don't break code compiling on
+ // stable with lots of `&`s and a low recursion limit, if anyone's done that.
+ if self.tcx.recursion_limit().value_within_limit(pat_adjustments.len()) {
+ // Preserve the smart pointer type for THIR lowering and closure upvar analysis.
+ pat_adjustments
+ .push(PatAdjustment { kind: PatAdjust::OverloadedDeref, source: expected });
+ } else {
+ let guar = report_autoderef_recursion_limit_error(self.tcx, pat.span, expected);
+ inner_ty = Ty::new_error(self.tcx, guar);
+ }
+ drop(typeck_results);
+
+ // Recurse, using the old pat info to keep `current_depth` to its old value.
+ // Peeling smart pointers does not update the default binding mode.
+ self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, old_pat_info)
+ }
PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected,
// We allow any type here; we ensure that the type is uninhabited during match checking.
PatKind::Never => expected,
- PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
- let ty = self.check_pat_path(
- *hir_id,
- pat.hir_id,
- *span,
- qpath,
- opt_path_res.unwrap(),
- expected,
- &pat_info.top_info,
- );
+ PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), hir_id, .. }) => {
+ let ty = match opt_path_res.unwrap() {
+ Ok(ref pr) => {
+ self.check_pat_path(pat.hir_id, pat.span, pr, expected, &pat_info.top_info)
+ }
+ Err(guar) => Ty::new_error(self.tcx, guar),
+ };
self.write_ty(*hir_id, ty);
ty
}
@@ -465,12 +600,32 @@ fn check_pat_inner(
PatKind::Binding(ba, var_id, ident, sub) => {
self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
}
- PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
- self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
- }
- PatKind::Struct(ref qpath, fields, has_rest_pat) => {
- self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
- }
+ PatKind::TupleStruct(ref qpath, subpats, ddpos) => match opt_path_res.unwrap() {
+ Ok(ResolvedPat { ty, kind: ResolvedPatKind::TupleStruct { res, variant } }) => self
+ .check_pat_tuple_struct(
+ pat, qpath, subpats, ddpos, res, ty, variant, expected, pat_info,
+ ),
+ Err(guar) => {
+ let ty_err = Ty::new_error(self.tcx, guar);
+ for subpat in subpats {
+ self.check_pat(subpat, ty_err, pat_info);
+ }
+ ty_err
+ }
+ Ok(pr) => span_bug!(pat.span, "tuple struct pattern resolved to {pr:?}"),
+ },
+ PatKind::Struct(_, fields, has_rest_pat) => match opt_path_res.unwrap() {
+ Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self
+ .check_pat_struct(pat, fields, has_rest_pat, ty, variant, expected, pat_info),
+ Err(guar) => {
+ let ty_err = Ty::new_error(self.tcx, guar);
+ for field in fields {
+ self.check_pat(field.pat, ty_err, pat_info);
+ }
+ ty_err
+ }
+ Ok(pr) => span_bug!(pat.span, "struct pattern resolved to {pr:?}"),
+ },
PatKind::Guard(pat, cond) => {
self.check_pat(pat, expected, pat_info);
self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {});
@@ -496,31 +651,32 @@ fn check_pat_inner(
/// How should the binding mode and expected type be adjusted?
///
- /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
- fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> AdjustMode {
+ /// When the pattern contains a path, `opt_path_res` must be `Some(path_res)`.
+ fn calc_adjust_mode(
+ &self,
+ pat: &'tcx Pat<'tcx>,
+ opt_path_res: Option<Result<ResolvedPat<'tcx>, ErrorGuaranteed>>,
+ ) -> AdjustMode {
match &pat.kind {
// Type checking these product-like types successfully always require
// that the expected type be of those types and not reference types.
+ PatKind::Tuple(..)
+ | PatKind::Range(..)
+ | PatKind::Slice(..) => AdjustMode::peel_all(),
+ // When checking an explicit deref pattern, only peel reference types.
+ // FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box
+ // patterns may want `PeelKind::Implicit`, stopping on encountering a box.
+ | PatKind::Box(_)
+ | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat },
+ // A never pattern behaves somewhat like a literal or unit variant.
+ PatKind::Never => AdjustMode::peel_all(),
+ // For patterns with paths, how we peel the scrutinee depends on the path's resolution.
PatKind::Struct(..)
| PatKind::TupleStruct(..)
- | PatKind::Tuple(..)
- | PatKind::Box(_)
- | PatKind::Deref(_)
- | PatKind::Range(..)
- | PatKind::Slice(..) => AdjustMode::Peel,
- // A never pattern behaves somewhat like a literal or unit variant.
- PatKind::Never => AdjustMode::Peel,
- PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => match opt_path_res.unwrap() {
- // These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
- // Peeling the reference types too early will cause type checking failures.
- // Although it would be possible to *also* peel the types of the constants too.
- Res::Def(DefKind::Const | DefKind::AssocConst, _) => AdjustMode::Pass,
- // In the `ValueNS`, we have `SelfCtor(..) | Ctor(_, Const), _)` remaining which
- // could successfully compile. The former being `Self` requires a unit struct.
- // In either case, and unlike constants, the pattern itself cannot be
- // a reference type wherefore peeling doesn't give up any expressiveness.
- _ => AdjustMode::Peel,
- },
+ | PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => {
+ // If there was an error resolving the path, default to peeling everything.
+ opt_path_res.unwrap().map_or(AdjustMode::peel_all(), |pr| pr.adjust_mode())
+ }
// String and byte-string literals result in types `&str` and `&[u8]` respectively.
// All other literals result in non-reference types.
@@ -529,7 +685,17 @@ fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> A
// Call `resolve_vars_if_possible` here for inline const blocks.
PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
ty::Ref(..) => AdjustMode::Pass,
- _ => AdjustMode::Peel,
+ _ => {
+ // Path patterns have already been handled, and inline const blocks currently
+ // aren't possible to write, so any handling for them would be untested.
+ if cfg!(debug_assertions)
+ && self.tcx.features().deref_patterns()
+ && !matches!(lt.kind, PatExprKind::Lit { .. })
+ {
+ span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind);
+ }
+ AdjustMode::peel_all()
+ }
},
// Ref patterns are complicated, we handle them in `check_pat_ref`.
@@ -1112,27 +1278,26 @@ fn check_dereferenceable(
Ok(())
}
- fn check_pat_struct(
+ fn resolve_pat_struct(
&self,
pat: &'tcx Pat<'tcx>,
qpath: &hir::QPath<'tcx>,
+ ) -> Result<ResolvedPat<'tcx>, ErrorGuaranteed> {
+ // Resolve the path and check the definition for errors.
+ let (variant, pat_ty) = self.check_struct_path(qpath, pat.hir_id)?;
+ Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::Struct { variant } })
+ }
+
+ fn check_pat_struct(
+ &self,
+ pat: &'tcx Pat<'tcx>,
fields: &'tcx [hir::PatField<'tcx>],
has_rest_pat: bool,
+ pat_ty: Ty<'tcx>,
+ variant: &'tcx VariantDef,
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx>,
) -> Ty<'tcx> {
- // Resolve the path and check the definition for errors.
- let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
- Ok(data) => data,
- Err(guar) => {
- let err = Ty::new_error(self.tcx, guar);
- for field in fields {
- self.check_pat(field.pat, err, pat_info);
- }
- return err;
- }
- };
-
// Type-check the path.
let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
@@ -1143,31 +1308,27 @@ fn check_pat_struct(
}
}
- fn check_pat_path(
+ fn resolve_pat_path(
&self,
path_id: HirId,
- pat_id_for_diag: HirId,
span: Span,
- qpath: &hir::QPath<'_>,
- path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
- expected: Ty<'tcx>,
- ti: &TopInfo<'tcx>,
- ) -> Ty<'tcx> {
+ qpath: &'tcx hir::QPath<'_>,
+ ) -> Result<ResolvedPat<'tcx>, ErrorGuaranteed> {
let tcx = self.tcx;
- // We have already resolved the path.
- let (res, opt_ty, segments) = path_resolution;
+ let (res, opt_ty, segments) =
+ self.resolve_ty_and_res_fully_qualified_call(qpath, path_id, span);
match res {
Res::Err => {
let e =
self.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
- return Ty::new_error(tcx, e);
+ return Err(e);
}
Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
let expected = "unit struct, unit variant or constant";
let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected);
- return Ty::new_error(tcx, e);
+ return Err(e);
}
Res::SelfCtor(def_id) => {
if let ty::Adt(adt_def, _) = *tcx.type_of(def_id).skip_binder().kind()
@@ -1185,7 +1346,7 @@ fn check_pat_path(
E0533,
"unit struct",
);
- return Ty::new_error(tcx, e);
+ return Err(e);
}
}
Res::Def(
@@ -1198,15 +1359,26 @@ fn check_pat_path(
_ => bug!("unexpected pattern resolution: {:?}", res),
}
- // Type-check the path.
+ // Find the type of the path pattern, for later checking.
let (pat_ty, pat_res) =
self.instantiate_value_path(segments, opt_ty, res, span, span, path_id);
+ Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::Path { res, pat_res, segments } })
+ }
+
+ fn check_pat_path(
+ &self,
+ pat_id_for_diag: HirId,
+ span: Span,
+ resolved: &ResolvedPat<'tcx>,
+ expected: Ty<'tcx>,
+ ti: &TopInfo<'tcx>,
+ ) -> Ty<'tcx> {
if let Err(err) =
- self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty)
+ self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, resolved.ty)
{
- self.emit_bad_pat_path(err, pat_id_for_diag, span, res, pat_res, pat_ty, segments);
+ self.emit_bad_pat_path(err, pat_id_for_diag, span, resolved);
}
- pat_ty
+ resolved.ty
}
fn maybe_suggest_range_literal(
@@ -1249,11 +1421,12 @@ fn emit_bad_pat_path(
mut e: Diag<'_>,
hir_id: HirId,
pat_span: Span,
- res: Res,
- pat_res: Res,
- pat_ty: Ty<'tcx>,
- segments: &'tcx [hir::PathSegment<'tcx>],
+ resolved_pat: &ResolvedPat<'tcx>,
) {
+ let ResolvedPatKind::Path { res, pat_res, segments } = resolved_pat.kind else {
+ span_bug!(pat_span, "unexpected resolution for path pattern: {resolved_pat:?}");
+ };
+
if let Some(span) = self.tcx.hir_res_span(pat_res) {
e.span_label(span, format!("{} defined here", res.descr()));
if let [hir::PathSegment { ident, .. }] = &*segments {
@@ -1276,7 +1449,7 @@ fn emit_bad_pat_path(
);
}
_ => {
- let (type_def_id, item_def_id) = match pat_ty.kind() {
+ let (type_def_id, item_def_id) = match resolved_pat.ty.kind() {
ty::Adt(def, _) => match res {
Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)),
_ => (None, None),
@@ -1316,12 +1489,61 @@ fn emit_bad_pat_path(
e.emit();
}
+ fn resolve_pat_tuple_struct(
+ &self,
+ pat: &'tcx Pat<'tcx>,
+ qpath: &'tcx hir::QPath<'tcx>,
+ ) -> Result<ResolvedPat<'tcx>, ErrorGuaranteed> {
+ let tcx = self.tcx;
+ let report_unexpected_res = |res: Res| {
+ let expected = "tuple struct or tuple variant";
+ let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
+ Err(e)
+ };
+
+ // Resolve the path and check the definition for errors.
+ let (res, opt_ty, segments) =
+ self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
+ if res == Res::Err {
+ let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
+ self.set_tainted_by_errors(e);
+ return Err(e);
+ }
+
+ // Type-check the path.
+ let (pat_ty, res) =
+ self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
+ if !pat_ty.is_fn() {
+ return report_unexpected_res(res);
+ }
+
+ let variant = match res {
+ Res::Err => {
+ self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted");
+ }
+ Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
+ return report_unexpected_res(res);
+ }
+ Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
+ _ => bug!("unexpected pattern resolution: {:?}", res),
+ };
+
+ // Replace constructor type with constructed type for tuple struct patterns.
+ let pat_ty = pat_ty.fn_sig(tcx).output();
+ let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
+
+ Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::TupleStruct { res, variant } })
+ }
+
fn check_pat_tuple_struct(
&self,
pat: &'tcx Pat<'tcx>,
qpath: &'tcx hir::QPath<'tcx>,
subpats: &'tcx [Pat<'tcx>],
ddpos: hir::DotDotPos,
+ res: Res,
+ pat_ty: Ty<'tcx>,
+ variant: &'tcx VariantDef,
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx>,
) -> Ty<'tcx> {
@@ -1331,46 +1553,6 @@ fn check_pat_tuple_struct(
self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
}
};
- let report_unexpected_res = |res: Res| {
- let expected = "tuple struct or tuple variant";
- let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
- on_error(e);
- e
- };
-
- // Resolve the path and check the definition for errors.
- let (res, opt_ty, segments) =
- self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
- if res == Res::Err {
- let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
- self.set_tainted_by_errors(e);
- on_error(e);
- return Ty::new_error(tcx, e);
- }
-
- // Type-check the path.
- let (pat_ty, res) =
- self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
- if !pat_ty.is_fn() {
- let e = report_unexpected_res(res);
- return Ty::new_error(tcx, e);
- }
-
- let variant = match res {
- Res::Err => {
- self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted");
- }
- Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
- let e = report_unexpected_res(res);
- return Ty::new_error(tcx, e);
- }
- Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
- _ => bug!("unexpected pattern resolution: {:?}", res),
- };
-
- // Replace constructor type with constructed type for tuple struct patterns.
- let pat_ty = pat_ty.fn_sig(tcx).output();
- let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
// Type-check the tuple struct pattern against the expected type.
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
@@ -2255,36 +2437,49 @@ fn check_pat_deref(
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx>,
) -> Ty<'tcx> {
- let tcx = self.tcx;
+ let target_ty = self.deref_pat_target(span, expected);
+ self.check_pat(inner, target_ty, pat_info);
+ self.register_deref_mut_bounds_if_needed(span, inner, [expected]);
+ expected
+ }
+
+ fn deref_pat_target(&self, span: Span, source_ty: Ty<'tcx>) -> Ty<'tcx> {
// Register a `DerefPure` bound, which is required by all `deref!()` pats.
+ let tcx = self.tcx;
self.register_bound(
- expected,
+ source_ty,
tcx.require_lang_item(hir::LangItem::DerefPure, Some(span)),
self.misc(span),
);
- // <expected as Deref>::Target
- let ty = Ty::new_projection(
+ // The expected type for the deref pat's inner pattern is `<expected as Deref>::Target`.
+ let target_ty = Ty::new_projection(
tcx,
tcx.require_lang_item(hir::LangItem::DerefTarget, Some(span)),
- [expected],
+ [source_ty],
);
- let ty = self.normalize(span, ty);
- let ty = self.try_structurally_resolve_type(span, ty);
- self.check_pat(inner, ty, pat_info);
+ let target_ty = self.normalize(span, target_ty);
+ self.try_structurally_resolve_type(span, target_ty)
+ }
- // Check if the pattern has any `ref mut` bindings, which would require
- // `DerefMut` to be emitted in MIR building instead of just `Deref`.
- // We do this *after* checking the inner pattern, since we want to make
- // sure to apply any match-ergonomics adjustments.
+ /// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut`
+ /// bindings, which would require `DerefMut` to be emitted in MIR building instead of just
+ /// `Deref`. We do this *after* checking the inner pattern, since we want to make sure to
+ /// account for `ref mut` binding modes inherited from implicitly dereferencing `&mut` refs.
+ fn register_deref_mut_bounds_if_needed(
+ &self,
+ span: Span,
+ inner: &'tcx Pat<'tcx>,
+ derefed_tys: impl IntoIterator<Item = Ty<'tcx>>,
+ ) {
if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) {
- self.register_bound(
- expected,
- tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)),
- self.misc(span),
- );
+ for mutably_derefed_ty in derefed_tys {
+ self.register_bound(
+ mutably_derefed_ty,
+ self.tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)),
+ self.misc(span),
+ );
+ }
}
-
- expected
}
// Precondition: Pat is Ref(inner)
diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl
index 2a65101..bbc1fab 100644
--- a/compiler/rustc_incremental/messages.ftl
+++ b/compiler/rustc_incremental/messages.ftl
@@ -93,7 +93,7 @@
incremental_undefined_clean_dirty_assertions_item =
clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
-incremental_unknown_item = unknown item `{$name}`
+incremental_unknown_rustc_clean_argument = unknown `rustc_clean` argument
incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs
index b4a2073..dbc72d0 100644
--- a/compiler/rustc_incremental/src/errors.rs
+++ b/compiler/rustc_incremental/src/errors.rs
@@ -107,11 +107,10 @@ pub(crate) struct NotLoaded<'a> {
}
#[derive(Diagnostic)]
-#[diag(incremental_unknown_item)]
-pub(crate) struct UnknownItem {
+#[diag(incremental_unknown_rustc_clean_argument)]
+pub(crate) struct UnknownRustcCleanArgument {
#[primary_span]
pub span: Span,
- pub name: Symbol,
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index dabfb6a..299ee48 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -2,7 +2,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![deny(missing_docs)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index d40a0d5..6416625 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -405,8 +405,7 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
debug!("check_config: searching for cfg {:?}", value);
cfg = Some(config.contains(&(value, None)));
} else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) {
- tcx.dcx()
- .emit_err(errors::UnknownItem { span: attr.span(), name: item.name_or_empty() });
+ tcx.dcx().emit_err(errors::UnknownRustcCleanArgument { span: item.span() });
}
}
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 76a1ff3..f0d24d2 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -290,7 +290,7 @@ pub(crate) fn prepare_session_directory(sess: &Session, crate_name: Symbol) {
// Try to remove the session directory we just allocated. We don't
// know if there's any garbage in it from the failed copy action.
- if let Err(err) = safe_remove_dir_all(&session_dir) {
+ if let Err(err) = std_fs::remove_dir_all(&session_dir) {
sess.dcx().emit_warn(errors::DeletePartial { path: &session_dir, err });
}
@@ -324,7 +324,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option<Svh>) {
incr_comp_session_dir.display()
);
- if let Err(err) = safe_remove_dir_all(&*incr_comp_session_dir) {
+ if let Err(err) = std_fs::remove_dir_all(&*incr_comp_session_dir) {
sess.dcx().emit_warn(errors::DeleteFull { path: &incr_comp_session_dir, err });
}
@@ -715,7 +715,7 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result<
for directory_name in session_directories {
if !lock_file_to_session_dir.items().any(|(_, dir)| *dir == directory_name) {
let path = crate_directory.join(directory_name);
- if let Err(err) = safe_remove_dir_all(&path) {
+ if let Err(err) = std_fs::remove_dir_all(&path) {
sess.dcx().emit_warn(errors::InvalidGcFailed { path: &path, err });
}
}
@@ -821,7 +821,7 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result<
all_except_most_recent(deletion_candidates).into_items().all(|(path, lock)| {
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
- if let Err(err) = safe_remove_dir_all(&path) {
+ if let Err(err) = std_fs::remove_dir_all(&path) {
sess.dcx().emit_warn(errors::FinalizedGcFailed { path: &path, err });
} else {
delete_session_dir_lock_file(sess, &lock_file_path(&path));
@@ -839,7 +839,7 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result<
fn delete_old(sess: &Session, path: &Path) {
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
- if let Err(err) = safe_remove_dir_all(path) {
+ if let Err(err) = std_fs::remove_dir_all(path) {
sess.dcx().emit_warn(errors::SessionGcFailed { path, err });
} else {
delete_session_dir_lock_file(sess, &lock_file_path(path));
@@ -862,30 +862,8 @@ fn all_except_most_recent(
}
}
-/// Since paths of artifacts within session directories can get quite long, we
-/// need to support deleting files with very long paths. The regular
-/// WinApi functions only support paths up to 260 characters, however. In order
-/// to circumvent this limitation, we canonicalize the path of the directory
-/// before passing it to std::fs::remove_dir_all(). This will convert the path
-/// into the '\\?\' format, which supports much longer paths.
-fn safe_remove_dir_all(p: &Path) -> io::Result<()> {
- let canonicalized = match try_canonicalize(p) {
- Ok(canonicalized) => canonicalized,
- Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()),
- Err(err) => return Err(err),
- };
-
- std_fs::remove_dir_all(canonicalized)
-}
-
fn safe_remove_file(p: &Path) -> io::Result<()> {
- let canonicalized = match try_canonicalize(p) {
- Ok(canonicalized) => canonicalized,
- Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()),
- Err(err) => return Err(err),
- };
-
- match std_fs::remove_file(canonicalized) {
+ match std_fs::remove_file(p) {
Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(()),
result => result,
}
diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs
index 67ac805..d2702bd 100644
--- a/compiler/rustc_index/src/slice.rs
+++ b/compiler/rustc_index/src/slice.rs
@@ -1,6 +1,6 @@
use std::fmt;
use std::marker::PhantomData;
-use std::ops::{Index, IndexMut};
+use std::ops::{Index, IndexMut, RangeBounds};
use std::slice::GetDisjointMutError::*;
use std::slice::{self, SliceIndex};
@@ -105,6 +105,17 @@ pub fn swap(&mut self, a: I, b: I) {
}
#[inline]
+ pub fn copy_within(
+ &mut self,
+ src: impl IntoSliceIdx<I, [T], Output: RangeBounds<usize>>,
+ dest: I,
+ ) where
+ T: Copy,
+ {
+ self.raw.copy_within(src.into_slice_idx(), dest.index());
+ }
+
+ #[inline]
pub fn get<R: IntoSliceIdx<I, [T]>>(
&self,
index: R,
diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs
index f0b58ea..eedbe63 100644
--- a/compiler/rustc_index_macros/src/newtype.rs
+++ b/compiler/rustc_index_macros/src/newtype.rs
@@ -257,6 +257,13 @@ fn add(self, other: usize) -> Self {
}
}
+ impl std::ops::AddAssign<usize> for #name {
+ #[inline]
+ fn add_assign(&mut self, other: usize) {
+ *self = *self + other;
+ }
+ }
+
impl rustc_index::Idx for #name {
#[inline]
fn new(value: usize) -> Self {
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 8366aa6..40e2e65 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -618,9 +618,7 @@ pub fn vars_since_snapshot(
RegionVid::from(value_count)..RegionVid::from(self.storage.unification_table.len());
(
range.clone(),
- (range.start.index()..range.end.index())
- .map(|index| self.storage.var_infos[ty::RegionVid::from(index)].origin)
- .collect(),
+ (range.start..range.end).map(|index| self.storage.var_infos[index].origin).collect(),
)
}
diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
index b5d3c26..39c8c40 100644
--- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
@@ -30,11 +30,12 @@ fn const_vars_since_snapshot<'tcx>(
snapshot_var_len: usize,
) -> (Range<ConstVid>, Vec<ConstVariableOrigin>) {
let range = vars_since_snapshot(table, snapshot_var_len);
+ let range = range.start.vid..range.end.vid;
(
- range.start.vid..range.end.vid,
- (range.start.index()..range.end.index())
- .map(|index| match table.probe_value(ConstVid::from_u32(index)) {
+ range.clone(),
+ range
+ .map(|index| match table.probe_value(index) {
ConstVariableValue::Known { value: _ } => {
ConstVariableOrigin { param_def_id: None, span: rustc_span::DUMMY_SP }
}
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index b537750..6d5ad96 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -12,6 +12,7 @@
use hir::def_id::LocalDefId;
use rustc_hir as hir;
+use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
pub use rustc_middle::traits::*;
@@ -35,9 +36,11 @@
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
/// satisfies the obligation, or else finding a bound that is in
/// scope. The eventual result is usually a `Selection` (defined below).
-#[derive(Clone)]
+#[derive(Clone, TypeFoldable, TypeVisitable)]
pub struct Obligation<'tcx, T> {
/// The reason we have to prove this thing.
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
pub cause: ObligationCause<'tcx>,
/// The environment in which we should prove this thing.
@@ -51,6 +54,8 @@ pub struct Obligation<'tcx, T> {
/// If this goes over a certain threshold, we abort compilation --
/// in such cases, we can not say whether or not the predicate
/// holds for certain. Stupid halting problem; such a drag.
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
pub recursion_depth: usize,
}
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 4335073..03661eb 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -1,8 +1,6 @@
use std::fmt;
-use rustc_middle::ty::{
- self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, try_visit,
-};
+use rustc_middle::ty;
use crate::traits;
use crate::traits::project::Normalized;
@@ -34,31 +32,3 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "MismatchedProjectionTypes({:?})", self.err)
}
}
-
-///////////////////////////////////////////////////////////////////////////
-// TypeFoldable implementations.
-
-impl<'tcx, O: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>>
- for traits::Obligation<'tcx, O>
-{
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(traits::Obligation {
- cause: self.cause,
- recursion_depth: self.recursion_depth,
- predicate: self.predicate.try_fold_with(folder)?,
- param_env: self.param_env.try_fold_with(folder)?,
- })
- }
-}
-
-impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>>
- for traits::Obligation<'tcx, O>
-{
- fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
- try_visit!(self.predicate.visit_with(visitor));
- self.param_env.visit_with(visitor)
- }
-}
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index e367393..ff28dbe 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -5,7 +5,6 @@
[dependencies]
# tidy-alphabetical-start
-rustc-rayon = { version = "0.5.0" }
rustc-rayon-core = { version = "0.5.0" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 7dfad16..fde1872 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -800,6 +800,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
+
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() };
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 75a1b61..d405d04 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -614,6 +614,7 @@ macro_rules! tracked {
tracked!(control_flow_guard, CFGuard::Checks);
tracked!(debug_assertions, Some(true));
tracked!(debuginfo, DebugInfo::Limited);
+ tracked!(dwarf_version, Some(5));
tracked!(embed_bitcode, false);
tracked!(force_frame_pointers, FramePointer::Always);
tracked!(force_unwind_tables, Some(true));
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index f5d4f3f..c3a939f 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -190,7 +190,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
let current_gcx = FromDyn::from(CurrentGcx::new());
let current_gcx2 = current_gcx.clone();
- let builder = rayon::ThreadPoolBuilder::new()
+ let builder = rayon_core::ThreadPoolBuilder::new()
.thread_name(|_| "rustc".to_string())
.acquire_thread_handler(jobserver::acquire_thread)
.release_thread_handler(jobserver::release_thread)
@@ -247,7 +247,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
builder
.build_scoped(
// Initialize each new worker thread when created.
- move |thread: rayon::ThreadBuilder| {
+ move |thread: rayon_core::ThreadBuilder| {
// Register the thread for use with the `WorkerLocal` type.
registry.register();
@@ -256,7 +256,9 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
})
},
// Run `f` on the first thread in the thread pool.
- move |pool: &rayon::ThreadPool| pool.install(|| f(current_gcx.into_inner())),
+ move |pool: &rayon_core::ThreadPool| {
+ pool.install(|| f(current_gcx.into_inner()))
+ },
)
.unwrap()
})
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 782d328..60c183b 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -271,7 +271,7 @@
lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition
.suggestion = convert it to a `use`
-lint_extern_without_abi = extern declarations without an explicit ABI are deprecated
+lint_extern_without_abi = `extern` declarations without an explicit ABI are deprecated
.label = ABI should be specified here
.suggestion = explicitly specify the {$default_abi} ABI
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 16c9e08..3660bb3 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -83,11 +83,6 @@ enum TargetLint {
Ignored,
}
-pub enum FindLintError {
- NotFound,
- Removed,
-}
-
struct LintAlias {
name: &'static str,
/// Whether deprecation warnings should be suppressed for this alias.
@@ -231,13 +226,24 @@ pub fn register_lints(&mut self, lints: &[&'static Lint]) {
}
}
- pub fn register_group_alias(&mut self, lint_name: &'static str, alias: &'static str) {
- self.lint_groups.insert(
+ fn insert_group(&mut self, name: &'static str, group: LintGroup) {
+ let previous = self.lint_groups.insert(name, group);
+ if previous.is_some() {
+ bug!("group {name:?} already exists");
+ }
+ }
+
+ pub fn register_group_alias(&mut self, group_name: &'static str, alias: &'static str) {
+ let Some(LintGroup { lint_ids, .. }) = self.lint_groups.get(group_name) else {
+ bug!("group alias {alias:?} points to unregistered group {group_name:?}")
+ };
+
+ self.insert_group(
alias,
LintGroup {
- lint_ids: vec![],
+ lint_ids: lint_ids.clone(),
is_externally_loaded: false,
- depr: Some(LintAlias { name: lint_name, silent: true }),
+ depr: Some(LintAlias { name: group_name, silent: true }),
},
);
}
@@ -249,24 +255,17 @@ pub fn register_group(
deprecated_name: Option<&'static str>,
to: Vec<LintId>,
) {
- let new = self
- .lint_groups
- .insert(name, LintGroup { lint_ids: to, is_externally_loaded, depr: None })
- .is_none();
if let Some(deprecated) = deprecated_name {
- self.lint_groups.insert(
+ self.insert_group(
deprecated,
LintGroup {
- lint_ids: vec![],
+ lint_ids: to.clone(),
is_externally_loaded,
depr: Some(LintAlias { name, silent: false }),
},
);
}
-
- if !new {
- bug!("duplicate specification of lint group {}", name);
- }
+ self.insert_group(name, LintGroup { lint_ids: to, is_externally_loaded, depr: None });
}
/// This lint should give no warning and have no effect.
@@ -292,23 +291,15 @@ pub fn register_removed(&mut self, name: &str, reason: &str) {
self.by_name.insert(name.into(), Removed(reason.into()));
}
- pub fn find_lints(&self, mut lint_name: &str) -> Result<Vec<LintId>, FindLintError> {
+ pub fn find_lints(&self, lint_name: &str) -> Option<&[LintId]> {
match self.by_name.get(lint_name) {
- Some(&Id(lint_id)) => Ok(vec![lint_id]),
- Some(&Renamed(_, lint_id)) => Ok(vec![lint_id]),
- Some(&Removed(_)) => Err(FindLintError::Removed),
- Some(&Ignored) => Ok(vec![]),
- None => loop {
- return match self.lint_groups.get(lint_name) {
- Some(LintGroup { lint_ids, depr, .. }) => {
- if let Some(LintAlias { name, .. }) = depr {
- lint_name = name;
- continue;
- }
- Ok(lint_ids.clone())
- }
- None => Err(FindLintError::Removed),
- };
+ Some(Id(lint_id)) => Some(slice::from_ref(lint_id)),
+ Some(Renamed(_, lint_id)) => Some(slice::from_ref(lint_id)),
+ Some(Removed(_)) => None,
+ Some(Ignored) => Some(&[]),
+ None => match self.lint_groups.get(lint_name) {
+ Some(LintGroup { lint_ids, .. }) => Some(lint_ids),
+ None => None,
},
}
}
@@ -374,8 +365,12 @@ pub fn check_lint_name(
CheckLintNameResult::MissingTool
};
}
- Some(LintGroup { lint_ids, .. }) => {
- return CheckLintNameResult::Tool(lint_ids, None);
+ Some(LintGroup { lint_ids, depr, .. }) => {
+ return if let &Some(LintAlias { name, silent: false }) = depr {
+ CheckLintNameResult::Tool(lint_ids, Some(name.to_string()))
+ } else {
+ CheckLintNameResult::Tool(lint_ids, None)
+ };
}
},
Some(Id(id)) => return CheckLintNameResult::Tool(slice::from_ref(id), None),
@@ -393,15 +388,11 @@ pub fn check_lint_name(
None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"),
Some(LintGroup { lint_ids, depr, .. }) => {
// Check if the lint group name is deprecated
- if let Some(LintAlias { name, silent }) = depr {
- let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap();
- return if *silent {
- CheckLintNameResult::Ok(lint_ids)
- } else {
- CheckLintNameResult::Tool(lint_ids, Some((*name).to_string()))
- };
+ if let &Some(LintAlias { name, silent: false }) = depr {
+ CheckLintNameResult::Tool(lint_ids, Some(name.to_string()))
+ } else {
+ CheckLintNameResult::Ok(lint_ids)
}
- CheckLintNameResult::Ok(lint_ids)
}
},
Some(Id(id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
@@ -412,7 +403,7 @@ pub fn check_lint_name(
fn no_lint_suggestion(&self, lint_name: &str, tool_name: &str) -> CheckLintNameResult<'_> {
let name_lower = lint_name.to_lowercase();
- if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() {
+ if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_some() {
// First check if the lint name is (partly) in upper case instead of lower case...
return CheckLintNameResult::NoLint(Some((Symbol::intern(&name_lower), false)));
}
@@ -455,18 +446,8 @@ fn check_tool_name_for_backwards_compat(
None => match self.lint_groups.get(&*complete_name) {
// Now we are sure, that this lint exists nowhere
None => self.no_lint_suggestion(lint_name, tool_name),
- Some(LintGroup { lint_ids, depr, .. }) => {
- // Reaching this would be weird, but let's cover this case anyway
- if let Some(LintAlias { name, silent }) = depr {
- let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap();
- if *silent {
- CheckLintNameResult::Tool(lint_ids, Some(complete_name))
- } else {
- CheckLintNameResult::Tool(lint_ids, Some((*name).to_string()))
- }
- } else {
- CheckLintNameResult::Tool(lint_ids, Some(complete_name))
- }
+ Some(LintGroup { lint_ids, .. }) => {
+ CheckLintNameResult::Tool(lint_ids, Some(complete_name))
}
},
Some(Id(id)) => CheckLintNameResult::Tool(slice::from_ref(id), Some(complete_name)),
@@ -855,11 +836,11 @@ pub fn get_associated_type(
&self,
self_ty: Ty<'tcx>,
trait_id: DefId,
- name: &str,
+ name: Symbol,
) -> Option<Ty<'tcx>> {
let tcx = self.tcx;
tcx.associated_items(trait_id)
- .find_by_ident_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
+ .find_by_ident_and_kind(tcx, Ident::with_dummy_span(name), ty::AssocTag::Type, trait_id)
.and_then(|assoc| {
let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]);
tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok()
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index ec8f844..5989ef9 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -69,7 +69,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
&& let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()
&& let Some(self_principal) = data.principal()
// `<T as Deref>::Target` is `dyn target_principal`
- && let Some(target) = cx.get_associated_type(self_ty, did, "Target")
+ && let Some(target) = cx.get_associated_type(self_ty, did, sym::Target)
&& let ty::Dynamic(data, _, ty::Dyn) = target.kind()
&& let Some(target_principal) = data.principal()
// `target_principal` is a supertrait of `t_principal`
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index d109a5c..586e55c 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,5 +1,5 @@
use rustc_errors::codes::*;
-use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
+use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::lint::Level;
use rustc_span::{Span, Symbol};
@@ -26,11 +26,7 @@ pub(crate) enum OverruledAttributeSub {
}
impl Subdiagnostic for OverruledAttributeSub {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
OverruledAttributeSub::DefaultSource { id } => {
diag.note(fluent::lint_default_source);
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index 39ea8d8..a9b0451 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -3,9 +3,7 @@
use hir::intravisit::{self, Visitor};
use rustc_ast::Recovered;
-use rustc_errors::{
- Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
-};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle};
use rustc_hir::{self as hir, HirIdSet};
use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::adjustment::Adjust;
@@ -327,11 +325,7 @@ struct IfLetRescopeRewrite {
}
impl Subdiagnostic for IfLetRescopeRewrite {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut suggestions = vec![];
for match_head in self.match_heads {
match match_head {
@@ -360,7 +354,7 @@ fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
.chain(repeat('}').take(closing_brackets.count))
.collect(),
));
- let msg = f(diag, crate::fluent_generated::lint_suggestion);
+ let msg = diag.eagerly_translate(crate::fluent_generated::lint_suggestion);
diag.multipart_suggestion_with_style(
msg,
suggestions,
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index d0b1e7b..0077564 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -517,11 +517,11 @@ fn add_command_line(&mut self) {
let lint_flag_val = Symbol::intern(lint_name);
- let Ok(ids) = self.store.find_lints(lint_name) else {
+ let Some(ids) = self.store.find_lints(lint_name) else {
// errors already handled above
continue;
};
- for id in ids {
+ for &id in ids {
// ForceWarn and Forbid cannot be overridden
if let Some(LevelAndSource { level: Level::ForceWarn | Level::Forbid, .. }) =
self.current_specs().get(&id)
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 9b5c564..212368b 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -21,7 +21,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
@@ -125,9 +124,7 @@
#[rustfmt::skip]
pub use builtin::{MissingDoc, SoftLints};
-pub use context::{
- CheckLintNameResult, EarlyContext, FindLintError, LateContext, LintContext, LintStore,
-};
+pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore};
pub use early::{EarlyCheckNode, check_ast_node};
pub use late::{check_crate, late_lint_mod, unerased_lint_store};
pub use levels::LintLevelsBuilder;
@@ -606,6 +603,11 @@ macro_rules! add_lint_group {
"converted into hard error, see issue #127323 \
<https://github.com/rust-lang/rust/issues/127323> for more information",
);
+ store.register_removed(
+ "undefined_naked_function_abi",
+ "converted into hard error, see PR #139001 \
+ <https://github.com/rust-lang/rust/issues/139001> for more information",
+ );
}
fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 51214c8..8ab64fb 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -6,7 +6,7 @@
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag,
- EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
+ EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle,
};
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
@@ -449,11 +449,7 @@ pub(crate) struct BuiltinUnpermittedTypeInitSub {
}
impl Subdiagnostic for BuiltinUnpermittedTypeInitSub {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut err = self.err;
loop {
if let Some(span) = err.span {
@@ -504,11 +500,7 @@ pub(crate) struct BuiltinClashingExternSub<'a> {
}
impl Subdiagnostic for BuiltinClashingExternSub<'_> {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut expected_str = DiagStyledString::new();
expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
let mut found_str = DiagStyledString::new();
@@ -824,11 +816,7 @@ pub(crate) struct HiddenUnicodeCodepointsDiagLabels {
}
impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
for (c, span) in self.spans {
diag.span_label(span, format!("{c:?}"));
}
@@ -842,11 +830,7 @@ pub(crate) enum HiddenUnicodeCodepointsDiagSub {
// Used because of multiple multipart_suggestion and note
impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
diag.multipart_suggestion_with_style(
@@ -1015,11 +999,7 @@ pub(crate) struct NonBindingLetSub {
}
impl Subdiagnostic for NonBindingLetSub {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
if can_suggest_binding {
@@ -1303,11 +1283,7 @@ pub(crate) enum NonSnakeCaseDiagSub {
}
impl Subdiagnostic for NonSnakeCaseDiagSub {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
NonSnakeCaseDiagSub::Label { span } => {
diag.span_label(span, fluent::lint_label);
@@ -1629,11 +1605,7 @@ pub(crate) enum OverflowingBinHexSign {
}
impl Subdiagnostic for OverflowingBinHexSign {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
OverflowingBinHexSign::Positive => {
diag.note(fluent::lint_positive_note);
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index a6c82f5..a084dac 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -864,8 +864,8 @@ fn ty_is_known_nonnull<'tcx>(
return true;
}
- // `UnsafeCell` has its niche hidden.
- if def.is_unsafe_cell() {
+ // `UnsafeCell` and `UnsafePinned` have their niche hidden.
+ if def.is_unsafe_cell() || def.is_unsafe_pinned() {
return false;
}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 8a761a0..b25d2a3 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -110,7 +110,6 @@
UNCONDITIONAL_PANIC,
UNCONDITIONAL_RECURSION,
UNCOVERED_PARAM_IN_PROJECTION,
- UNDEFINED_NAKED_FUNCTION_ABI,
UNEXPECTED_CFGS,
UNFULFILLED_LINT_EXPECTATIONS,
UNINHABITED_STATIC,
@@ -2831,39 +2830,6 @@
}
declare_lint! {
- /// The `undefined_naked_function_abi` lint detects naked function definitions that
- /// either do not specify an ABI or specify the Rust ABI.
- ///
- /// ### Example
- ///
- /// ```rust
- /// #![feature(asm_experimental_arch, naked_functions)]
- ///
- /// use std::arch::naked_asm;
- ///
- /// #[naked]
- /// pub fn default_abi() -> u32 {
- /// unsafe { naked_asm!(""); }
- /// }
- ///
- /// #[naked]
- /// pub extern "Rust" fn rust_abi() -> u32 {
- /// unsafe { naked_asm!(""); }
- /// }
- /// ```
- ///
- /// {{produces}}
- ///
- /// ### Explanation
- ///
- /// The Rust ABI is currently undefined. Therefore, naked functions should
- /// specify a non-Rust ABI.
- pub UNDEFINED_NAKED_FUNCTION_ABI,
- Warn,
- "undefined naked function ABI"
-}
-
-declare_lint! {
/// The `ineffective_unstable_trait_impl` lint detects `#[unstable]` attributes which are not used.
///
/// ### Example
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 7fdbae3..b4069b3 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -249,7 +249,7 @@ pub fn from_str(x: &str) -> Option<Self> {
/// Converts an `Attribute` to a level.
pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option<LintExpectationId>)> {
- Self::from_symbol(attr.name_or_empty(), || Some(attr.id()))
+ attr.name().and_then(|name| Self::from_symbol(name, || Some(attr.id())))
}
/// Converts a `Symbol` to a level.
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 909083d..bc9516b 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -20,14 +20,12 @@
/// The central struct for constructing the `add_to_diag` method from an annotated struct.
pub(crate) struct SubdiagnosticDerive {
diag: syn::Ident,
- f: syn::Ident,
}
impl SubdiagnosticDerive {
pub(crate) fn new() -> Self {
let diag = format_ident!("diag");
- let f = format_ident!("f");
- Self { diag, f }
+ Self { diag }
}
pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
@@ -86,19 +84,16 @@ pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
};
let diag = &self.diag;
- let f = &self.f;
// FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here?
#[allow(keyword_idents_2024)]
let ret = structure.gen_impl(quote! {
gen impl rustc_errors::Subdiagnostic for @Self {
- fn add_to_diag_with<__G, __F>(
+ fn add_to_diag<__G>(
self,
#diag: &mut rustc_errors::Diag<'_, __G>,
- #f: &__F
) where
__G: rustc_errors::EmissionGuarantee,
- __F: rustc_errors::SubdiagMessageOp<__G>,
{
#implementation
}
@@ -384,11 +379,10 @@ fn generate_field_code_inner_path(
Ok(quote! {})
}
"subdiagnostic" => {
- let f = &self.parent.f;
let diag = &self.parent.diag;
let binding = &info.binding;
self.has_subdiagnostic = true;
- Ok(quote! { #binding.add_to_diag_with(#diag, #f); })
+ Ok(quote! { #binding.add_to_diag(#diag); })
}
_ => {
let mut span_attrs = vec![];
@@ -531,12 +525,11 @@ pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveErro
let span_field = self.span_field.value_ref();
let diag = &self.parent.diag;
- let f = &self.parent.f;
let mut calls = TokenStream::new();
for (kind, slug, no_span) in kind_slugs {
let message = format_ident!("__message");
calls.extend(
- quote! { let #message = #f(#diag, crate::fluent_generated::#slug.into()); },
+ quote! { let #message = #diag.eagerly_translate(crate::fluent_generated::#slug); },
);
let name = format_ident!(
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index c4f584d..8505131 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -14,31 +14,33 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
s.add_bounds(synstructure::AddBounds::Generics);
s.bind_with(|_| synstructure::BindStyle::Move);
+ let try_body_fold = s.each_variant(|vi| {
+ let bindings = vi.bindings();
+ vi.construct(|_, index| {
+ let bind = &bindings[index];
+
+ // retain value of fields with #[type_foldable(identity)]
+ if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") {
+ bind.to_token_stream()
+ } else {
+ quote! {
+ ::rustc_middle::ty::TypeFoldable::try_fold_with(#bind, __folder)?
+ }
+ }
+ })
+ });
+
let body_fold = s.each_variant(|vi| {
let bindings = vi.bindings();
vi.construct(|_, index| {
let bind = &bindings[index];
- let mut fixed = false;
-
// retain value of fields with #[type_foldable(identity)]
- bind.ast().attrs.iter().for_each(|x| {
- if !x.path().is_ident("type_foldable") {
- return;
- }
- let _ = x.parse_nested_meta(|nested| {
- if nested.path.is_ident("identity") {
- fixed = true;
- }
- Ok(())
- });
- });
-
- if fixed {
+ if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") {
bind.to_token_stream()
} else {
quote! {
- ::rustc_middle::ty::TypeFoldable::try_fold_with(#bind, __folder)?
+ ::rustc_middle::ty::TypeFoldable::fold_with(#bind, __folder)
}
}
})
@@ -51,8 +53,32 @@ fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty:
self,
__folder: &mut __F
) -> Result<Self, __F::Error> {
- Ok(match self { #body_fold })
+ Ok(match self { #try_body_fold })
+ }
+
+ fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(
+ self,
+ __folder: &mut __F
+ ) -> Self {
+ match self { #body_fold }
}
},
)
}
+
+fn has_ignore_attr(attrs: &[syn::Attribute], name: &'static str, meta: &'static str) -> bool {
+ let mut ignored = false;
+ attrs.iter().for_each(|attr| {
+ if !attr.path().is_ident(name) {
+ return;
+ }
+ let _ = attr.parse_nested_meta(|nested| {
+ if nested.path.is_ident(meta) {
+ ignored = true;
+ }
+ Ok(())
+ });
+ });
+
+ ignored
+}
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 028d5c8..3b44c44 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -1,6 +1,5 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(coroutines)]
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index cfb0de8..cee9cff 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -226,8 +226,8 @@ fn process_module(&mut self, module: &ForeignModule) {
let mut wasm_import_module = None;
let mut import_name_type = None;
for item in items.iter() {
- match item.name_or_empty() {
- sym::name => {
+ match item.name() {
+ Some(sym::name) => {
if name.is_some() {
sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
continue;
@@ -242,7 +242,7 @@ fn process_module(&mut self, module: &ForeignModule) {
}
name = Some((link_name, span));
}
- sym::kind => {
+ Some(sym::kind) => {
if kind.is_some() {
sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
continue;
@@ -304,7 +304,7 @@ fn process_module(&mut self, module: &ForeignModule) {
};
kind = Some(link_kind);
}
- sym::modifiers => {
+ Some(sym::modifiers) => {
if modifiers.is_some() {
sess.dcx()
.emit_err(errors::MultipleLinkModifiers { span: item.span() });
@@ -316,7 +316,7 @@ fn process_module(&mut self, module: &ForeignModule) {
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
- sym::cfg => {
+ Some(sym::cfg) => {
if cfg.is_some() {
sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
continue;
@@ -346,7 +346,7 @@ fn process_module(&mut self, module: &ForeignModule) {
}
cfg = Some(link_cfg.clone());
}
- sym::wasm_import_module => {
+ Some(sym::wasm_import_module) => {
if wasm_import_module.is_some() {
sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
continue;
@@ -357,7 +357,7 @@ fn process_module(&mut self, module: &ForeignModule) {
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
- sym::import_name_type => {
+ Some(sym::import_name_type) => {
if import_name_type.is_some() {
sess.dcx()
.emit_err(errors::MultipleImportNameType { span: item.span() });
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 4cc12ca..3c22453 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1332,29 +1332,30 @@ fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Ite
}
fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
- let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
- kw::Empty
- } else {
- self.item_name(id)
- };
- let (kind, has_self) = match self.def_kind(id) {
- DefKind::AssocConst => (ty::AssocKind::Const, false),
- DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
- DefKind::AssocTy => (ty::AssocKind::Type, false),
+ let kind = match self.def_kind(id) {
+ DefKind::AssocConst => ty::AssocKind::Const { name: self.item_name(id) },
+ DefKind::AssocFn => ty::AssocKind::Fn {
+ name: self.item_name(id),
+ has_self: self.get_fn_has_self_parameter(id, sess),
+ },
+ DefKind::AssocTy => {
+ let data = if let Some(rpitit_info) = self.root.tables.opt_rpitit_info.get(self, id)
+ {
+ ty::AssocTypeData::Rpitit(rpitit_info.decode(self))
+ } else {
+ ty::AssocTypeData::Normal(self.item_name(id))
+ };
+ ty::AssocKind::Type { data }
+ }
_ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
};
let container = self.root.tables.assoc_container.get(self, id).unwrap();
- let opt_rpitit_info =
- self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self));
ty::AssocItem {
- name,
kind,
def_id: self.local_def_id(id),
trait_item_def_id: self.get_trait_item_def_id(id),
container,
- fn_has_self_parameter: has_self,
- opt_rpitit_info,
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 903fa1e..3ea61d1 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -821,7 +821,9 @@ struct AnalyzeAttrState<'a> {
#[inline]
fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> bool {
let mut should_encode = false;
- if !rustc_feature::encode_cross_crate(attr.name_or_empty()) {
+ if let Some(name) = attr.name()
+ && !rustc_feature::encode_cross_crate(name)
+ {
// Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
} else if attr.doc_str().is_some() {
// We keep all doc comments reachable to rustdoc because they might be "imported" into
@@ -1338,7 +1340,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
if let Some(assoc_item) = tcx.opt_associated_item(def_id)
&& assoc_item.container == ty::AssocItemContainer::Trait
- && assoc_item.kind == ty::AssocKind::Fn
+ && assoc_item.is_fn()
{
true
} else {
@@ -1691,7 +1693,7 @@ fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
match item.container {
AssocItemContainer::Trait => {
- if let ty::AssocKind::Type = item.kind {
+ if item.is_type() {
self.encode_explicit_item_bounds(def_id);
self.encode_explicit_item_self_bounds(def_id);
if tcx.is_conditionally_const(def_id) {
@@ -1706,7 +1708,7 @@ fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
}
}
}
- if let Some(rpitit_info) = item.opt_rpitit_info {
+ if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind {
record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info);
if matches!(rpitit_info, ty::ImplTraitInTraitData::Trait { .. }) {
record_array!(
@@ -2199,7 +2201,7 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
}
let reachable_set = tcx.reachable_set(());
- par_for_each_in(tcx.mir_keys(()), |&def_id| {
+ par_for_each_in(tcx.mir_keys(()), |&&def_id| {
let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id);
if encode_const {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 2f27e5f..5aa81f4 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -36,9 +36,7 @@
use rustc_session::config::{SymbolManglingVersion, TargetModifier};
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
use rustc_span::edition::Edition;
-use rustc_span::hygiene::{
- ExpnIndex, MacroKind, SyntaxContextDataNonRecursive as SyntaxContextData,
-};
+use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey};
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol};
use rustc_target::spec::{PanicStrategy, TargetTuple};
use table::TableBuilder;
@@ -195,7 +193,7 @@ enum LazyState {
Previous(NonZero<usize>),
}
-type SyntaxContextTable = LazyTable<u32, Option<LazyValue<SyntaxContextData>>>;
+type SyntaxContextTable = LazyTable<u32, Option<LazyValue<SyntaxContextKey>>>;
type ExpnDataTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnData>>>;
type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 98273a0..d1bbb05 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -89,7 +89,6 @@ macro_rules! arena_types {
[] name_set: rustc_data_structures::unord::UnordSet<rustc_span::Symbol>,
[] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem,
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::Symbol>,
- [] pats: rustc_middle::ty::PatternKind<'tcx>,
[] valtree: rustc_middle::ty::ValTreeKind<'tcx>,
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 7f2b9e9..fee707f 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -1,3 +1,7 @@
+//! This module used to contain a type called `Map`. That type has since been
+//! eliminated, and all its methods are now on `TyCtxt`. But the module name
+//! stays as `map` because there isn't an obviously better name for it.
+
use rustc_abi::ExternAbi;
use rustc_ast::visit::{VisitorResult, walk_list};
use rustc_data_structures::fingerprint::Fingerprint;
@@ -18,16 +22,6 @@
use crate::query::LocalCrate;
use crate::ty::TyCtxt;
-// FIXME: the structure was necessary in the past but now it
-// only serves as "namespace" for HIR-related methods, and can be
-// removed if all the methods are reasonably renamed and moved to tcx
-// (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834).
-#[allow(unused)] // FIXME: temporary
-#[derive(Copy, Clone)]
-pub struct Map<'hir> {
- pub(super) tcx: TyCtxt<'hir>,
-}
-
/// An iterator that walks up the ancestor tree of a given `HirId`.
/// Constructed using `tcx.hir_parent_iter(hir_id)`.
struct ParentHirIterator<'tcx> {
@@ -335,7 +329,7 @@ pub fn hir_body_const_context(self, def_id: impl Into<DefId>) -> Option<ConstCon
/// Returns an iterator of the `DefId`s for all body-owners in this
/// crate. If you would prefer to iterate over the bodies
- /// themselves, you can do `self.hir().krate().body_ids.iter()`.
+ /// themselves, you can do `self.hir_crate(()).body_ids.iter()`.
#[inline]
pub fn hir_body_owners(self) -> impl Iterator<Item = LocalDefId> {
self.hir_crate_items(()).body_owners.iter().copied()
@@ -343,7 +337,7 @@ pub fn hir_body_owners(self) -> impl Iterator<Item = LocalDefId> {
#[inline]
pub fn par_hir_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
- par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
+ par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&&def_id| f(def_id));
}
pub fn hir_ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index a3177a6..a28dcb0 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -83,44 +83,39 @@ pub fn par_items(
&self,
f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
) -> Result<(), ErrorGuaranteed> {
- try_par_for_each_in(&self.free_items[..], |&id| f(id))
+ try_par_for_each_in(&self.free_items[..], |&&id| f(id))
}
pub fn par_trait_items(
&self,
f: impl Fn(TraitItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
) -> Result<(), ErrorGuaranteed> {
- try_par_for_each_in(&self.trait_items[..], |&id| f(id))
+ try_par_for_each_in(&self.trait_items[..], |&&id| f(id))
}
pub fn par_impl_items(
&self,
f: impl Fn(ImplItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
) -> Result<(), ErrorGuaranteed> {
- try_par_for_each_in(&self.impl_items[..], |&id| f(id))
+ try_par_for_each_in(&self.impl_items[..], |&&id| f(id))
}
pub fn par_foreign_items(
&self,
f: impl Fn(ForeignItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
) -> Result<(), ErrorGuaranteed> {
- try_par_for_each_in(&self.foreign_items[..], |&id| f(id))
+ try_par_for_each_in(&self.foreign_items[..], |&&id| f(id))
}
pub fn par_opaques(
&self,
f: impl Fn(LocalDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
) -> Result<(), ErrorGuaranteed> {
- try_par_for_each_in(&self.opaques[..], |&id| f(id))
+ try_par_for_each_in(&self.opaques[..], |&&id| f(id))
}
}
impl<'tcx> TyCtxt<'tcx> {
- #[inline(always)]
- pub fn hir(self) -> map::Map<'tcx> {
- map::Map { tcx: self }
- }
-
pub fn parent_module(self, id: HirId) -> LocalModDefId {
if !id.is_owner() && self.def_kind(id.owner) == DefKind::Mod {
LocalModDefId::new_unchecked(id.owner.def_id)
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index 60ce854..c3d1061 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -40,6 +40,8 @@ pub enum ProjectionKind {
/// A conversion from an opaque type to its hidden type so we can
/// do further projections on it.
+ ///
+ /// This is unused if `-Znext-solver` is enabled.
OpaqueCast,
}
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 3cd148c..5b86037 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -39,15 +39,6 @@
pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
-impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
- fn try_fold_with<F: ty::FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_canonical_var_infos(v))
- }
-}
-
/// When we canonicalize a value to form a query, we wind up replacing
/// various parts of it with canonical variables. This struct stores
/// those replaced bits to remember for when we process the query
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 1e61781..8fe2cc7 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -29,7 +29,6 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::potential_query_instability)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(allocator_api)]
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 4dfb362..db19c85 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1636,8 +1636,8 @@ pub fn find_self_call<'tcx>(
&body[block].terminator
&& let Operand::Constant(box ConstOperand { const_, .. }) = func
&& let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
- && let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
- tcx.opt_associated_item(def_id)
+ && let Some(item) = tcx.opt_associated_item(def_id)
+ && item.is_method()
&& let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
**args
{
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 5a038b2..d57019f 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -531,12 +531,12 @@ fn write_mir_intro<'tcx>(
// construct a scope tree and write it out
let mut scope_tree: FxHashMap<SourceScope, Vec<SourceScope>> = Default::default();
- for (index, scope_data) in body.source_scopes.iter().enumerate() {
+ for (index, scope_data) in body.source_scopes.iter_enumerated() {
if let Some(parent) = scope_data.parent_scope {
- scope_tree.entry(parent).or_default().push(SourceScope::new(index));
+ scope_tree.entry(parent).or_default().push(index);
} else {
// Only the argument scope has no parent, because it's the root.
- assert_eq!(index, OUTERMOST_SOURCE_SCOPE.index());
+ assert_eq!(index, OUTERMOST_SOURCE_SCOPE);
}
}
@@ -859,7 +859,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
BackwardIncompatibleDropHint { ref place, reason: _ } => {
// For now, we don't record the reason because there is only one use case,
// which is to report breaking change in drop order by Edition 2024
- write!(fmt, "backward incompatible drop({place:?})")
+ write!(fmt, "BackwardIncompatibleDropHint({place:?})")
}
}
}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index ff9d32e..304b3ca 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -931,6 +931,8 @@ pub enum TerminatorKind<'tcx> {
asm_macro: InlineAsmMacro,
/// The template for the inline assembly, with placeholders.
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
template: &'tcx [InlineAsmTemplatePiece],
/// The operands for the inline assembly, as `Operand`s or `Place`s.
@@ -941,6 +943,8 @@ pub enum TerminatorKind<'tcx> {
/// Source spans for each line of the inline assembly code. These are
/// used to map assembler errors back to the line in the source code.
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
line_spans: &'tcx [Span],
/// Valid targets for the inline assembly.
@@ -1238,6 +1242,8 @@ pub enum ProjectionElem<V, T> {
/// Like an explicit cast from an opaque type to a concrete type, but without
/// requiring an intermediate variable.
+ ///
+ /// This is unused with `-Znext-solver`.
OpaqueCast(T),
/// A transmute from an unsafe binder to the type that it wraps. This is a projection
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 3c83d96..de4d514 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -457,9 +457,15 @@ fn super_statement(
}
}
}
+ StatementKind::BackwardIncompatibleDropHint { place, .. } => {
+ self.visit_place(
+ place,
+ PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint),
+ location
+ );
+ }
StatementKind::ConstEvalCounter => {}
StatementKind::Nop => {}
- StatementKind::BackwardIncompatibleDropHint { .. } => {}
}
}
@@ -1348,6 +1354,8 @@ pub enum NonUseContext {
AscribeUserTy(ty::Variance),
/// The data of a user variable, for debug info.
VarDebugInfo,
+ /// A `BackwardIncompatibleDropHint` statement, meant for edition 2024 lints.
+ BackwardIncompatibleDropHint,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -1422,7 +1430,9 @@ pub fn ambient_variance(self) -> ty::Variance {
use NonUseContext::*;
match self {
PlaceContext::MutatingUse(_) => ty::Invariant,
- PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
+ PlaceContext::NonUse(
+ StorageDead | StorageLive | VarDebugInfo | BackwardIncompatibleDropHint,
+ ) => ty::Invariant,
PlaceContext::NonMutatingUse(
Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
| Projection,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 28a59d3..e94f088 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -161,11 +161,11 @@
/// Represents crate as a whole (as distinct from the top-level crate module).
///
- /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir_crate()`),
- /// we will have to assume that any change means that you need to be recompiled.
- /// This is because the `hir_crate` query gives you access to all other items.
- /// To avoid this fate, do not call `tcx.hir_crate()`; instead,
- /// prefer wrappers like [`TyCtxt::hir_visit_all_item_likes_in_crate`].
+ /// If you call `tcx.hir_crate(())` we will have to assume that any change
+ /// means that you need to be recompiled. This is because the `hir_crate`
+ /// query gives you access to all other items. To avoid this fate, do not
+ /// call `tcx.hir_crate(())`; instead, prefer wrappers like
+ /// [`TyCtxt::hir_visit_all_item_likes_in_crate`].
query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
arena_cache
eval_always
@@ -197,7 +197,7 @@
/// Gives access to the HIR node's parent for the HIR owner `key`.
///
- /// This can be conveniently accessed by methods on `tcx.hir()`.
+ /// This can be conveniently accessed by `tcx.hir_*` methods.
/// Avoid calling this query directly.
query hir_owner_parent(key: hir::OwnerId) -> hir::HirId {
desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) }
@@ -205,7 +205,7 @@
/// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner.
///
- /// This can be conveniently accessed by methods on `tcx.hir()`.
+ /// This can be conveniently accessed by `tcx.hir_*` methods.
/// Avoid calling this query directly.
query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> {
desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) }
@@ -214,7 +214,7 @@
/// Gives access to the HIR attributes inside the HIR owner `key`.
///
- /// This can be conveniently accessed by methods on `tcx.hir()`.
+ /// This can be conveniently accessed by `tcx.hir_*` methods.
/// Avoid calling this query directly.
query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index f78398c..5431097 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -16,8 +16,7 @@
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_session::Session;
use rustc_span::hygiene::{
- ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext,
- SyntaxContextDataNonRecursive as SyntaxContextData,
+ ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey,
};
use rustc_span::source_map::Spanned;
use rustc_span::{
@@ -567,7 +566,7 @@ fn decode_syntax_context(&mut self) -> SyntaxContext {
// We look up the position of the associated `SyntaxData` and decode it.
let pos = syntax_contexts.get(&id).unwrap();
this.with_position(pos.to_usize(), |decoder| {
- let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT);
+ let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT);
data
})
})
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index f8ab555..a61a6c5 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -5,7 +5,7 @@
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_span::Span;
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{Ty, TyCtxt};
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum PointerCoercion {
@@ -133,7 +133,7 @@ pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>) -> DefId {
};
tcx.associated_items(trait_def_id)
.in_definition_order()
- .find(|m| m.kind == ty::AssocKind::Fn)
+ .find(|item| item.is_fn())
.unwrap()
.def_id
}
@@ -214,3 +214,25 @@ pub enum CustomCoerceUnsized {
/// Records the index of the field being coerced.
Struct(FieldIdx),
}
+
+/// Represents an implicit coercion applied to the scrutinee of a match before testing a pattern
+/// against it. Currently, this is used only for implicit dereferences.
+#[derive(Clone, Copy, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
+pub struct PatAdjustment<'tcx> {
+ pub kind: PatAdjust,
+ /// The type of the scrutinee before the adjustment is applied, or the "adjusted type" of the
+ /// pattern.
+ pub source: Ty<'tcx>,
+}
+
+/// Represents implicit coercions of patterns' types, rather than values' types.
+#[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub enum PatAdjust {
+ /// An implicit dereference before matching, such as when matching the pattern `0` against a
+ /// scrutinee of type `&u8` or `&mut u8`.
+ BuiltinDeref,
+ /// An implicit call to `Deref(Mut)::deref(_mut)` before matching, such as when matching the
+ /// pattern `[..]` against a scrutinee of type `Vec<T>`.
+ OverloadedDeref,
+}
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 00fe5cb..66517c9 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -53,6 +53,10 @@ impl AdtFlags: u16 {
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
/// Indicates whether the type is `UnsafeCell`.
const IS_UNSAFE_CELL = 1 << 9;
+ /// Indicates whether the type is `UnsafePinned`.
+ const IS_UNSAFE_PINNED = 1 << 10;
+ /// Indicates whether the type is anonymous.
+ const IS_ANONYMOUS = 1 << 11;
}
}
rustc_data_structures::external_bitflags_debug! { AdtFlags }
@@ -302,6 +306,9 @@ pub(super) fn new(
if tcx.is_lang_item(did, LangItem::UnsafeCell) {
flags |= AdtFlags::IS_UNSAFE_CELL;
}
+ if tcx.is_lang_item(did, LangItem::UnsafePinned) {
+ flags |= AdtFlags::IS_UNSAFE_PINNED;
+ }
AdtDefData { did, variants, flags, repr }
}
@@ -405,6 +412,12 @@ pub fn is_unsafe_cell(self) -> bool {
self.flags().contains(AdtFlags::IS_UNSAFE_CELL)
}
+ /// Returns `true` if this is `UnsafePinned<T>`.
+ #[inline]
+ pub fn is_unsafe_pinned(self) -> bool {
+ self.flags().contains(AdtFlags::IS_UNSAFE_PINNED)
+ }
+
/// Returns `true` if this is `ManuallyDrop<T>`.
#[inline]
pub fn is_manually_drop(self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index bbaf735..0c44fd2 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -18,27 +18,33 @@ pub enum AssocItemContainer {
#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash, Encodable, Decodable)]
pub struct AssocItem {
pub def_id: DefId,
- pub name: Symbol,
pub kind: AssocKind,
pub container: AssocItemContainer,
/// If this is an item in an impl of a trait then this is the `DefId` of
/// the associated item on the trait that this implements.
pub trait_item_def_id: Option<DefId>,
-
- /// Whether this is a method with an explicit self
- /// as its first parameter, allowing method calls.
- pub fn_has_self_parameter: bool,
-
- /// `Some` if the associated item (an associated type) comes from the
- /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
- /// provides additional information about its source.
- pub opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
}
impl AssocItem {
+ // Gets the identifier, if it has one.
+ pub fn opt_name(&self) -> Option<Symbol> {
+ match self.kind {
+ ty::AssocKind::Type { data: AssocTypeData::Normal(name) } => Some(name),
+ ty::AssocKind::Type { data: AssocTypeData::Rpitit(_) } => None,
+ ty::AssocKind::Const { name } => Some(name),
+ ty::AssocKind::Fn { name, .. } => Some(name),
+ }
+ }
+
+ // Gets the identifier name. Aborts if it lacks one, i.e. is an RPITIT
+ // associated type.
+ pub fn name(&self) -> Symbol {
+ self.opt_name().expect("name of non-Rpitit assoc item")
+ }
+
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
- Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
+ Ident::new(self.name(), tcx.def_ident_span(self.def_id).unwrap())
}
/// Gets the defaultness of the associated item.
@@ -78,35 +84,65 @@ pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
match self.kind {
- ty::AssocKind::Fn => {
+ ty::AssocKind::Fn { .. } => {
// We skip the binder here because the binder would deanonymize all
// late-bound regions, and we don't want method signatures to show up
// `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
// regions just fine, showing `fn(&MyType)`.
tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string()
}
- ty::AssocKind::Type => format!("type {};", self.name),
- ty::AssocKind::Const => {
- format!(
- "const {}: {:?};",
- self.name,
- tcx.type_of(self.def_id).instantiate_identity()
- )
+ ty::AssocKind::Type { .. } => format!("type {};", self.name()),
+ ty::AssocKind::Const { name } => {
+ format!("const {}: {:?};", name, tcx.type_of(self.def_id).instantiate_identity())
}
}
}
pub fn descr(&self) -> &'static str {
match self.kind {
- ty::AssocKind::Const => "associated const",
- ty::AssocKind::Fn if self.fn_has_self_parameter => "method",
- ty::AssocKind::Fn => "associated function",
- ty::AssocKind::Type => "associated type",
+ ty::AssocKind::Const { .. } => "associated const",
+ ty::AssocKind::Fn { has_self: true, .. } => "method",
+ ty::AssocKind::Fn { has_self: false, .. } => "associated function",
+ ty::AssocKind::Type { .. } => "associated type",
+ }
+ }
+
+ pub fn namespace(&self) -> Namespace {
+ match self.kind {
+ ty::AssocKind::Type { .. } => Namespace::TypeNS,
+ ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
+ }
+ }
+
+ pub fn as_def_kind(&self) -> DefKind {
+ match self.kind {
+ AssocKind::Const { .. } => DefKind::AssocConst,
+ AssocKind::Fn { .. } => DefKind::AssocFn,
+ AssocKind::Type { .. } => DefKind::AssocTy,
+ }
+ }
+ pub fn is_type(&self) -> bool {
+ matches!(self.kind, ty::AssocKind::Type { .. })
+ }
+
+ pub fn is_fn(&self) -> bool {
+ matches!(self.kind, ty::AssocKind::Fn { .. })
+ }
+
+ pub fn is_method(&self) -> bool {
+ matches!(self.kind, ty::AssocKind::Fn { has_self: true, .. })
+ }
+
+ pub fn as_tag(&self) -> AssocTag {
+ match self.kind {
+ AssocKind::Const { .. } => AssocTag::Const,
+ AssocKind::Fn { .. } => AssocTag::Fn,
+ AssocKind::Type { .. } => AssocTag::Type,
}
}
pub fn is_impl_trait_in_trait(&self) -> bool {
- self.opt_rpitit_info.is_some()
+ matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) })
}
/// Returns true if:
@@ -114,7 +150,7 @@ pub fn is_impl_trait_in_trait(&self) -> bool {
/// - If it is in a trait impl, the item from the original trait has this attribute, or
/// - It is an inherent assoc const.
pub fn is_type_const_capable(&self, tcx: TyCtxt<'_>) -> bool {
- if self.kind != ty::AssocKind::Const {
+ if !matches!(self.kind, ty::AssocKind::Const { .. }) {
return false;
}
@@ -129,25 +165,34 @@ pub fn is_type_const_capable(&self, tcx: TyCtxt<'_>) -> bool {
}
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
+pub enum AssocTypeData {
+ Normal(Symbol),
+ /// The associated type comes from an RPITIT. It has no name, and the
+ /// `ImplTraitInTraitData` provides additional information about its
+ /// source.
+ Rpitit(ty::ImplTraitInTraitData),
+}
+
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)]
pub enum AssocKind {
- Const,
- Fn,
- Type,
+ Const { name: Symbol },
+ Fn { name: Symbol, has_self: bool },
+ Type { data: AssocTypeData },
}
impl AssocKind {
pub fn namespace(&self) -> Namespace {
match *self {
- ty::AssocKind::Type => Namespace::TypeNS,
- ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS,
+ ty::AssocKind::Type { .. } => Namespace::TypeNS,
+ ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
}
}
pub fn as_def_kind(&self) -> DefKind {
match self {
- AssocKind::Const => DefKind::AssocConst,
- AssocKind::Fn => DefKind::AssocFn,
- AssocKind::Type => DefKind::AssocTy,
+ AssocKind::Const { .. } => DefKind::AssocConst,
+ AssocKind::Fn { .. } => DefKind::AssocFn,
+ AssocKind::Type { .. } => DefKind::AssocTy,
}
}
}
@@ -155,15 +200,22 @@ pub fn as_def_kind(&self) -> DefKind {
impl std::fmt::Display for AssocKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
- // FIXME: fails to distinguish between "associated function" and
- // "method" because `has_self` isn't known here.
- AssocKind::Fn => write!(f, "method"),
- AssocKind::Const => write!(f, "associated const"),
- AssocKind::Type => write!(f, "associated type"),
+ AssocKind::Fn { has_self: true, .. } => write!(f, "method"),
+ AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"),
+ AssocKind::Const { .. } => write!(f, "associated const"),
+ AssocKind::Type { .. } => write!(f, "associated type"),
}
}
}
+// Like `AssocKind`, but just the tag, no fields. Used in various kinds of matching.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum AssocTag {
+ Const,
+ Fn,
+ Type,
+}
+
/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
///
/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
@@ -171,17 +223,17 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// done only on items with the same name.
#[derive(Debug, Clone, PartialEq, HashStable)]
pub struct AssocItems {
- items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
+ items: SortedIndexMultiMap<u32, Option<Symbol>, ty::AssocItem>,
}
impl AssocItems {
/// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
- let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
+ let items = items_in_def_order.into_iter().map(|item| (item.opt_name(), item)).collect();
AssocItems { items }
}
- /// Returns a slice of associated items in the order they were defined.
+ /// Returns an iterator over associated items in the order they were defined.
///
/// New code should avoid relying on definition order. If you need a particular associated item
/// for a known trait, make that trait a lang item instead of indexing this array.
@@ -198,7 +250,8 @@ pub fn filter_by_name_unhygienic(
&self,
name: Symbol,
) -> impl '_ + Iterator<Item = &ty::AssocItem> {
- self.items.get_by_key(name)
+ assert!(!name.is_empty());
+ self.items.get_by_key(Some(name))
}
/// Returns the associated item with the given identifier and `AssocKind`, if one exists.
@@ -207,27 +260,14 @@ pub fn find_by_ident_and_kind(
&self,
tcx: TyCtxt<'_>,
ident: Ident,
- kind: AssocKind,
+ assoc_tag: AssocTag,
parent_def_id: DefId,
) -> Option<&ty::AssocItem> {
self.filter_by_name_unhygienic(ident.name)
- .filter(|item| item.kind == kind)
+ .filter(|item| item.as_tag() == assoc_tag)
.find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
}
- /// Returns the associated item with the given identifier and any of `AssocKind`, if one
- /// exists. The identifier is matched hygienically.
- pub fn find_by_ident_and_kinds(
- &self,
- tcx: TyCtxt<'_>,
- ident: Ident,
- // Sorted in order of what kinds to look at
- kinds: &[AssocKind],
- parent_def_id: DefId,
- ) -> Option<&ty::AssocItem> {
- kinds.iter().find_map(|kind| self.find_by_ident_and_kind(tcx, ident, *kind, parent_def_id))
- }
-
/// Returns the associated item with the given identifier in the given `Namespace`, if one
/// exists. The identifier is matched hygienically.
pub fn find_by_ident_and_namespace(
@@ -238,7 +278,7 @@ pub fn find_by_ident_and_namespace(
parent_def_id: DefId,
) -> Option<&ty::AssocItem> {
self.filter_by_name_unhygienic(ident.name)
- .filter(|item| item.kind.namespace() == ns)
+ .filter(|item| item.namespace() == ns)
.find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
}
}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index ae1c6c6..dc5fe2d 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -3,6 +3,7 @@
use rustc_data_structures::intern::Interned;
use rustc_error_messages::MultiSpan;
use rustc_macros::HashStable;
+use rustc_type_ir::walk::TypeWalker;
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
use crate::ty::{self, Ty, TyCtxt};
@@ -243,4 +244,18 @@ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
pub fn is_ct_infer(self) -> bool {
matches!(self.kind(), ty::ConstKind::Infer(_))
}
+
+ /// Iterator that walks `self` and any types reachable from
+ /// `self`, in depth-first order. Note that just walks the types
+ /// that appear in `self`, it does not descend into the fields of
+ /// structs or variants. For example:
+ ///
+ /// ```text
+ /// isize => { isize }
+ /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+ /// [isize] => { [isize], isize }
+ /// ```
+ pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
+ TypeWalker::new(self.into())
+ }
}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index abf6cbb..fa2f1cf 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -464,7 +464,7 @@ fn as_lang_item(self, def_id: DefId) -> Option<TraitSolverLangItem> {
fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator<Item = DefId> {
self.associated_items(def_id)
.in_definition_order()
- .filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type))
+ .filter(|assoc_item| assoc_item.is_type())
.map(|assoc_item| assoc_item.def_id)
}
@@ -870,7 +870,7 @@ fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -
Ty(Interned::new_unchecked(
self.type_
.intern(kind, |kind| {
- let flags = super::flags::FlagComputation::for_kind(&kind);
+ let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_kind(&kind);
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
@@ -896,7 +896,7 @@ fn intern_const(
Const(Interned::new_unchecked(
self.const_
.intern(kind, |kind: ty::ConstKind<'_>| {
- let flags = super::flags::FlagComputation::for_const_kind(&kind);
+ let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_const_kind(&kind);
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
@@ -912,7 +912,7 @@ fn intern_const(
fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
&self,
- flags: &ty::flags::FlagComputation,
+ flags: &ty::FlagComputation<TyCtxt<'tcx>>,
sess: &'a Session,
untracked: &'a Untracked,
val: &T,
@@ -940,7 +940,7 @@ fn intern_predicate(
Predicate(Interned::new_unchecked(
self.predicate
.intern(kind, |kind| {
- let flags = super::flags::FlagComputation::for_predicate(kind);
+ let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_predicate(kind);
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
@@ -961,7 +961,7 @@ fn intern_clauses(&self, clauses: &[Clause<'tcx>]) -> Clauses<'tcx> {
} else {
self.clauses
.intern_ref(clauses, || {
- let flags = super::flags::FlagComputation::for_clauses(clauses);
+ let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_clauses(clauses);
InternedInSet(ListWithCachedTypeInfo::from_arena(
&*self.arena,
@@ -2147,7 +2147,7 @@ pub fn return_type_impl_or_dyn_traits(
return vec![];
};
- let mut v = TraitObjectVisitor(vec![], self.hir());
+ let mut v = TraitObjectVisitor(vec![]);
v.visit_ty_unambig(hir_output);
v.0
}
@@ -2160,7 +2160,7 @@ pub fn return_type_impl_or_dyn_traits_with_type_alias(
scope_def_id: LocalDefId,
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
let hir_id = self.local_def_id_to_hir_id(scope_def_id);
- let mut v = TraitObjectVisitor(vec![], self.hir());
+ let mut v = TraitObjectVisitor(vec![]);
// when the return type is a type alias
if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir_fn_decl_by_hir_id(hir_id)
&& let hir::TyKind::Path(hir::QPath::Resolved(
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index d3abb3d..fbb57b8 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -571,15 +571,15 @@ pub fn suggest_constraining_type_params<'a>(
}
/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
-pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>);
+pub(crate) struct TraitObjectVisitor<'tcx>(pub(crate) Vec<&'tcx hir::Ty<'tcx>>);
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
match ty.kind {
hir::TyKind::TraitObject(_, tagged_ptr)
if let hir::Lifetime {
- res:
- hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
+ kind:
+ hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Static,
..
} = tagged_ptr.pointer() =>
{
@@ -592,18 +592,6 @@ fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
}
}
-/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
-pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>);
-
-impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
- fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
- if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res
- {
- self.0.push(lt.ident.span);
- }
- }
-}
-
pub struct IsSuggestableVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
infer_suggestable: bool,
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index a0e67929..5ecf117 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -279,7 +279,7 @@ pub fn short_string<T>(self, p: T, path: &mut Option<PathBuf>) -> String
p.hash(&mut s);
let hash = s.finish();
*path = Some(path.take().unwrap_or_else(|| {
- self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None)
+ self.output_filenames(()).temp_path_for_diagnostic(&format!("long-type-{hash}.txt"))
}));
let Ok(mut file) =
File::options().create(true).read(true).append(true).open(&path.as_ref().unwrap())
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
deleted file mode 100644
index 2424923..0000000
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ /dev/null
@@ -1,359 +0,0 @@
-use std::slice;
-
-use crate::ty::{self, GenericArg, GenericArgKind, InferConst, Ty, TypeFlags};
-
-#[derive(Debug)]
-pub struct FlagComputation {
- pub flags: TypeFlags,
-
- /// see `Ty::outer_exclusive_binder` for details
- pub outer_exclusive_binder: ty::DebruijnIndex,
-}
-
-impl FlagComputation {
- fn new() -> FlagComputation {
- FlagComputation { flags: TypeFlags::empty(), outer_exclusive_binder: ty::INNERMOST }
- }
-
- #[allow(rustc::usage_of_ty_tykind)]
- pub fn for_kind(kind: &ty::TyKind<'_>) -> FlagComputation {
- let mut result = FlagComputation::new();
- result.add_kind(kind);
- result
- }
-
- pub fn for_predicate(binder: ty::Binder<'_, ty::PredicateKind<'_>>) -> FlagComputation {
- let mut result = FlagComputation::new();
- result.add_predicate(binder);
- result
- }
-
- pub fn for_const_kind(kind: &ty::ConstKind<'_>) -> FlagComputation {
- let mut result = FlagComputation::new();
- result.add_const_kind(kind);
- result
- }
-
- pub fn for_clauses(clauses: &[ty::Clause<'_>]) -> FlagComputation {
- let mut result = FlagComputation::new();
- for c in clauses {
- result.add_flags(c.as_predicate().flags());
- result.add_exclusive_binder(c.as_predicate().outer_exclusive_binder());
- }
- result
- }
-
- fn add_flags(&mut self, flags: TypeFlags) {
- self.flags = self.flags | flags;
- }
-
- /// indicates that `self` refers to something at binding level `binder`
- fn add_bound_var(&mut self, binder: ty::DebruijnIndex) {
- let exclusive_binder = binder.shifted_in(1);
- self.add_exclusive_binder(exclusive_binder);
- }
-
- /// indicates that `self` refers to something *inside* binding
- /// level `binder` -- not bound by `binder`, but bound by the next
- /// binder internal to it
- fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) {
- self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder);
- }
-
- /// Adds the flags/depth from a set of types that appear within the current type, but within a
- /// region binder.
- fn bound_computation<T, F>(&mut self, value: ty::Binder<'_, T>, f: F)
- where
- F: FnOnce(&mut Self, T),
- {
- let mut computation = FlagComputation::new();
-
- if !value.bound_vars().is_empty() {
- computation.add_flags(TypeFlags::HAS_BINDER_VARS);
- }
-
- f(&mut computation, value.skip_binder());
-
- self.add_flags(computation.flags);
-
- // The types that contributed to `computation` occurred within
- // a region binder, so subtract one from the region depth
- // within when adding the depth to `self`.
- let outer_exclusive_binder = computation.outer_exclusive_binder;
- if outer_exclusive_binder > ty::INNERMOST {
- self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
- } // otherwise, this binder captures nothing
- }
-
- #[allow(rustc::usage_of_ty_tykind)]
- fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
- match kind {
- &ty::Bool
- | &ty::Char
- | &ty::Int(_)
- | &ty::Float(_)
- | &ty::Uint(_)
- | &ty::Never
- | &ty::Str
- | &ty::Foreign(..) => {}
-
- &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
-
- &ty::Param(_) => {
- self.add_flags(TypeFlags::HAS_TY_PARAM);
- }
-
- &ty::Closure(_, args)
- | &ty::Coroutine(_, args)
- | &ty::CoroutineClosure(_, args)
- | &ty::CoroutineWitness(_, args) => {
- self.add_args(args);
- }
-
- &ty::Bound(debruijn, _) => {
- self.add_bound_var(debruijn);
- self.add_flags(TypeFlags::HAS_TY_BOUND);
- }
-
- &ty::Placeholder(..) => {
- self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
- }
-
- &ty::Infer(infer) => match infer {
- ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
- self.add_flags(TypeFlags::HAS_TY_FRESH)
- }
-
- ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => {
- self.add_flags(TypeFlags::HAS_TY_INFER)
- }
- },
-
- &ty::Adt(_, args) => {
- self.add_args(args);
- }
-
- &ty::Alias(kind, data) => {
- self.add_flags(match kind {
- ty::Projection => TypeFlags::HAS_TY_PROJECTION,
- ty::Weak => TypeFlags::HAS_TY_WEAK,
- ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
- ty::Inherent => TypeFlags::HAS_TY_INHERENT,
- });
-
- self.add_alias_ty(data);
- }
-
- &ty::Dynamic(obj, r, _) => {
- for predicate in obj.iter() {
- self.bound_computation(predicate, |computation, predicate| match predicate {
- ty::ExistentialPredicate::Trait(tr) => computation.add_args(tr.args),
- ty::ExistentialPredicate::Projection(p) => {
- computation.add_existential_projection(&p);
- }
- ty::ExistentialPredicate::AutoTrait(_) => {}
- });
- }
-
- self.add_region(r);
- }
-
- &ty::Array(tt, len) => {
- self.add_ty(tt);
- self.add_const(len);
- }
-
- &ty::Pat(ty, pat) => {
- self.add_ty(ty);
- match *pat {
- ty::PatternKind::Range { start, end } => {
- self.add_const(start);
- self.add_const(end);
- }
- }
- }
-
- &ty::Slice(tt) => self.add_ty(tt),
-
- &ty::RawPtr(ty, _) => {
- self.add_ty(ty);
- }
-
- &ty::Ref(r, ty, _) => {
- self.add_region(r);
- self.add_ty(ty);
- }
-
- &ty::Tuple(types) => {
- self.add_tys(types);
- }
-
- &ty::FnDef(_, args) => {
- self.add_args(args);
- }
-
- &ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| {
- computation.add_tys(sig_tys.inputs_and_output);
- }),
-
- &ty::UnsafeBinder(bound_ty) => {
- self.bound_computation(bound_ty.into(), |computation, ty| {
- computation.add_ty(ty);
- })
- }
- }
- }
-
- fn add_predicate(&mut self, binder: ty::Binder<'_, ty::PredicateKind<'_>>) {
- self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom));
- }
-
- fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
- match atom {
- ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
- self.add_args(trait_pred.trait_ref.args);
- }
- ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
- trait_ref,
- constness: _,
- })) => {
- self.add_args(trait_ref.args);
- }
- ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
- a,
- b,
- ))) => {
- self.add_region(a);
- self.add_region(b);
- }
- ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
- ty,
- region,
- ))) => {
- self.add_ty(ty);
- self.add_region(region);
- }
- ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
- self.add_const(ct);
- self.add_ty(ty);
- }
- ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
- self.add_ty(a);
- self.add_ty(b);
- }
- ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
- self.add_ty(a);
- self.add_ty(b);
- }
- ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
- projection_term,
- term,
- })) => {
- self.add_alias_term(projection_term);
- self.add_term(term);
- }
- ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
- self.add_args(slice::from_ref(&arg));
- }
- ty::PredicateKind::DynCompatible(_def_id) => {}
- ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
- self.add_const(uv);
- }
- ty::PredicateKind::ConstEquate(expected, found) => {
- self.add_const(expected);
- self.add_const(found);
- }
- ty::PredicateKind::Ambiguous => {}
- ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => {
- self.add_alias_term(alias);
- self.add_term(term);
- }
- ty::PredicateKind::AliasRelate(t1, t2, _) => {
- self.add_term(t1);
- self.add_term(t2);
- }
- }
- }
-
- fn add_ty(&mut self, ty: Ty<'_>) {
- self.add_flags(ty.flags());
- self.add_exclusive_binder(ty.outer_exclusive_binder());
- }
-
- fn add_tys(&mut self, tys: &[Ty<'_>]) {
- for &ty in tys {
- self.add_ty(ty);
- }
- }
-
- fn add_region(&mut self, r: ty::Region<'_>) {
- self.add_flags(r.type_flags());
- if let ty::ReBound(debruijn, _) = r.kind() {
- self.add_bound_var(debruijn);
- }
- }
-
- fn add_const(&mut self, c: ty::Const<'_>) {
- self.add_flags(c.flags());
- self.add_exclusive_binder(c.outer_exclusive_binder());
- }
-
- fn add_const_kind(&mut self, c: &ty::ConstKind<'_>) {
- match *c {
- ty::ConstKind::Unevaluated(uv) => {
- self.add_args(uv.args);
- self.add_flags(TypeFlags::HAS_CT_PROJECTION);
- }
- ty::ConstKind::Infer(infer) => match infer {
- InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
- InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
- },
- ty::ConstKind::Bound(debruijn, _) => {
- self.add_bound_var(debruijn);
- self.add_flags(TypeFlags::HAS_CT_BOUND);
- }
- ty::ConstKind::Param(_) => {
- self.add_flags(TypeFlags::HAS_CT_PARAM);
- }
- ty::ConstKind::Placeholder(_) => {
- self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
- }
- ty::ConstKind::Value(cv) => self.add_ty(cv.ty),
- ty::ConstKind::Expr(e) => self.add_args(e.args()),
- ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
- }
- }
-
- fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
- self.add_args(projection.args);
- match projection.term.unpack() {
- ty::TermKind::Ty(ty) => self.add_ty(ty),
- ty::TermKind::Const(ct) => self.add_const(ct),
- }
- }
-
- fn add_alias_ty(&mut self, alias_ty: ty::AliasTy<'_>) {
- self.add_args(alias_ty.args);
- }
-
- fn add_alias_term(&mut self, alias_term: ty::AliasTerm<'_>) {
- self.add_args(alias_term.args);
- }
-
- fn add_args(&mut self, args: &[GenericArg<'_>]) {
- for kind in args {
- match kind.unpack() {
- GenericArgKind::Type(ty) => self.add_ty(ty),
- GenericArgKind::Lifetime(lt) => self.add_region(lt),
- GenericArgKind::Const(ct) => self.add_const(ct),
- }
- }
- }
-
- fn add_term(&mut self, term: ty::Term<'_>) {
- match term.unpack() {
- ty::TermKind::Ty(ty) => self.add_ty(ty),
- ty::TermKind::Const(ct) => self.add_const(ct),
- }
- }
-}
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 8dc73e4..8d6871d 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -278,7 +278,7 @@ pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- let shift_bv = |bv: ty::BoundVar| ty::BoundVar::from_usize(bv.as_usize() + bound_vars);
+ let shift_bv = |bv: ty::BoundVar| bv + bound_vars;
self.replace_escaping_bound_vars_uncached(
value,
FnMutDelegate {
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 9c1ff13..8de64b3 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -11,12 +11,13 @@
use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
use rustc_serialize::{Decodable, Encodable};
use rustc_type_ir::WithCachedTypeInfo;
+use rustc_type_ir::walk::TypeWalker;
use smallvec::SmallVec;
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::{
self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, InlineConstArgs,
- Lift, List, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, VisitorResult,
+ Lift, List, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, VisitorResult,
walk_visitable_list,
};
@@ -297,6 +298,20 @@ pub fn is_non_region_infer(self) -> bool {
GenericArgKind::Const(ct) => ct.is_ct_infer(),
}
}
+
+ /// Iterator that walks `self` and any types reachable from
+ /// `self`, in depth-first order. Note that just walks the types
+ /// that appear in `self`, it does not descend into the fields of
+ /// structs or variants. For example:
+ ///
+ /// ```text
+ /// isize => { isize }
+ /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+ /// [isize] => { [isize], isize }
+ /// ```
+ pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
+ TypeWalker::new(self)
+ }
}
impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for GenericArg<'a> {
@@ -322,6 +337,14 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
}
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ match self.unpack() {
+ GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(),
+ GenericArgKind::Type(ty) => ty.fold_with(folder).into(),
+ GenericArgKind::Const(ct) => ct.fold_with(folder).into(),
+ }
+ }
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
@@ -591,6 +614,27 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
}
}
0 => Ok(self),
+ _ => ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_args(v)),
+ }
+ }
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ // See justification for this behavior in `try_fold_with`.
+ match self.len() {
+ 1 => {
+ let param0 = self[0].fold_with(folder);
+ if param0 == self[0] { self } else { folder.cx().mk_args(&[param0]) }
+ }
+ 2 => {
+ let param0 = self[0].fold_with(folder);
+ let param1 = self[1].fold_with(folder);
+ if param0 == self[0] && param1 == self[1] {
+ self
+ } else {
+ folder.cx().mk_args(&[param0, param1])
+ }
+ }
+ 0 => self,
_ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_args(v)),
}
}
@@ -626,6 +670,22 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
Ok(folder.cx().mk_type_list(&[param0, param1]))
}
}
+ _ => ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)),
+ }
+ }
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ // See comment justifying behavior in `try_fold_with`.
+ match self.len() {
+ 2 => {
+ let param0 = self[0].fold_with(folder);
+ let param1 = self[1].fold_with(folder);
+ if param0 == self[0] && param1 == self[1] {
+ self
+ } else {
+ folder.cx().mk_type_list(&[param0, param1])
+ }
+ }
_ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)),
}
}
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 07f2a60..faad0a8 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -746,7 +746,7 @@ pub fn fn_once_adapter_instance(
let call_once = tcx
.associated_items(fn_once)
.in_definition_order()
- .find(|it| it.kind == ty::AssocKind::Fn)
+ .find(|it| it.is_fn())
.unwrap()
.def_id;
let track_caller =
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 0fd370a..0cf58209 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -7,9 +7,9 @@
use rustc_data_structures::aligned::{Aligned, align_of};
use rustc_data_structures::sync::DynSync;
use rustc_serialize::{Encodable, Encoder};
+use rustc_type_ir::FlagComputation;
-use super::flags::FlagComputation;
-use super::{DebruijnIndex, TypeFlags};
+use super::{DebruijnIndex, TyCtxt, TypeFlags};
use crate::arena::Arena;
/// `List<T>` is a bit like `&[T]`, but with some critical differences.
@@ -299,8 +299,8 @@ const fn empty() -> Self {
}
}
-impl From<FlagComputation> for TypeInfo {
- fn from(computation: FlagComputation) -> TypeInfo {
+impl<'tcx> From<FlagComputation<TyCtxt<'tcx>>> for TypeInfo {
+ fn from(computation: FlagComputation<TyCtxt<'tcx>>) -> TypeInfo {
TypeInfo {
flags: computation.flags,
outer_exclusive_binder: computation.outer_exclusive_binder,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a2b3aca..3698cfb 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -117,7 +117,6 @@
pub mod codec;
pub mod error;
pub mod fast_reject;
-pub mod flags;
pub mod inhabitedness;
pub mod layout;
pub mod normalize_erasing_regions;
@@ -128,7 +127,6 @@
pub mod trait_def;
pub mod util;
pub mod vtable;
-pub mod walk;
mod adt;
mod assoc;
@@ -539,6 +537,13 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
}
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ match self.unpack() {
+ ty::TermKind::Ty(ty) => ty.fold_with(folder).into(),
+ ty::TermKind::Const(ct) => ct.fold_with(folder).into(),
+ }
+ }
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
@@ -1464,7 +1469,7 @@ pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
self.associated_items(id)
.in_definition_order()
- .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
+ .filter(move |item| item.is_fn() && item.defaultness(self).has_value())
}
pub fn repr_options_of_def(self, did: LocalDefId) -> ReprOptions {
@@ -1610,8 +1615,11 @@ pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
/// return-position `impl Trait` from a trait, then provide the source info
/// about where that RPITIT came from.
pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
- if let DefKind::AssocTy = self.def_kind(def_id) {
- self.associated_item(def_id).opt_rpitit_info
+ if let DefKind::AssocTy = self.def_kind(def_id)
+ && let AssocKind::Type { data: AssocTypeData::Rpitit(rpitit_info) } =
+ self.associated_item(def_id).kind
+ {
+ Some(rpitit_info)
} else {
None
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index b56e086..ecd6132 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -113,7 +113,7 @@ impl $crate::ty::ParameterizedOverTcx for $ty {
rustc_span::Span,
rustc_span::Symbol,
rustc_span::def_id::DefPathHash,
- rustc_span::hygiene::SyntaxContextDataNonRecursive,
+ rustc_span::hygiene::SyntaxContextKey,
rustc_span::Ident,
rustc_type_ir::Variance,
rustc_hir::Attribute,
diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs
index 4cad1ab..758adc4 100644
--- a/compiler/rustc_middle/src/ty/pattern.rs
+++ b/compiler/rustc_middle/src/ty/pattern.rs
@@ -1,14 +1,40 @@
use std::fmt;
use rustc_data_structures::intern::Interned;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use rustc_macros::HashStable;
+use rustc_type_ir::ir_print::IrPrint;
+use rustc_type_ir::{
+ FlagComputation, Flags, {self as ir},
+};
+use super::TyCtxt;
use crate::ty;
+pub type PatternKind<'tcx> = ir::PatternKind<TyCtxt<'tcx>>;
+
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>);
+impl<'tcx> Flags for Pattern<'tcx> {
+ fn flags(&self) -> rustc_type_ir::TypeFlags {
+ match &**self {
+ ty::PatternKind::Range { start, end } => {
+ FlagComputation::for_const_kind(&start.kind()).flags
+ | FlagComputation::for_const_kind(&end.kind()).flags
+ }
+ }
+ }
+
+ fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
+ match &**self {
+ ty::PatternKind::Range { start, end } => {
+ start.outer_exclusive_binder().max(end.outer_exclusive_binder())
+ }
+ }
+ }
+}
+
impl<'tcx> std::ops::Deref for Pattern<'tcx> {
type Target = PatternKind<'tcx>;
@@ -23,9 +49,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-impl<'tcx> fmt::Debug for PatternKind<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match *self {
+impl<'tcx> IrPrint<PatternKind<'tcx>> for TyCtxt<'tcx> {
+ fn print(t: &PatternKind<'tcx>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *t {
PatternKind::Range { start, end } => {
write!(f, "{start}")?;
@@ -53,10 +79,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
}
+
+ fn print_debug(t: &PatternKind<'tcx>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Self::print(t, fmt)
+ }
}
-#[derive(Clone, PartialEq, Eq, Hash)]
-#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
-pub enum PatternKind<'tcx> {
- Range { start: ty::Const<'tcx>, end: ty::Const<'tcx> },
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Pattern<'tcx> {
+ type Kind = PatternKind<'tcx>;
+ fn kind(self) -> Self::Kind {
+ *self
+ }
}
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 5904dea..9172c5d 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -382,7 +382,7 @@ pub fn shrunk_instance_name<'tcx>(
return (s, None);
}
- let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None);
+ let path = tcx.output_filenames(()).temp_path_for_diagnostic("long-type.txt");
let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
(shrunk, written_to_path)
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 667cc5c..d739218 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -620,7 +620,7 @@ fn try_print_visible_def_path_recur(
// the children of the visible parent (as was done when computing
// `visible_parent_map`), looking for the specific child we currently have and then
// have access to the re-exported name.
- DefPathData::TypeNs(Some(ref mut name)) if Some(visible_parent) != actual_parent => {
+ DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
// Item might be re-exported several times, but filter for the one
// that's public and whose identifier isn't `_`.
let reexport = self
@@ -641,7 +641,7 @@ fn try_print_visible_def_path_recur(
}
// Re-exported `extern crate` (#43189).
DefPathData::CrateRoot => {
- data = DefPathData::TypeNs(Some(self.tcx().crate_name(def_id.krate)));
+ data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate));
}
_ => {}
}
@@ -1214,7 +1214,7 @@ fn pretty_print_opaque_impl_type(
&& assoc
.trait_container(tcx)
.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
- && assoc.name == rustc_span::sym::Return
+ && assoc.opt_name() == Some(rustc_span::sym::Return)
{
if let ty::Coroutine(_, args) = args.type_at(0).kind() {
let return_ty = args.as_coroutine().return_ty();
@@ -1237,7 +1237,7 @@ fn pretty_print_opaque_impl_type(
p!(", ");
}
- p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name));
+ p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name()));
match term.unpack() {
TermKind::Ty(ty) => p!(print(ty)),
@@ -3291,7 +3291,7 @@ macro_rules! define_print_and_forward_display {
}
ty::ExistentialProjection<'tcx> {
- let name = cx.tcx().associated_item(self.def_id).name;
+ let name = cx.tcx().associated_item(self.def_id).name();
// The args don't contain the self ty (as it has been erased) but the corresp.
// generics do as the trait always has a self ty param. We need to offset.
let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..];
diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs
index ce4208f..561f841 100644
--- a/compiler/rustc_middle/src/ty/significant_drop_order.rs
+++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs
@@ -26,7 +26,7 @@ fn true_significant_drop_ty<'tcx>(
name_rev.push(tcx.crate_name(did.krate));
}
rustc_hir::definitions::DefPathData::TypeNs(symbol) => {
- name_rev.push(symbol.unwrap());
+ name_rev.push(symbol);
}
_ => return None,
}
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 798ef35..2686166 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -6,20 +6,19 @@
use std::fmt::{self, Debug};
use rustc_abi::TyAndLayout;
-use rustc_ast::InlineAsmTemplatePiece;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::LocalDefId;
-use rustc_span::Span;
use rustc_span::source_map::Spanned;
-use rustc_type_ir::{ConstKind, VisitorResult, try_visit};
+use rustc_type_ir::{ConstKind, TypeFolder, VisitorResult, try_visit};
use super::print::PrettyPrinter;
use super::{GenericArg, GenericArgKind, Pattern, Region};
+use crate::infer::canonical::CanonicalVarInfos;
use crate::mir::PlaceElem;
use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths};
use crate::ty::{
- self, FallibleTypeFolder, InferConst, Lift, Term, TermKind, Ty, TyCtxt, TypeFoldable,
- TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ self, FallibleTypeFolder, Lift, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
impl fmt::Debug for ty::TraitDef {
@@ -61,6 +60,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
+impl<'tcx> fmt::Debug for ty::adjustment::PatAdjustment<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{} -> {:?}", self.source, self.kind)
+ }
+}
+
impl fmt::Debug for ty::BoundRegionKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
@@ -271,6 +276,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
crate::ty::AssocKind,
crate::ty::BoundRegion,
crate::ty::BoundVar,
+ crate::ty::InferConst,
crate::ty::Placeholder<crate::ty::BoundRegion>,
crate::ty::Placeholder<crate::ty::BoundTy>,
crate::ty::Placeholder<ty::BoundVar>,
@@ -337,24 +343,6 @@ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Resul
}
}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_poly_existential_predicates(v))
- }
-}
-
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v))
- }
-}
-
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Pattern<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
@@ -363,6 +351,11 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
let pat = (*self).clone().try_fold_with(folder)?;
Ok(if pat == *self { self } else { folder.cx().mk_pat(pat) })
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ let pat = (*self).clone().fold_with(folder);
+ if pat == *self { self } else { folder.cx().mk_pat(pat) }
+ }
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Pattern<'tcx> {
@@ -378,6 +371,10 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
) -> Result<Self, F::Error> {
folder.try_fold_ty(self)
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ folder.fold_ty(self)
+ }
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
@@ -436,6 +433,45 @@ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
Ok(if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) })
}
+
+ fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ let kind = match *self.kind() {
+ ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.fold_with(folder), mutbl),
+ ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)),
+ ty::Slice(typ) => ty::Slice(typ.fold_with(folder)),
+ ty::Adt(tid, args) => ty::Adt(tid, args.fold_with(folder)),
+ ty::Dynamic(trait_ty, region, representation) => {
+ ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder), representation)
+ }
+ ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)),
+ ty::FnDef(def_id, args) => ty::FnDef(def_id, args.fold_with(folder)),
+ ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.fold_with(folder), hdr),
+ ty::UnsafeBinder(f) => ty::UnsafeBinder(f.fold_with(folder)),
+ ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl),
+ ty::Coroutine(did, args) => ty::Coroutine(did, args.fold_with(folder)),
+ ty::CoroutineWitness(did, args) => ty::CoroutineWitness(did, args.fold_with(folder)),
+ ty::Closure(did, args) => ty::Closure(did, args.fold_with(folder)),
+ ty::CoroutineClosure(did, args) => ty::CoroutineClosure(did, args.fold_with(folder)),
+ ty::Alias(kind, data) => ty::Alias(kind, data.fold_with(folder)),
+ ty::Pat(ty, pat) => ty::Pat(ty.fold_with(folder), pat.fold_with(folder)),
+
+ ty::Bool
+ | ty::Char
+ | ty::Str
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Error(_)
+ | ty::Infer(_)
+ | ty::Param(..)
+ | ty::Bound(..)
+ | ty::Placeholder(..)
+ | ty::Never
+ | ty::Foreign(..) => return self,
+ };
+
+ if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) }
+ }
}
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
@@ -496,6 +532,10 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
) -> Result<Self, F::Error> {
folder.try_fold_region(self)
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ folder.fold_region(self)
+ }
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
@@ -511,6 +551,10 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
) -> Result<Self, F::Error> {
folder.try_fold_predicate(self)
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ folder.fold_predicate(self)
+ }
}
// FIXME(clause): This is wonky
@@ -521,6 +565,10 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
) -> Result<Self, F::Error> {
Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ folder.fold_predicate(self.as_predicate()).expect_clause()
+ }
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
@@ -543,6 +591,11 @@ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
let new = self.kind().try_fold_with(folder)?;
Ok(folder.cx().reuse_or_mk_predicate(self, new))
}
+
+ fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ let new = self.kind().fold_with(folder);
+ folder.cx().reuse_or_mk_predicate(self, new)
+ }
}
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
@@ -563,15 +616,6 @@ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::
}
}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
- }
-}
-
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
@@ -579,6 +623,10 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
) -> Result<Self, F::Error> {
folder.try_fold_const(self)
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ folder.fold_const(self)
+ }
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
@@ -606,6 +654,20 @@ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
};
if kind != self.kind() { Ok(folder.cx().mk_ct_from_kind(kind)) } else { Ok(self) }
}
+
+ fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ let kind = match self.kind() {
+ ConstKind::Param(p) => ConstKind::Param(p.fold_with(folder)),
+ ConstKind::Infer(i) => ConstKind::Infer(i.fold_with(folder)),
+ ConstKind::Bound(d, b) => ConstKind::Bound(d.fold_with(folder), b.fold_with(folder)),
+ ConstKind::Placeholder(p) => ConstKind::Placeholder(p.fold_with(folder)),
+ ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.fold_with(folder)),
+ ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)),
+ ConstKind::Error(e) => ConstKind::Error(e.fold_with(folder)),
+ ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)),
+ };
+ if kind != self.kind() { folder.cx().mk_ct_from_kind(kind) } else { self }
+ }
}
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
@@ -639,20 +701,9 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
) -> Result<Self, F::Error> {
Ok(self)
}
-}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- _folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(self)
- }
-}
-
-impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst {
- fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Result {
- V::Result::output()
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, _folder: &mut F) -> Self {
+ self
}
}
@@ -683,23 +734,9 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
span: self.span.try_fold_with(folder)?,
})
}
-}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- _folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(self)
- }
-}
-
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- _folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(self)
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ Spanned { node: self.node.fold_with(folder), span: self.span.fold_with(folder) }
}
}
@@ -710,13 +747,37 @@ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
) -> Result<Self, F::Error> {
Ok(self)
}
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, _folder: &mut F) -> Self {
+ self
+ }
}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v))
+macro_rules! list_fold {
+ ($($ty:ty : $mk:ident),+ $(,)?) => {
+ $(
+ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for $ty {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ ty::util::try_fold_list(self, folder, |tcx, v| tcx.$mk(v))
+ }
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Self {
+ ty::util::fold_list(self, folder, |tcx, v| tcx.$mk(v))
+ }
+ }
+ )*
}
}
+
+list_fold! {
+ ty::Clauses<'tcx> : mk_clauses,
+ &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
+ &'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
+ CanonicalVarInfos<'tcx> : mk_canonical_var_infos,
+}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 27ee363..301ae60 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -16,6 +16,7 @@
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension};
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use rustc_type_ir::TyKind::*;
+use rustc_type_ir::walk::TypeWalker;
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, TypeVisitableExt, elaborate};
use tracing::instrument;
use ty::util::{AsyncDropGlueMorphology, IntTypeExt};
@@ -734,7 +735,7 @@ pub fn new_dynamic(
.map(|principal| {
tcx.associated_items(principal.def_id())
.in_definition_order()
- .filter(|item| item.kind == ty::AssocKind::Type)
+ .filter(|item| item.is_type())
.filter(|item| !item.is_impl_trait_in_trait())
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.count()
@@ -1872,14 +1873,14 @@ pub fn from_coroutine_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) ->
/// Fast path helper for testing if a type is `Sized`.
///
- /// Returning true means the type is known to be sized. Returning
- /// `false` means nothing -- could be sized, might not be.
+ /// Returning true means the type is known to implement `Sized`. Returning `false` means
+ /// nothing -- could be sized, might not be.
///
- /// Note that we could never rely on the fact that a type such as `[_]` is
- /// trivially `!Sized` because we could be in a type environment with a
- /// bound such as `[_]: Copy`. A function with such a bound obviously never
- /// can be called, but that doesn't mean it shouldn't typecheck. This is why
- /// this method doesn't return `Option<bool>`.
+ /// Note that we could never rely on the fact that a type such as `[_]` is trivially `!Sized`
+ /// because we could be in a type environment with a bound such as `[_]: Copy`. A function with
+ /// such a bound obviously never can be called, but that doesn't mean it shouldn't typecheck.
+ /// This is why this method doesn't return `Option<bool>`.
+ #[instrument(skip(tcx), level = "debug")]
pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind() {
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
@@ -2029,6 +2030,20 @@ pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool {
pub fn is_known_rigid(self) -> bool {
self.kind().is_known_rigid()
}
+
+ /// Iterator that walks `self` and any types reachable from
+ /// `self`, in depth-first order. Note that just walks the types
+ /// that appear in `self`, it does not descend into the fields of
+ /// structs or variants. For example:
+ ///
+ /// ```text
+ /// isize => { isize }
+ /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+ /// [isize] => { [isize], isize }
+ /// ```
+ pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
+ TypeWalker::new(self.into())
+ }
}
impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 90c6ef6..4c5c669 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -77,8 +77,8 @@ pub struct TypeckResults<'tcx> {
/// to a form valid in all Editions, either as a lint diagnostic or hard error.
rust_2024_migration_desugared_pats: ItemLocalMap<Rust2024IncompatiblePatInfo>,
- /// Stores the types which were implicitly dereferenced in pattern binding modes
- /// for later usage in THIR lowering. For example,
+ /// Stores the types which were implicitly dereferenced in pattern binding modes or deref
+ /// patterns for later usage in THIR lowering. For example,
///
/// ```
/// match &&Some(5i32) {
@@ -86,11 +86,20 @@ pub struct TypeckResults<'tcx> {
/// _ => {},
/// }
/// ```
- /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
+ /// leads to a `vec![&&Option<i32>, &Option<i32>]` and
+ ///
+ /// ```
+ /// #![feature(deref_patterns)]
+ /// match &Box::new(Some(5i32)) {
+ /// Some(n) => {},
+ /// _ => {},
+ /// }
+ /// ```
+ /// leads to a `vec![&Box<Option<i32>>, Box<Option<i32>>]`. Empty vectors are not stored.
///
/// See:
/// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
- pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
+ pat_adjustments: ItemLocalMap<Vec<ty::adjustment::PatAdjustment<'tcx>>>,
/// Set of reference patterns that match against a match-ergonomics inserted reference
/// (as opposed to against a reference in the scrutinee type).
@@ -403,11 +412,15 @@ pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMod
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
}
- pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+ pub fn pat_adjustments(
+ &self,
+ ) -> LocalTableInContext<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
}
- pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+ pub fn pat_adjustments_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 857b462..08cee11 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -819,7 +819,7 @@ pub fn def_descr(self, def_id: DefId) -> &'static str {
/// Get an English description for the item's kind.
pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str {
match def_kind {
- DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method",
+ DefKind::AssocFn if self.associated_item(def_id).is_method() => "method",
DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => {
match coroutine_kind {
hir::CoroutineKind::Desugared(
@@ -873,7 +873,7 @@ pub fn def_descr_article(self, def_id: DefId) -> &'static str {
/// Gets an English article for the [`TyCtxt::def_kind_descr`].
pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str {
match def_kind {
- DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a",
+ DefKind::AssocFn if self.associated_item(def_id).is_method() => "a",
DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => {
match coroutine_kind {
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, ..) => "an",
@@ -1647,6 +1647,42 @@ pub fn fold_list<'tcx, F, L, T>(
list: L,
folder: &mut F,
intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> L,
+) -> L
+where
+ F: TypeFolder<TyCtxt<'tcx>>,
+ L: AsRef<[T]>,
+ T: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy,
+{
+ let slice = list.as_ref();
+ let mut iter = slice.iter().copied();
+ // Look for the first element that changed
+ match iter.by_ref().enumerate().find_map(|(i, t)| {
+ let new_t = t.fold_with(folder);
+ if new_t != t { Some((i, new_t)) } else { None }
+ }) {
+ Some((i, new_t)) => {
+ // An element changed, prepare to intern the resulting list
+ let mut new_list = SmallVec::<[_; 8]>::with_capacity(slice.len());
+ new_list.extend_from_slice(&slice[..i]);
+ new_list.push(new_t);
+ for t in iter {
+ new_list.push(t.fold_with(folder))
+ }
+ intern(folder.cx(), &new_list)
+ }
+ None => list,
+ }
+}
+
+/// Does the equivalent of
+/// ```ignore (illustrative)
+/// let v = self.iter().map(|p| p.try_fold_with(folder)).collect::<SmallVec<[_; 8]>>();
+/// folder.tcx().intern_*(&v)
+/// ```
+pub fn try_fold_list<'tcx, F, L, T>(
+ list: L,
+ folder: &mut F,
+ intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> L,
) -> Result<L, F::Error>
where
F: FallibleTypeFolder<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index b341b30..44c7b6a 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -231,9 +231,7 @@ pub fn max_universe(self) -> ty::UniverseIndex {
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
fn visit_ty(&mut self, t: Ty<'tcx>) {
if let ty::Placeholder(placeholder) = t.kind() {
- self.max_universe = ty::UniverseIndex::from_u32(
- self.max_universe.as_u32().max(placeholder.universe.as_u32()),
- );
+ self.max_universe = self.max_universe.max(placeholder.universe);
}
t.super_visit_with(self)
@@ -241,9 +239,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) {
fn visit_const(&mut self, c: ty::consts::Const<'tcx>) {
if let ty::ConstKind::Placeholder(placeholder) = c.kind() {
- self.max_universe = ty::UniverseIndex::from_u32(
- self.max_universe.as_u32().max(placeholder.universe.as_u32()),
- );
+ self.max_universe = self.max_universe.max(placeholder.universe);
}
c.super_visit_with(self)
@@ -251,9 +247,7 @@ fn visit_const(&mut self, c: ty::consts::Const<'tcx>) {
fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::RePlaceholder(placeholder) = r.kind() {
- self.max_universe = ty::UniverseIndex::from_u32(
- self.max_universe.as_u32().max(placeholder.universe.as_u32()),
- );
+ self.max_universe = self.max_universe.max(placeholder.universe);
}
}
}
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
deleted file mode 100644
index a23316a..0000000
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ /dev/null
@@ -1,217 +0,0 @@
-//! An iterator over the type substructure.
-//! WARNING: this does not keep track of the region depth.
-
-use rustc_data_structures::sso::SsoHashSet;
-use smallvec::{SmallVec, smallvec};
-use tracing::debug;
-
-use crate::ty::{self, GenericArg, GenericArgKind, Ty};
-
-// The TypeWalker's stack is hot enough that it's worth going to some effort to
-// avoid heap allocations.
-type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
-
-pub struct TypeWalker<'tcx> {
- stack: TypeWalkerStack<'tcx>,
- last_subtree: usize,
- pub visited: SsoHashSet<GenericArg<'tcx>>,
-}
-
-/// An iterator for walking the type tree.
-///
-/// It's very easy to produce a deeply
-/// nested type tree with a lot of
-/// identical subtrees. In order to work efficiently
-/// in this situation walker only visits each type once.
-/// It maintains a set of visited types and
-/// skips any types that are already there.
-impl<'tcx> TypeWalker<'tcx> {
- pub fn new(root: GenericArg<'tcx>) -> Self {
- Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() }
- }
-
- /// Skips the subtree corresponding to the last type
- /// returned by `next()`.
- ///
- /// Example: Imagine you are walking `Foo<Bar<i32>, usize>`.
- ///
- /// ```ignore (illustrative)
- /// let mut iter: TypeWalker = ...;
- /// iter.next(); // yields Foo
- /// iter.next(); // yields Bar<i32>
- /// iter.skip_current_subtree(); // skips i32
- /// iter.next(); // yields usize
- /// ```
- pub fn skip_current_subtree(&mut self) {
- self.stack.truncate(self.last_subtree);
- }
-}
-
-impl<'tcx> Iterator for TypeWalker<'tcx> {
- type Item = GenericArg<'tcx>;
-
- fn next(&mut self) -> Option<GenericArg<'tcx>> {
- debug!("next(): stack={:?}", self.stack);
- loop {
- let next = self.stack.pop()?;
- self.last_subtree = self.stack.len();
- if self.visited.insert(next) {
- push_inner(&mut self.stack, next);
- debug!("next: stack={:?}", self.stack);
- return Some(next);
- }
- }
- }
-}
-
-impl<'tcx> GenericArg<'tcx> {
- /// Iterator that walks `self` and any types reachable from
- /// `self`, in depth-first order. Note that just walks the types
- /// that appear in `self`, it does not descend into the fields of
- /// structs or variants. For example:
- ///
- /// ```text
- /// isize => { isize }
- /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
- /// [isize] => { [isize], isize }
- /// ```
- pub fn walk(self) -> TypeWalker<'tcx> {
- TypeWalker::new(self)
- }
-}
-
-impl<'tcx> Ty<'tcx> {
- /// Iterator that walks `self` and any types reachable from
- /// `self`, in depth-first order. Note that just walks the types
- /// that appear in `self`, it does not descend into the fields of
- /// structs or variants. For example:
- ///
- /// ```text
- /// isize => { isize }
- /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
- /// [isize] => { [isize], isize }
- /// ```
- pub fn walk(self) -> TypeWalker<'tcx> {
- TypeWalker::new(self.into())
- }
-}
-
-impl<'tcx> ty::Const<'tcx> {
- /// Iterator that walks `self` and any types reachable from
- /// `self`, in depth-first order. Note that just walks the types
- /// that appear in `self`, it does not descend into the fields of
- /// structs or variants. For example:
- ///
- /// ```text
- /// isize => { isize }
- /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
- /// [isize] => { [isize], isize }
- /// ```
- pub fn walk(self) -> TypeWalker<'tcx> {
- TypeWalker::new(self.into())
- }
-}
-
-/// We push `GenericArg`s on the stack in reverse order so as to
-/// maintain a pre-order traversal. As of the time of this
-/// writing, the fact that the traversal is pre-order is not
-/// known to be significant to any code, but it seems like the
-/// natural order one would expect (basically, the order of the
-/// types as they are written).
-fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) {
- match parent.unpack() {
- GenericArgKind::Type(parent_ty) => match *parent_ty.kind() {
- ty::Bool
- | ty::Char
- | ty::Int(_)
- | ty::Uint(_)
- | ty::Float(_)
- | ty::Str
- | ty::Infer(_)
- | ty::Param(_)
- | ty::Never
- | ty::Error(_)
- | ty::Placeholder(..)
- | ty::Bound(..)
- | ty::Foreign(..) => {}
-
- ty::Pat(ty, pat) => {
- match *pat {
- ty::PatternKind::Range { start, end } => {
- stack.push(end.into());
- stack.push(start.into());
- }
- }
- stack.push(ty.into());
- }
- ty::Array(ty, len) => {
- stack.push(len.into());
- stack.push(ty.into());
- }
- ty::Slice(ty) => {
- stack.push(ty.into());
- }
- ty::RawPtr(ty, _) => {
- stack.push(ty.into());
- }
- ty::Ref(lt, ty, _) => {
- stack.push(ty.into());
- stack.push(lt.into());
- }
- ty::Alias(_, data) => {
- stack.extend(data.args.iter().rev());
- }
- ty::Dynamic(obj, lt, _) => {
- stack.push(lt.into());
- stack.extend(obj.iter().rev().flat_map(|predicate| {
- let (args, opt_ty) = match predicate.skip_binder() {
- ty::ExistentialPredicate::Trait(tr) => (tr.args, None),
- ty::ExistentialPredicate::Projection(p) => (p.args, Some(p.term)),
- ty::ExistentialPredicate::AutoTrait(_) =>
- // Empty iterator
- {
- (ty::GenericArgs::empty(), None)
- }
- };
-
- args.iter().rev().chain(opt_ty.map(|term| match term.unpack() {
- ty::TermKind::Ty(ty) => ty.into(),
- ty::TermKind::Const(ct) => ct.into(),
- }))
- }));
- }
- ty::Adt(_, args)
- | ty::Closure(_, args)
- | ty::CoroutineClosure(_, args)
- | ty::Coroutine(_, args)
- | ty::CoroutineWitness(_, args)
- | ty::FnDef(_, args) => {
- stack.extend(args.iter().rev());
- }
- ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)),
- ty::FnPtr(sig_tys, _hdr) => {
- stack.extend(
- sig_tys.skip_binder().inputs_and_output.iter().rev().map(|ty| ty.into()),
- );
- }
- ty::UnsafeBinder(bound_ty) => {
- stack.push(bound_ty.skip_binder().into());
- }
- },
- GenericArgKind::Lifetime(_) => {}
- GenericArgKind::Const(parent_ct) => match parent_ct.kind() {
- ty::ConstKind::Infer(_)
- | ty::ConstKind::Param(_)
- | ty::ConstKind::Placeholder(_)
- | ty::ConstKind::Bound(..)
- | ty::ConstKind::Error(_) => {}
-
- ty::ConstKind::Value(cv) => stack.push(cv.ty.into()),
-
- ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
- ty::ConstKind::Unevaluated(ct) => {
- stack.extend(ct.args.iter().rev());
- }
- },
- }
-}
diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs
index bfc1681..902a6e7 100644
--- a/compiler/rustc_mir_build/src/builder/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs
@@ -103,8 +103,9 @@ fn parse_attribute(attr: &Attribute) -> MirPhase {
let mut dialect: Option<String> = None;
let mut phase: Option<String> = None;
+ // Not handling errors properly for this internal attribute; will just abort on errors.
for nested in meta_items {
- let name = nested.name_or_empty();
+ let name = nested.name().unwrap();
let value = nested.value_str().unwrap().as_str().to_string();
match name.as_str() {
"dialect" => {
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index 9670c17..d66b38c 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -101,18 +101,21 @@ pub(super) fn for_pattern(
place_builder = resolved;
}
- // Only add the OpaqueCast projection if the given place is an opaque type and the
- // expected type from the pattern is not.
- let may_need_cast = match place_builder.base() {
- PlaceBase::Local(local) => {
- let ty =
- Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx).ty;
- ty != pattern.ty && ty.has_opaque_types()
+ if !cx.tcx.next_trait_solver_globally() {
+ // Only add the OpaqueCast projection if the given place is an opaque type and the
+ // expected type from the pattern is not.
+ let may_need_cast = match place_builder.base() {
+ PlaceBase::Local(local) => {
+ let ty =
+ Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx)
+ .ty;
+ ty != pattern.ty && ty.has_opaque_types()
+ }
+ _ => true,
+ };
+ if may_need_cast {
+ place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
}
- _ => true,
- };
- if may_need_cast {
- place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
}
let place = place_builder.try_to_place(cx);
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index d1f9d4c..73cc3c8 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -140,8 +140,8 @@ pub(super) fn perform_test(
let success_block = target_block(TestBranch::Success);
let fail_block = target_block(TestBranch::Failure);
- let expect_ty = value.ty();
- let expect = self.literal_operand(test.span, value);
+ let mut expect_ty = value.ty();
+ let mut expect = self.literal_operand(test.span, value);
let mut place = place;
let mut block = block;
@@ -174,6 +174,31 @@ pub(super) fn perform_test(
place = ref_str;
ty = ref_str_ty;
}
+ &ty::Pat(base, _) => {
+ assert_eq!(ty, value.ty());
+ assert!(base.is_trivially_pure_clone_copy());
+
+ let transmuted_place = self.temp(base, test.span);
+ self.cfg.push_assign(
+ block,
+ self.source_info(scrutinee_span),
+ transmuted_place,
+ Rvalue::Cast(CastKind::Transmute, Operand::Copy(place), base),
+ );
+
+ let transmuted_expect = self.temp(base, test.span);
+ self.cfg.push_assign(
+ block,
+ self.source_info(test.span),
+ transmuted_expect,
+ Rvalue::Cast(CastKind::Transmute, expect, base),
+ );
+
+ place = transmuted_place;
+ expect = Operand::Copy(transmuted_expect);
+ ty = base;
+ expect_ty = base;
+ }
_ => {}
}
@@ -715,7 +740,7 @@ fn trait_method<'tcx>(
let item = tcx
.associated_items(trait_def_id)
.filter_by_name_unhygienic(method_name)
- .find(|item| item.kind == ty::AssocKind::Fn)
+ .find(|item| item.is_fn())
.expect("trait method not found");
let method_ty = Ty::new_fn_def(tcx, item.def_id, args);
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index 8ca9ab5..59a52ae 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -485,7 +485,7 @@ fn construct_fn<'tcx>(
};
if let Some(custom_mir_attr) =
- tcx.hir_attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
+ tcx.hir_attrs(fn_id).iter().find(|attr| attr.has_name(sym::custom_mir))
{
return custom::build_custom_mir(
tcx,
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 0e16f87..ae09db5 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -2,7 +2,7 @@
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
- MultiSpan, SubdiagMessageOp, Subdiagnostic, pluralize,
+ MultiSpan, Subdiagnostic, pluralize,
};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{self, Ty};
@@ -546,11 +546,7 @@ pub(crate) struct UnsafeNotInheritedLintNote {
}
impl Subdiagnostic for UnsafeNotInheritedLintNote {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body);
let body_start = self.body_span.shrink_to_lo();
let body_end = self.body_span.shrink_to_hi();
@@ -1031,11 +1027,7 @@ pub(crate) struct Variant {
}
impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("ty", self.ty);
let mut spans = MultiSpan::from(self.adt_def_span);
@@ -1117,11 +1109,7 @@ pub(crate) struct Rust2024IncompatiblePatSugg {
}
impl Subdiagnostic for Rust2024IncompatiblePatSugg {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
// Format and emit explanatory notes about default binding modes. Reversing the spans' order
// means if we have nested spans, the innermost ones will be visited first.
for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() {
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index a25697b..8e96d46 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -3,7 +3,6 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 31e22e6..fde2341 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -191,7 +191,7 @@ fn apply_adjustment(
let pointer_target = ExprKind::Field {
lhs: self.thir.exprs.push(expr),
variant_index: FIRST_VARIANT,
- name: FieldIdx::from(0u32),
+ name: FieldIdx::ZERO,
};
let arg = Expr { temp_lifetime, ty: pin_ty, span, kind: pointer_target };
let arg = self.thir.exprs.push(arg);
@@ -226,7 +226,7 @@ fn apply_adjustment(
adt_def: self.tcx.adt_def(pin_did),
variant_index: FIRST_VARIANT,
args,
- fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
+ fields: Box::new([FieldExpr { name: FieldIdx::ZERO, expr }]),
user_ty: None,
base: AdtExprBase::None,
}));
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index b3daed8..2f593b9 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -113,7 +113,7 @@ fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
apply_adjustments: tcx
.hir_attrs(hir_id)
.iter()
- .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
+ .all(|attr| !attr.has_name(rustc_span::sym::custom_mir)),
}
}
diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs
index bd7787b..12c457f 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/migration.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs
@@ -4,8 +4,7 @@
use rustc_errors::MultiSpan;
use rustc_hir::{BindingMode, ByRef, HirId, Mutability};
use rustc_lint as lint;
-use rustc_middle::span_bug;
-use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, Ty, TyCtxt};
+use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt};
use rustc_span::{Ident, Span};
use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg};
@@ -87,19 +86,18 @@ pub(super) fn emit<'tcx>(self, tcx: TyCtxt<'tcx>, pat_id: HirId) {
}
/// Tracks when we're lowering a pattern that implicitly dereferences the scrutinee.
- /// This should only be called when the pattern type adjustments list `adjustments` is
- /// non-empty. Returns the prior default binding mode; this should be followed by a call to
- /// [`PatMigration::leave_ref`] to restore it when we leave the pattern.
+ /// This should only be called when the pattern type adjustments list `adjustments` contains an
+ /// implicit deref of a reference type. Returns the prior default binding mode; this should be
+ /// followed by a call to [`PatMigration::leave_ref`] to restore it when we leave the pattern.
pub(super) fn visit_implicit_derefs<'tcx>(
&mut self,
pat_span: Span,
- adjustments: &[Ty<'tcx>],
+ adjustments: &[ty::adjustment::PatAdjustment<'tcx>],
) -> Option<(Span, Mutability)> {
- let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| {
- let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
- span_bug!(pat_span, "pattern implicitly dereferences a non-ref type");
- };
- mutbl
+ // Implicitly dereferencing references changes the default binding mode, but implicit derefs
+ // of smart pointers do not. Thus, we only consider implicit derefs of reference types.
+ let implicit_deref_mutbls = adjustments.iter().filter_map(|adjust| {
+ if let &ty::Ref(_, _, mutbl) = adjust.source.kind() { Some(mutbl) } else { None }
});
if !self.info.suggest_eliding_modes {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 73d60cf..8f058ef 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -18,6 +18,7 @@
use rustc_middle::thir::{
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
};
+use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug};
@@ -63,13 +64,15 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
- let adjustments: &[Ty<'tcx>] =
+ let adjustments: &[PatAdjustment<'tcx>] =
self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
// Track the default binding mode for the Rust 2024 migration suggestion.
+ // Implicitly dereferencing references changes the default binding mode, but implicit deref
+ // patterns do not. Only track binding mode changes if a ref type is in the adjustments.
let mut opt_old_mode_span = None;
if let Some(s) = &mut self.rust_2024_migration
- && !adjustments.is_empty()
+ && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
{
opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments);
}
@@ -102,17 +105,23 @@ fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
_ => self.lower_pattern_unadjusted(pat),
};
- let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| {
- debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty);
- Box::new(Pat {
- span: thir_pat.span,
- ty: *ref_ty,
- kind: PatKind::Deref { subpattern: thir_pat },
- })
+ let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| {
+ debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust);
+ let span = thir_pat.span;
+ let kind = match adjust.kind {
+ PatAdjust::BuiltinDeref => PatKind::Deref { subpattern: thir_pat },
+ PatAdjust::OverloadedDeref => {
+ let mutable = self.typeck_results.pat_has_ref_mut_binding(pat);
+ let mutability =
+ if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
+ PatKind::DerefPattern { subpattern: thir_pat, mutability }
+ }
+ };
+ Box::new(Pat { span, ty: adjust.source, kind })
});
if let Some(s) = &mut self.rust_2024_migration
- && !adjustments.is_empty()
+ && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref)
{
s.leave_ref(opt_old_mode_span);
}
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 448fad2..95f488a 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -109,27 +109,29 @@ fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result<Self, ()> {
.flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter()));
for attr in rustc_mir_attrs {
- let attr_result = if attr.has_name(sym::borrowck_graphviz_postflow) {
- Self::set_field(&mut ret.basename_and_suffix, tcx, &attr, |s| {
- let path = PathBuf::from(s.to_string());
- match path.file_name() {
- Some(_) => Ok(path),
- None => {
- tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() });
+ let attr_result = match attr.name() {
+ Some(name @ sym::borrowck_graphviz_postflow) => {
+ Self::set_field(&mut ret.basename_and_suffix, tcx, name, &attr, |s| {
+ let path = PathBuf::from(s.to_string());
+ match path.file_name() {
+ Some(_) => Ok(path),
+ None => {
+ tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() });
+ Err(())
+ }
+ }
+ })
+ }
+ Some(name @ sym::borrowck_graphviz_format) => {
+ Self::set_field(&mut ret.formatter, tcx, name, &attr, |s| match s {
+ sym::two_phase => Ok(s),
+ _ => {
+ tcx.dcx().emit_err(UnknownFormatter { span: attr.span() });
Err(())
}
- }
- })
- } else if attr.has_name(sym::borrowck_graphviz_format) {
- Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s {
- sym::gen_kill | sym::two_phase => Ok(s),
- _ => {
- tcx.dcx().emit_err(UnknownFormatter { span: attr.span() });
- Err(())
- }
- })
- } else {
- Ok(())
+ })
+ }
+ _ => Ok(()),
};
result = result.and(attr_result);
@@ -141,12 +143,12 @@ fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result<Self, ()> {
fn set_field<T>(
field: &mut Option<T>,
tcx: TyCtxt<'_>,
+ name: Symbol,
attr: &ast::MetaItemInner,
mapper: impl FnOnce(Symbol) -> Result<T, ()>,
) -> Result<(), ()> {
if field.is_some() {
- tcx.dcx()
- .emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name_or_empty() });
+ tcx.dcx().emit_err(DuplicateValuesFor { span: attr.span(), name });
return Err(());
}
@@ -156,7 +158,7 @@ fn set_field<T>(
Ok(())
} else {
tcx.dcx()
- .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name_or_empty() });
+ .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name().unwrap() });
Err(())
}
}
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 82c57ef..a0efc62 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -1,5 +1,4 @@
// tidy-alphabetical-start
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(assert_matches)]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
diff --git a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs
index ed3b1ae..daddb5d 100644
--- a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs
+++ b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs
@@ -42,7 +42,7 @@ fn is_ptr_to_int_in_const(&self, function: &Operand<'tcx>) -> bool {
if self.tcx.is_const_fn(def_id)
|| matches!(
self.tcx.opt_associated_item(def_id),
- Some(AssocItem { kind: AssocKind::Const, .. })
+ Some(AssocItem { kind: AssocKind::Const { .. }, .. })
)
{
let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder();
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index cb84401..4be67b8 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -35,7 +35,8 @@ fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// MIR building, and are not needed after InstrumentCoverage.
CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. },
)
- | StatementKind::FakeRead(..) => statement.make_nop(),
+ | StatementKind::FakeRead(..)
+ | StatementKind::BackwardIncompatibleDropHint { .. } => statement.make_nop(),
StatementKind::Assign(box (
_,
Rvalue::Cast(
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 04d96f1..92d5e15 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -203,7 +203,7 @@ struct TransformVisitor<'tcx> {
impl<'tcx> TransformVisitor<'tcx> {
fn insert_none_ret_block(&self, body: &mut Body<'tcx>) -> BasicBlock {
- let block = BasicBlock::new(body.basic_blocks.len());
+ let block = body.basic_blocks.next_index();
let source_info = SourceInfo::outermost(body.span);
let none_value = match self.coroutine_kind {
@@ -547,7 +547,7 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, None);
- for bb in START_BLOCK..body.basic_blocks.next_index() {
+ for bb in body.basic_blocks.indices() {
let bb_data = &body[bb];
if bb_data.is_cleanup {
continue;
@@ -556,11 +556,11 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
match &bb_data.terminator().kind {
TerminatorKind::Call { func, .. } => {
let func_ty = func.ty(body, tcx);
- if let ty::FnDef(def_id, _) = *func_ty.kind() {
- if def_id == get_context_def_id {
- let local = eliminate_get_context_call(&mut body[bb]);
- replace_resume_ty_local(tcx, body, local, context_mut_ref);
- }
+ if let ty::FnDef(def_id, _) = *func_ty.kind()
+ && def_id == get_context_def_id
+ {
+ let local = eliminate_get_context_call(&mut body[bb]);
+ replace_resume_ty_local(tcx, body, local, context_mut_ref);
}
}
TerminatorKind::Yield { resume_arg, .. } => {
@@ -1057,7 +1057,7 @@ fn insert_switch<'tcx>(
let blocks = body.basic_blocks_mut().iter_mut();
for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) {
- *target = BasicBlock::new(target.index() + 1);
+ *target += 1;
}
}
@@ -1169,6 +1169,13 @@ fn create_coroutine_drop_shim<'tcx>(
dump_mir(tcx, false, "coroutine_drop", &0, &body, |_, _| Ok(()));
body.source.instance = drop_instance;
+ // Creating a coroutine drop shim happens on `Analysis(PostCleanup) -> Runtime(Initial)`
+ // but the pass manager doesn't update the phase of the coroutine drop shim. Update the
+ // phase of the drop shim so that later on when we run the pass manager on the shim, in
+ // the `mir_shims` query, we don't ICE on the intra-pass validation before we've updated
+ // the phase of the body from analysis.
+ body.phase = MirPhase::Runtime(RuntimePhase::Initial);
+
body
}
@@ -1186,7 +1193,7 @@ fn insert_panic_block<'tcx>(
body: &mut Body<'tcx>,
message: AssertMessage<'tcx>,
) -> BasicBlock {
- let assert_block = BasicBlock::new(body.basic_blocks.len());
+ let assert_block = body.basic_blocks.next_index();
let kind = TerminatorKind::Assert {
cond: Operand::Constant(Box::new(ConstOperand {
span: body.span,
@@ -1209,14 +1216,8 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::Typing
}
// If there's a return terminator the function may return.
- for block in body.basic_blocks.iter() {
- if let TerminatorKind::Return = block.terminator().kind {
- return true;
- }
- }
-
+ body.basic_blocks.iter().any(|block| matches!(block.terminator().kind, TerminatorKind::Return))
// Otherwise the function can't return.
- false
}
fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
@@ -1293,12 +1294,12 @@ fn create_coroutine_resume_function<'tcx>(
kind: TerminatorKind::Goto { target: poison_block },
};
}
- } else if !block.is_cleanup {
+ } else if !block.is_cleanup
// Any terminators that *can* unwind but don't have an unwind target set are also
// pointed at our poisoning block (unless they're part of the cleanup path).
- if let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() {
- *unwind = UnwindAction::Cleanup(poison_block);
- }
+ && let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut()
+ {
+ *unwind = UnwindAction::Cleanup(poison_block);
}
}
}
@@ -1340,12 +1341,14 @@ fn create_coroutine_resume_function<'tcx>(
make_coroutine_state_argument_indirect(tcx, body);
match transform.coroutine_kind {
+ CoroutineKind::Coroutine(_)
+ | CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _) =>
+ {
+ make_coroutine_state_argument_pinned(tcx, body);
+ }
// Iterator::next doesn't accept a pinned argument,
// unlike for all other coroutine kinds.
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {}
- _ => {
- make_coroutine_state_argument_pinned(tcx, body);
- }
}
// Make sure we remove dead blocks to remove
@@ -1408,8 +1411,7 @@ fn create_cases<'tcx>(
let mut statements = Vec::new();
// Create StorageLive instructions for locals with live storage
- for i in 0..(body.local_decls.len()) {
- let l = Local::new(i);
+ for l in body.local_decls.indices() {
let needs_storage_live = point.storage_liveness.contains(l)
&& !transform.remap.contains(l)
&& !transform.always_live_locals.contains(l);
@@ -1535,15 +1537,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let coroutine_kind = body.coroutine_kind().unwrap();
// Get the discriminant type and args which typeck computed
- let (discr_ty, movable) = match *coroutine_ty.kind() {
- ty::Coroutine(_, args) => {
- let args = args.as_coroutine();
- (args.discr_ty(tcx), coroutine_kind.movability() == hir::Movability::Movable)
- }
- _ => {
- tcx.dcx().span_bug(body.span, format!("unexpected coroutine type {coroutine_ty}"));
- }
+ let ty::Coroutine(_, args) = coroutine_ty.kind() else {
+ tcx.dcx().span_bug(body.span, format!("unexpected coroutine type {coroutine_ty}"));
};
+ let discr_ty = args.as_coroutine().discr_ty(tcx);
let new_ret_ty = match coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
@@ -1610,6 +1607,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let always_live_locals = always_storage_live_locals(body);
+ let movable = coroutine_kind.movability() == hir::Movability::Movable;
let liveness_info =
locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 57f7893..d49f5d9 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -103,9 +103,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut should_cleanup = false;
// Also consider newly generated bbs in the same pass
- for i in 0..body.basic_blocks.len() {
+ for parent in body.basic_blocks.indices() {
let bbs = &*body.basic_blocks;
- let parent = BasicBlock::from_usize(i);
let Some(opt_data) = evaluate_candidate(tcx, body, parent) else { continue };
trace!("SUCCESS: found optimization possibility to apply: {opt_data:?}");
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index 0d8cf52..e3057a2 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -258,31 +258,27 @@ fn move_paths_for_fields(
) -> Vec<(Place<'tcx>, Option<D::Path>)> {
variant
.fields
- .iter()
- .enumerate()
- .map(|(i, f)| {
- let field = FieldIdx::new(i);
- let subpath = self.elaborator.field_subpath(variant_path, field);
+ .iter_enumerated()
+ .map(|(field_idx, field)| {
+ let subpath = self.elaborator.field_subpath(variant_path, field_idx);
let tcx = self.tcx();
assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
- // The type error for normalization may have been in dropck: see
- // `compute_drop_data` in rustc_borrowck, in which case we wouldn't have
- // deleted the MIR body and could have an error here as well.
- let field_ty = match tcx
- .try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args))
- {
+ let field_ty = match tcx.try_normalize_erasing_regions(
+ self.elaborator.typing_env(),
+ field.ty(tcx, args),
+ ) {
Ok(t) => t,
Err(_) => Ty::new_error(
self.tcx(),
- self.elaborator
- .body()
- .tainted_by_errors
- .expect("Error in drop elaboration not found by dropck."),
+ self.tcx().dcx().span_delayed_bug(
+ self.elaborator.body().span,
+ "Error normalizing in drop elaboration.",
+ ),
),
};
- (tcx.mk_place_field(base_place, field, field_ty), subpath)
+ (tcx.mk_place_field(base_place, field_idx, field_ty), subpath)
})
.collect()
}
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 0ab24e4..69e80ed 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -903,9 +903,9 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
let mut integrator = Integrator {
args: &args,
- new_locals: Local::new(caller_body.local_decls.len())..,
- new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
- new_blocks: BasicBlock::new(caller_body.basic_blocks.len())..,
+ new_locals: caller_body.local_decls.next_index()..,
+ new_scopes: caller_body.source_scopes.next_index()..,
+ new_blocks: caller_body.basic_blocks.next_index()..,
destination: destination_local,
callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
callsite,
@@ -1169,7 +1169,7 @@ fn map_local(&self, local: Local) -> Local {
if idx < self.args.len() {
self.args[idx]
} else {
- Local::new(self.new_locals.start.index() + (idx - self.args.len()))
+ self.new_locals.start + (idx - self.args.len())
}
};
trace!("mapping local `{:?}` to `{:?}`", local, new);
@@ -1177,13 +1177,13 @@ fn map_local(&self, local: Local) -> Local {
}
fn map_scope(&self, scope: SourceScope) -> SourceScope {
- let new = SourceScope::new(self.new_scopes.start.index() + scope.index());
+ let new = self.new_scopes.start + scope.index();
trace!("mapping scope `{:?}` to `{:?}`", scope, new);
new
}
fn map_block(&self, block: BasicBlock) -> BasicBlock {
- let new = BasicBlock::new(self.new_blocks.start.index() + block.index());
+ let new = self.new_blocks.start + block.index();
trace!("mapping block `{:?}` to `{:?}`", block, new);
new
}
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 2eff6b3..5f0c55d 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -10,7 +10,6 @@
use rustc_span::{DUMMY_SP, Symbol, sym};
use crate::simplify::simplify_duplicate_switch_targets;
-use crate::take_array;
pub(super) enum InstSimplify {
BeforeInline,
@@ -39,26 +38,26 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks);
for block in body.basic_blocks.as_mut() {
for statement in block.statements.iter_mut() {
- match statement.kind {
- StatementKind::Assign(box (_place, ref mut rvalue)) => {
- if !preserve_ub_checks {
- ctx.simplify_ub_check(rvalue);
- }
- ctx.simplify_bool_cmp(rvalue);
- ctx.simplify_ref_deref(rvalue);
- ctx.simplify_ptr_aggregate(rvalue);
- ctx.simplify_cast(rvalue);
- ctx.simplify_repeated_aggregate(rvalue);
- ctx.simplify_repeat_once(rvalue);
- }
- _ => {}
+ let StatementKind::Assign(box (.., rvalue)) = &mut statement.kind else {
+ continue;
+ };
+
+ if !preserve_ub_checks {
+ ctx.simplify_ub_check(rvalue);
}
+ ctx.simplify_bool_cmp(rvalue);
+ ctx.simplify_ref_deref(rvalue);
+ ctx.simplify_ptr_aggregate(rvalue);
+ ctx.simplify_cast(rvalue);
+ ctx.simplify_repeated_aggregate(rvalue);
+ ctx.simplify_repeat_once(rvalue);
}
- ctx.simplify_primitive_clone(block.terminator.as_mut().unwrap(), &mut block.statements);
- ctx.simplify_intrinsic_assert(block.terminator.as_mut().unwrap());
- ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap());
- simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
+ let terminator = block.terminator.as_mut().unwrap();
+ ctx.simplify_primitive_clone(terminator, &mut block.statements);
+ ctx.simplify_intrinsic_assert(terminator);
+ ctx.simplify_nounwind_call(terminator);
+ simplify_duplicate_switch_targets(terminator);
}
}
@@ -105,43 +104,34 @@ fn simplify_repeated_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
/// Transform boolean comparisons into logical operations.
fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) {
- match rvalue {
- Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => {
- let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
- // Transform "Eq(a, true)" ==> "a"
- (BinOp::Eq, _, Some(true)) => Some(Rvalue::Use(a.clone())),
+ let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) = &*rvalue else { return };
+ *rvalue = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
+ // Transform "Eq(a, true)" ==> "a"
+ (BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone()),
- // Transform "Ne(a, false)" ==> "a"
- (BinOp::Ne, _, Some(false)) => Some(Rvalue::Use(a.clone())),
+ // Transform "Ne(a, false)" ==> "a"
+ (BinOp::Ne, _, Some(false)) => Rvalue::Use(a.clone()),
- // Transform "Eq(true, b)" ==> "b"
- (BinOp::Eq, Some(true), _) => Some(Rvalue::Use(b.clone())),
+ // Transform "Eq(true, b)" ==> "b"
+ (BinOp::Eq, Some(true), _) => Rvalue::Use(b.clone()),
- // Transform "Ne(false, b)" ==> "b"
- (BinOp::Ne, Some(false), _) => Some(Rvalue::Use(b.clone())),
+ // Transform "Ne(false, b)" ==> "b"
+ (BinOp::Ne, Some(false), _) => Rvalue::Use(b.clone()),
- // Transform "Eq(false, b)" ==> "Not(b)"
- (BinOp::Eq, Some(false), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
+ // Transform "Eq(false, b)" ==> "Not(b)"
+ (BinOp::Eq, Some(false), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()),
- // Transform "Ne(true, b)" ==> "Not(b)"
- (BinOp::Ne, Some(true), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
+ // Transform "Ne(true, b)" ==> "Not(b)"
+ (BinOp::Ne, Some(true), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()),
- // Transform "Eq(a, false)" ==> "Not(a)"
- (BinOp::Eq, _, Some(false)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
+ // Transform "Eq(a, false)" ==> "Not(a)"
+ (BinOp::Eq, _, Some(false)) => Rvalue::UnaryOp(UnOp::Not, a.clone()),
- // Transform "Ne(a, true)" ==> "Not(a)"
- (BinOp::Ne, _, Some(true)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
+ // Transform "Ne(a, true)" ==> "Not(a)"
+ (BinOp::Ne, _, Some(true)) => Rvalue::UnaryOp(UnOp::Not, a.clone()),
- _ => None,
- };
-
- if let Some(new) = new {
- *rvalue = new;
- }
- }
-
- _ => {}
- }
+ _ => return,
+ };
}
fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
@@ -151,64 +141,58 @@ fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
/// Transform `&(*a)` ==> `a`.
fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) {
- if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue {
- if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
- if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty {
- return;
- }
-
- *rvalue = Rvalue::Use(Operand::Copy(Place {
- local: base.local,
- projection: self.tcx.mk_place_elems(base.projection),
- }));
- }
+ if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue
+ && let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection()
+ && rvalue.ty(self.local_decls, self.tcx) == base.ty(self.local_decls, self.tcx).ty
+ {
+ *rvalue = Rvalue::Use(Operand::Copy(Place {
+ local: base.local,
+ projection: self.tcx.mk_place_elems(base.projection),
+ }));
}
}
/// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`.
fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue
+ && let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx)
+ && meta_ty.is_unit()
{
- let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx);
- if meta_ty.is_unit() {
- // The mutable borrows we're holding prevent printing `rvalue` here
- let mut fields = std::mem::take(fields);
- let _meta = fields.pop().unwrap();
- let data = fields.pop().unwrap();
- let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability);
- *rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty);
- }
+ // The mutable borrows we're holding prevent printing `rvalue` here
+ let mut fields = std::mem::take(fields);
+ let _meta = fields.pop().unwrap();
+ let data = fields.pop().unwrap();
+ let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability);
+ *rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty);
}
}
fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) {
- if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue {
- let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks());
- let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None };
- *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
- }
+ let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue else { return };
+
+ let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks());
+ let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None };
+ *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
}
fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) {
- if let Rvalue::Cast(kind, operand, cast_ty) = rvalue {
- let operand_ty = operand.ty(self.local_decls, self.tcx);
- if operand_ty == *cast_ty {
- *rvalue = Rvalue::Use(operand.clone());
- } else if *kind == CastKind::Transmute {
- // Transmuting an integer to another integer is just a signedness cast
- if let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) =
- (operand_ty.kind(), cast_ty.kind())
- && int.bit_width() == uint.bit_width()
- {
- // The width check isn't strictly necessary, as different widths
- // are UB and thus we'd be allowed to turn it into a cast anyway.
- // But let's keep the UB around for codegen to exploit later.
- // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
- // then the width check is necessary for big-endian correctness.)
- *kind = CastKind::IntToInt;
- return;
- }
- }
+ let Rvalue::Cast(kind, operand, cast_ty) = rvalue else { return };
+
+ let operand_ty = operand.ty(self.local_decls, self.tcx);
+ if operand_ty == *cast_ty {
+ *rvalue = Rvalue::Use(operand.clone());
+ } else if *kind == CastKind::Transmute
+ // Transmuting an integer to another integer is just a signedness cast
+ && let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) =
+ (operand_ty.kind(), cast_ty.kind())
+ && int.bit_width() == uint.bit_width()
+ {
+ // The width check isn't strictly necessary, as different widths
+ // are UB and thus we'd be allowed to turn it into a cast anyway.
+ // But let's keep the UB around for codegen to exploit later.
+ // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
+ // then the width check is necessary for big-endian correctness.)
+ *kind = CastKind::IntToInt;
}
}
@@ -229,7 +213,9 @@ fn simplify_primitive_clone(
terminator: &mut Terminator<'tcx>,
statements: &mut Vec<Statement<'tcx>>,
) {
- let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind
+ let TerminatorKind::Call {
+ func, args, destination, target: Some(destination_block), ..
+ } = &terminator.kind
else {
return;
};
@@ -237,15 +223,8 @@ fn simplify_primitive_clone(
// It's definitely not a clone if there are multiple arguments
let [arg] = &args[..] else { return };
- let Some(destination_block) = *target else { return };
-
// Only bother looking more if it's easy to know what we're calling
- let Some((fn_def_id, fn_args)) = func.const_fn_def() else { return };
-
- // Clone needs one arg, so we can cheaply rule out other stuff
- if fn_args.len() != 1 {
- return;
- }
+ let Some((fn_def_id, ..)) = func.const_fn_def() else { return };
// These types are easily available from locals, so check that before
// doing DefId lookups to figure out what we're actually calling.
@@ -253,15 +232,12 @@ fn simplify_primitive_clone(
let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return };
- if !inner_ty.is_trivially_pure_clone_copy() {
+ if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn)
+ || !inner_ty.is_trivially_pure_clone_copy()
+ {
return;
}
- if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn) {
- return;
- }
-
- let Ok([arg]) = take_array(args) else { return };
let Some(arg_place) = arg.node.place() else { return };
statements.push(Statement {
@@ -273,11 +249,11 @@ fn simplify_primitive_clone(
)),
))),
});
- terminator.kind = TerminatorKind::Goto { target: destination_block };
+ terminator.kind = TerminatorKind::Goto { target: *destination_block };
}
fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
- let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else {
+ let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else {
return;
};
@@ -290,7 +266,7 @@ fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(),
ty::Closure(..) => ExternAbi::RustCall,
ty::Coroutine(..) => ExternAbi::Rust,
- _ => bug!("unexpected body ty: {:?}", body_ty),
+ _ => bug!("unexpected body ty: {body_ty:?}"),
};
if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) {
@@ -299,10 +275,9 @@ fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
}
fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) {
- let TerminatorKind::Call { func, target, .. } = &mut terminator.kind else {
- return;
- };
- let Some(target_block) = target else {
+ let TerminatorKind::Call { ref func, target: ref mut target @ Some(target_block), .. } =
+ terminator.kind
+ else {
return;
};
let func_ty = func.ty(self.local_decls, self.tcx);
@@ -310,12 +285,10 @@ fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) {
return;
};
// The intrinsics we are interested in have one generic parameter
- if args.is_empty() {
- return;
- }
+ let [arg, ..] = args[..] else { return };
let known_is_valid =
- intrinsic_assert_panics(self.tcx, self.typing_env, args[0], intrinsic_name);
+ intrinsic_assert_panics(self.tcx, self.typing_env, arg, intrinsic_name);
match known_is_valid {
// We don't know the layout or it's not validity assertion at all, don't touch it
None => {}
@@ -325,7 +298,7 @@ fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) {
}
Some(false) => {
// If we know the assert does not panic, turn the call into a Goto
- terminator.kind = TerminatorKind::Goto { target: *target_block };
+ terminator.kind = TerminatorKind::Goto { target: target_block };
}
}
}
@@ -346,9 +319,7 @@ fn resolve_rust_intrinsic<'tcx>(
tcx: TyCtxt<'tcx>,
func_ty: Ty<'tcx>,
) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
- if let ty::FnDef(def_id, args) = *func_ty.kind() {
- let intrinsic = tcx.intrinsic(def_id)?;
- return Some((intrinsic.name, args));
- }
- None
+ let ty::FnDef(def_id, args) = *func_ty.kind() else { return None };
+ let intrinsic = tcx.intrinsic(def_id)?;
+ Some((intrinsic.name, args))
}
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 0a72a9d..8b4b214 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -90,7 +90,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
};
for bb in body.basic_blocks.indices() {
- finder.start_from_switch(bb);
+ let old_len = finder.opportunities.len();
+ // If we have any const-eval errors discard any opportunities found
+ if finder.start_from_switch(bb).is_none() {
+ finder.opportunities.truncate(old_len);
+ }
}
let opportunities = finder.opportunities;
@@ -150,14 +154,6 @@ impl Condition {
fn matches(&self, value: ScalarInt) -> bool {
(self.value == value) == (self.polarity == Polarity::Eq)
}
-
- fn inv(mut self) -> Self {
- self.polarity = match self.polarity {
- Polarity::Eq => Polarity::Ne,
- Polarity::Ne => Polarity::Eq,
- };
- self
- }
}
#[derive(Copy, Clone, Debug)]
@@ -180,8 +176,21 @@ fn iter_matches(self, value: ScalarInt) -> impl Iterator<Item = Condition> {
self.iter().filter(move |c| c.matches(value))
}
- fn map(self, arena: &'a DroplessArena, f: impl Fn(Condition) -> Condition) -> ConditionSet<'a> {
- ConditionSet(arena.alloc_from_iter(self.iter().map(f)))
+ fn map(
+ self,
+ arena: &'a DroplessArena,
+ f: impl Fn(Condition) -> Option<Condition>,
+ ) -> Option<ConditionSet<'a>> {
+ let mut all_ok = true;
+ let set = arena.alloc_from_iter(self.iter().map_while(|c| {
+ if let Some(c) = f(c) {
+ Some(c)
+ } else {
+ all_ok = false;
+ None
+ }
+ }));
+ all_ok.then_some(ConditionSet(set))
}
}
@@ -192,28 +201,28 @@ fn is_empty(&self, state: &State<ConditionSet<'a>>) -> bool {
/// Recursion entry point to find threading opportunities.
#[instrument(level = "trace", skip(self))]
- fn start_from_switch(&mut self, bb: BasicBlock) {
+ fn start_from_switch(&mut self, bb: BasicBlock) -> Option<()> {
let bbdata = &self.body[bb];
if bbdata.is_cleanup || self.loop_headers.contains(bb) {
- return;
+ return Some(());
}
- let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { return };
- let Some(discr) = discr.place() else { return };
+ let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { return Some(()) };
+ let Some(discr) = discr.place() else { return Some(()) };
debug!(?discr, ?bb);
let discr_ty = discr.ty(self.body, self.tcx).ty;
let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else {
- return;
+ return Some(());
};
- let Some(discr) = self.map.find(discr.as_ref()) else { return };
+ let Some(discr) = self.map.find(discr.as_ref()) else { return Some(()) };
debug!(?discr);
let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body);
let mut state = State::new_reachable();
let conds = if let Some((value, then, else_)) = targets.as_static_if() {
- let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return };
+ let value = ScalarInt::try_from_uint(value, discr_layout.size)?;
self.arena.alloc_from_iter([
Condition { value, polarity: Polarity::Eq, target: then },
Condition { value, polarity: Polarity::Ne, target: else_ },
@@ -227,7 +236,7 @@ fn start_from_switch(&mut self, bb: BasicBlock) {
let conds = ConditionSet(conds);
state.insert_value_idx(discr, conds, &self.map);
- self.find_opportunity(bb, state, cost, 0);
+ self.find_opportunity(bb, state, cost, 0)
}
/// Recursively walk statements backwards from this bb's terminator to find threading
@@ -239,10 +248,10 @@ fn find_opportunity(
mut state: State<ConditionSet<'a>>,
mut cost: CostChecker<'_, 'tcx>,
depth: usize,
- ) {
+ ) -> Option<()> {
// Do not thread through loop headers.
if self.loop_headers.contains(bb) {
- return;
+ return Some(());
}
debug!(cost = ?cost.cost());
@@ -250,16 +259,16 @@ fn find_opportunity(
self.body.basic_blocks[bb].statements.iter().enumerate().rev()
{
if self.is_empty(&state) {
- return;
+ return Some(());
}
cost.visit_statement(stmt, Location { block: bb, statement_index });
if cost.cost() > MAX_COST {
- return;
+ return Some(());
}
// Attempt to turn the `current_condition` on `lhs` into a condition on another place.
- self.process_statement(bb, stmt, &mut state);
+ self.process_statement(bb, stmt, &mut state)?;
// When a statement mutates a place, assignments to that place that happen
// above the mutation cannot fulfill a condition.
@@ -271,7 +280,7 @@ fn find_opportunity(
}
if self.is_empty(&state) || depth >= MAX_BACKTRACK {
- return;
+ return Some(());
}
let last_non_rec = self.opportunities.len();
@@ -284,9 +293,9 @@ fn find_opportunity(
match term.kind {
TerminatorKind::SwitchInt { ref discr, ref targets } => {
self.process_switch_int(discr, targets, bb, &mut state);
- self.find_opportunity(pred, state, cost, depth + 1);
+ self.find_opportunity(pred, state, cost, depth + 1)?;
}
- _ => self.recurse_through_terminator(pred, || state, &cost, depth),
+ _ => self.recurse_through_terminator(pred, || state, &cost, depth)?,
}
} else if let &[ref predecessors @ .., last_pred] = &predecessors[..] {
for &pred in predecessors {
@@ -311,12 +320,13 @@ fn find_opportunity(
let first = &mut new_tos[0];
*first = ThreadingOpportunity { chain: vec![bb], target: first.target };
self.opportunities.truncate(last_non_rec + 1);
- return;
+ return Some(());
}
for op in self.opportunities[last_non_rec..].iter_mut() {
op.chain.push(bb);
}
+ Some(())
}
/// Extract the mutated place from a statement.
@@ -430,23 +440,23 @@ fn process_operand(
lhs: PlaceIndex,
rhs: &Operand<'tcx>,
state: &mut State<ConditionSet<'a>>,
- ) {
+ ) -> Option<()> {
match rhs {
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
Operand::Constant(constant) => {
- let Some(constant) =
- self.ecx.eval_mir_constant(&constant.const_, constant.span, None).discard_err()
- else {
- return;
- };
+ let constant = self
+ .ecx
+ .eval_mir_constant(&constant.const_, constant.span, None)
+ .discard_err()?;
self.process_constant(bb, lhs, constant, state);
}
// Transfer the conditions on the copied rhs.
Operand::Move(rhs) | Operand::Copy(rhs) => {
- let Some(rhs) = self.map.find(rhs.as_ref()) else { return };
+ let Some(rhs) = self.map.find(rhs.as_ref()) else { return Some(()) };
state.insert_place_idx(rhs, lhs, &self.map);
}
}
+ Some(())
}
#[instrument(level = "trace", skip(self))]
@@ -456,14 +466,18 @@ fn process_assign(
lhs_place: &Place<'tcx>,
rhs: &Rvalue<'tcx>,
state: &mut State<ConditionSet<'a>>,
- ) {
- let Some(lhs) = self.map.find(lhs_place.as_ref()) else { return };
+ ) -> Option<()> {
+ let Some(lhs) = self.map.find(lhs_place.as_ref()) else {
+ return Some(());
+ };
match rhs {
- Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state),
+ Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?,
// Transfer the conditions on the copy rhs.
- Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state),
+ Rvalue::CopyForDeref(rhs) => {
+ self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)?
+ }
Rvalue::Discriminant(rhs) => {
- let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return };
+ let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return Some(()) };
state.insert_place_idx(rhs, lhs, &self.map);
}
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
@@ -471,7 +485,7 @@ fn process_assign(
let agg_ty = lhs_place.ty(self.body, self.tcx).ty;
let lhs = match kind {
// Do not support unions.
- AggregateKind::Adt(.., Some(_)) => return,
+ AggregateKind::Adt(.., Some(_)) => return Some(()),
AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => {
if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant)
&& let Some(discr_value) = self
@@ -484,30 +498,31 @@ fn process_assign(
if let Some(idx) = self.map.apply(lhs, TrackElem::Variant(*variant_index)) {
idx
} else {
- return;
+ return Some(());
}
}
_ => lhs,
};
for (field_index, operand) in operands.iter_enumerated() {
if let Some(field) = self.map.apply(lhs, TrackElem::Field(field_index)) {
- self.process_operand(bb, field, operand, state);
+ self.process_operand(bb, field, operand, state)?;
}
}
}
- // Transfer the conditions on the copy rhs, after inversing polarity.
+ // Transfer the conditions on the copy rhs, after inverting the value of the condition.
Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => {
- if !place.ty(self.body, self.tcx).ty.is_bool() {
- // Constructing the conditions by inverting the polarity
- // of equality is only correct for bools. That is to say,
- // `!a == b` is not `a != b` for integers greater than 1 bit.
- return;
- }
- let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return };
- let Some(place) = self.map.find(place.as_ref()) else { return };
- // FIXME: I think This could be generalized to not bool if we
- // actually perform a logical not on the condition's value.
- let conds = conditions.map(self.arena, Condition::inv);
+ let layout = self.ecx.layout_of(place.ty(self.body, self.tcx).ty).unwrap();
+ let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return Some(()) };
+ let Some(place) = self.map.find(place.as_ref()) else { return Some(()) };
+ let conds = conditions.map(self.arena, |mut cond| {
+ cond.value = self
+ .ecx
+ .unary_op(UnOp::Not, &ImmTy::from_scalar_int(cond.value, layout))
+ .discard_err()?
+ .to_scalar_int()
+ .discard_err()?;
+ Some(cond)
+ })?;
state.insert_value_idx(place, conds, &self.map);
}
// We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
@@ -517,34 +532,34 @@ fn process_assign(
box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value))
| box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)),
) => {
- let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return };
- let Some(place) = self.map.find(place.as_ref()) else { return };
+ let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return Some(()) };
+ let Some(place) = self.map.find(place.as_ref()) else { return Some(()) };
let equals = match op {
BinOp::Eq => ScalarInt::TRUE,
BinOp::Ne => ScalarInt::FALSE,
- _ => return,
+ _ => return Some(()),
};
if value.const_.ty().is_floating_point() {
// Floating point equality does not follow bit-patterns.
// -0.0 and NaN both have special rules for equality,
// and therefore we cannot use integer comparisons for them.
// Avoid handling them, though this could be extended in the future.
- return;
+ return Some(());
}
- let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)
- else {
- return;
- };
- let conds = conditions.map(self.arena, |c| Condition {
- value,
- polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne },
- ..c
- });
+ let value = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)?;
+ let conds = conditions.map(self.arena, |c| {
+ Some(Condition {
+ value,
+ polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne },
+ ..c
+ })
+ })?;
state.insert_value_idx(place, conds, &self.map);
}
_ => {}
}
+ Some(())
}
#[instrument(level = "trace", skip(self))]
@@ -553,7 +568,7 @@ fn process_statement(
bb: BasicBlock,
stmt: &Statement<'tcx>,
state: &mut State<ConditionSet<'a>>,
- ) {
+ ) -> Option<()> {
let register_opportunity = |c: Condition| {
debug!(?bb, ?c.target, "register");
self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target })
@@ -566,30 +581,32 @@ fn process_statement(
// If we expect `discriminant(place) ?= A`,
// we have an opportunity if `variant_index ?= A`.
StatementKind::SetDiscriminant { box place, variant_index } => {
- let Some(discr_target) = self.map.find_discr(place.as_ref()) else { return };
+ let Some(discr_target) = self.map.find_discr(place.as_ref()) else {
+ return Some(());
+ };
let enum_ty = place.ty(self.body, self.tcx).ty;
// `SetDiscriminant` guarantees that the discriminant is now `variant_index`.
// Even if the discriminant write does nothing due to niches, it is UB to set the
// discriminant when the data does not encode the desired discriminant.
- let Some(discr) =
- self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err()
- else {
- return;
- };
+ let discr =
+ self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err()?;
self.process_immediate(bb, discr_target, discr, state);
}
// If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(
Operand::Copy(place) | Operand::Move(place),
)) => {
- let Some(conditions) = state.try_get(place.as_ref(), &self.map) else { return };
+ let Some(conditions) = state.try_get(place.as_ref(), &self.map) else {
+ return Some(());
+ };
conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity);
}
StatementKind::Assign(box (lhs_place, rhs)) => {
- self.process_assign(bb, lhs_place, rhs, state);
+ self.process_assign(bb, lhs_place, rhs, state)?;
}
_ => {}
}
+ Some(())
}
#[instrument(level = "trace", skip(self, state, cost))]
@@ -600,7 +617,7 @@ fn recurse_through_terminator(
state: impl FnOnce() -> State<ConditionSet<'a>>,
cost: &CostChecker<'_, 'tcx>,
depth: usize,
- ) {
+ ) -> Option<()> {
let term = self.body.basic_blocks[bb].terminator();
let place_to_flood = match term.kind {
// We come from a target, so those are not possible.
@@ -615,9 +632,9 @@ fn recurse_through_terminator(
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Yield { .. } => bug!("{term:?} invalid"),
// Cannot reason about inline asm.
- TerminatorKind::InlineAsm { .. } => return,
+ TerminatorKind::InlineAsm { .. } => return Some(()),
// `SwitchInt` is handled specially.
- TerminatorKind::SwitchInt { .. } => return,
+ TerminatorKind::SwitchInt { .. } => return Some(()),
// We can recurse, no thing particular to do.
TerminatorKind::Goto { .. } => None,
// Flood the overwritten place, and progress through.
@@ -632,7 +649,7 @@ fn recurse_through_terminator(
if let Some(place_to_flood) = place_to_flood {
state.flood_with(place_to_flood.as_ref(), &self.map, ConditionSet::BOTTOM);
}
- self.find_opportunity(bb, state, cost.clone(), depth + 1);
+ self.find_opportunity(bb, state, cost.clone(), depth + 1)
}
#[instrument(level = "trace", skip(self))]
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index dfd07f0..4d74ecd 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,5 +1,4 @@
// tidy-alphabetical-start
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(box_patterns)]
diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
index 29a9133..537f152 100644
--- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
+++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
@@ -512,23 +512,17 @@ struct LocalLabel<'a> {
/// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order
impl Subdiagnostic for LocalLabel<'_> {
- fn add_to_diag_with<
- G: rustc_errors::EmissionGuarantee,
- F: rustc_errors::SubdiagMessageOp<G>,
- >(
- self,
- diag: &mut rustc_errors::Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: rustc_errors::EmissionGuarantee>(self, diag: &mut rustc_errors::Diag<'_, G>) {
diag.arg("name", self.name);
diag.arg("is_generated_name", self.is_generated_name);
diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024);
- let msg = f(diag, crate::fluent_generated::mir_transform_tail_expr_local.into());
+ let msg = diag.eagerly_translate(crate::fluent_generated::mir_transform_tail_expr_local);
diag.span_label(self.span, msg);
for dtor in self.destructors {
- dtor.add_to_diag_with(diag, f);
+ dtor.add_to_diag(diag);
}
- let msg = f(diag, crate::fluent_generated::mir_transform_label_local_epilogue);
+ let msg =
+ diag.eagerly_translate(crate::fluent_generated::mir_transform_label_local_epilogue);
diag.span_label(self.span, msg);
}
}
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 0d9d036..5059837 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -20,13 +20,11 @@ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let typing_env = body.typing_env(tcx);
let mut should_cleanup = false;
- for i in 0..body.basic_blocks.len() {
- let bbs = &*body.basic_blocks;
- let bb_idx = BasicBlock::from_usize(i);
- match bbs[bb_idx].terminator().kind {
+ for bb_idx in body.basic_blocks.indices() {
+ match &body.basic_blocks[bb_idx].terminator().kind {
TerminatorKind::SwitchInt {
- discr: ref _discr @ (Operand::Copy(_) | Operand::Move(_)),
- ref targets,
+ discr: Operand::Copy(_) | Operand::Move(_),
+ targets,
..
// We require that the possible target blocks don't contain this block.
} if !targets.all_targets().contains(&bb_idx) => {}
@@ -66,9 +64,10 @@ fn simplify(
typing_env: ty::TypingEnv<'tcx>,
) -> Option<()> {
let bbs = &body.basic_blocks;
- let (discr, targets) = match bbs[switch_bb_idx].terminator().kind {
- TerminatorKind::SwitchInt { ref discr, ref targets, .. } => (discr, targets),
- _ => unreachable!(),
+ let TerminatorKind::SwitchInt { discr, targets, .. } =
+ &bbs[switch_bb_idx].terminator().kind
+ else {
+ unreachable!();
};
let discr_ty = discr.ty(body.local_decls(), tcx);
diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
index c63bfdc..f59b849 100644
--- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
+++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
@@ -18,19 +18,17 @@ fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// find basic blocks with no statement and a return terminator
let mut bbs_simple_returns = DenseBitSet::new_empty(body.basic_blocks.len());
let bbs = body.basic_blocks_mut();
- for idx in bbs.indices() {
- if bbs[idx].statements.is_empty()
- && bbs[idx].terminator().kind == TerminatorKind::Return
- {
+ for (idx, bb) in bbs.iter_enumerated() {
+ if bb.statements.is_empty() && bb.terminator().kind == TerminatorKind::Return {
bbs_simple_returns.insert(idx);
}
}
for bb in bbs {
- if let TerminatorKind::Goto { target } = bb.terminator().kind {
- if bbs_simple_returns.contains(target) {
- bb.terminator_mut().kind = TerminatorKind::Return;
- }
+ if let TerminatorKind::Goto { target } = bb.terminator().kind
+ && bbs_simple_returns.contains(target)
+ {
+ bb.terminator_mut().kind = TerminatorKind::Return;
}
}
diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs
index 6a177fa..12ace04 100644
--- a/compiler/rustc_mir_transform/src/patch.rs
+++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -181,7 +181,7 @@ pub(crate) fn local_ty(&self, local: Local) -> Ty<'tcx> {
/// Queues the addition of a new basic block.
pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
- let block = BasicBlock::new(self.term_patch_map.len());
+ let block = self.term_patch_map.next_index();
debug!("MirPatch: new_block: {:?}: {:?}", block, data);
self.new_blocks.push(data);
self.term_patch_map.push(None);
diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs
index 76c2f08..5599dee 100644
--- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs
+++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs
@@ -39,20 +39,22 @@ fn visit_place(
_context: PlaceContext,
_location: Location,
) {
- // Performance optimization: don't reintern if there is no `OpaqueCast` to remove.
- if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) {
- return;
+ if !self.tcx.next_trait_solver_globally() {
+ // `OpaqueCast` projections are only needed if there are opaque types on which projections
+ // are performed. After the `PostAnalysisNormalize` pass, all opaque types are replaced with their
+ // hidden types, so we don't need these projections anymore.
+ //
+ // Performance optimization: don't reintern if there is no `OpaqueCast` to remove.
+ if place.projection.iter().any(|elem| matches!(elem, ProjectionElem::OpaqueCast(_))) {
+ place.projection = self.tcx.mk_place_elems(
+ &place
+ .projection
+ .into_iter()
+ .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
+ .collect::<Vec<_>>(),
+ );
+ };
}
- // `OpaqueCast` projections are only needed if there are opaque types on which projections
- // are performed. After the `PostAnalysisNormalize` pass, all opaque types are replaced with their
- // hidden types, so we don't need these projections anymore.
- place.projection = self.tcx.mk_place_elems(
- &place
- .projection
- .into_iter()
- .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
- .collect::<Vec<_>>(),
- );
self.super_place(place, _context, _location);
}
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index c8d8dc1..47d4383 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -18,7 +18,7 @@
use rustc_const_eval::check_consts::{ConstCx, qualifs};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
-use rustc_index::{Idx, IndexSlice, IndexVec};
+use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, GenericArgs, List, Ty, TyCtxt, TypeVisitableExt};
@@ -864,17 +864,21 @@ fn promote_temp(&mut self, temp: Local) -> Local {
new_temp
}
- fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> {
+ fn promote_candidate(
+ mut self,
+ candidate: Candidate,
+ next_promoted_index: Promoted,
+ ) -> Body<'tcx> {
let def = self.source.source.def_id();
let (mut rvalue, promoted_op) = {
let promoted = &mut self.promoted;
- let promoted_id = Promoted::new(next_promoted_id);
let tcx = self.tcx;
let mut promoted_operand = |ty, span| {
promoted.span = span;
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def));
- let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) };
+ let uneval =
+ mir::UnevaluatedConst { def, args, promoted: Some(next_promoted_index) };
ConstOperand { span, user_ty: None, const_: Const::Unevaluated(uneval, ty) }
};
@@ -1034,7 +1038,7 @@ fn promote_candidates<'tcx>(
required_consts: Vec::new(),
};
- let mut promoted = promoter.promote_candidate(candidate, promotions.len());
+ let mut promoted = promoter.promote_candidate(candidate, promotions.next_index());
promoted.source.promoted = Some(promotions.next_index());
promotions.push(promoted);
}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index c977146..c13ffae 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -66,7 +66,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
let call_mut = tcx
.associated_items(fn_mut)
.in_definition_order()
- .find(|it| it.kind == ty::AssocKind::Fn)
+ .find(|it| it.is_fn())
.unwrap()
.def_id;
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 84905f4..5947637 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -597,20 +597,6 @@ fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
- if let StatementKind::BackwardIncompatibleDropHint { place, reason: _ } =
- &mut statement.kind
- {
- self.visit_local(
- &mut place.local,
- PlaceContext::MutatingUse(MutatingUseContext::Store),
- location,
- );
- } else {
- self.super_statement(statement, location);
- }
- }
-
fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
*l = self.map[*l].unwrap();
}
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index e7930f0..66fe3ef 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -221,12 +221,11 @@ fn check_cleanup_control_flow(&self) {
// Check for cycles
let mut stack = FxHashSet::default();
- for i in 0..parent.len() {
- let mut bb = BasicBlock::from_usize(i);
+ for (mut bb, parent) in parent.iter_enumerated_mut() {
stack.clear();
stack.insert(bb);
loop {
- let Some(parent) = parent[bb].take() else { break };
+ let Some(parent) = parent.take() else { break };
let no_cycle = stack.insert(parent);
if !no_cycle {
self.fail(
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 6e676ac..d1d0f7c 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -688,7 +688,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
let target_ty = self.monomorphize(target_ty);
let source_ty = self.monomorphize(source_ty);
let (source_ty, target_ty) =
- find_vtable_types_for_unsizing(self.tcx.at(span), source_ty, target_ty);
+ find_tails_for_unsizing(self.tcx.at(span), source_ty, target_ty);
// This could also be a different Unsize instruction, like
// from a fixed sized array to a slice. But we are only
// interested in things that produce a vtable.
@@ -1037,36 +1037,35 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
///
/// Finally, there is also the case of custom unsizing coercions, e.g., for
/// smart pointers such as `Rc` and `Arc`.
-fn find_vtable_types_for_unsizing<'tcx>(
+fn find_tails_for_unsizing<'tcx>(
tcx: TyCtxtAt<'tcx>,
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>,
) -> (Ty<'tcx>, Ty<'tcx>) {
- let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
- let typing_env = ty::TypingEnv::fully_monomorphized();
- if tcx.type_has_metadata(inner_source, typing_env) {
- (inner_source, inner_target)
- } else {
- tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, typing_env)
- }
- };
+ let typing_env = ty::TypingEnv::fully_monomorphized();
+ debug_assert!(!source_ty.has_param(), "{source_ty} should be fully monomorphic");
+ debug_assert!(!target_ty.has_param(), "{target_ty} should be fully monomorphic");
match (source_ty.kind(), target_ty.kind()) {
- (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _))
- | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b),
+ (
+ &ty::Ref(_, source_pointee, _),
+ &ty::Ref(_, target_pointee, _) | &ty::RawPtr(target_pointee, _),
+ )
+ | (&ty::RawPtr(source_pointee, _), &ty::RawPtr(target_pointee, _)) => {
+ tcx.struct_lockstep_tails_for_codegen(source_pointee, target_pointee, typing_env)
+ }
+
+ // `Box<T>` could go through the ADT code below, b/c it'll unpeel to `Unique<T>`,
+ // and eventually bottom out in a raw ref, but we can micro-optimize it here.
(_, _)
if let Some(source_boxed) = source_ty.boxed_ty()
&& let Some(target_boxed) = target_ty.boxed_ty() =>
{
- ptr_vtable(source_boxed, target_boxed)
+ tcx.struct_lockstep_tails_for_codegen(source_boxed, target_boxed, typing_env)
}
- // T as dyn* Trait
- (_, &ty::Dynamic(_, _, ty::DynStar)) => ptr_vtable(source_ty, target_ty),
-
(&ty::Adt(source_adt_def, source_args), &ty::Adt(target_adt_def, target_args)) => {
assert_eq!(source_adt_def, target_adt_def);
-
let CustomCoerceUnsized::Struct(coerce_index) =
match crate::custom_coerce_unsize_info(tcx, source_ty, target_ty) {
Ok(ccu) => ccu,
@@ -1075,21 +1074,23 @@ fn find_vtable_types_for_unsizing<'tcx>(
return (e, e);
}
};
-
- let source_fields = &source_adt_def.non_enum_variant().fields;
- let target_fields = &target_adt_def.non_enum_variant().fields;
-
- assert!(
- coerce_index.index() < source_fields.len()
- && source_fields.len() == target_fields.len()
- );
-
- find_vtable_types_for_unsizing(
- tcx,
- source_fields[coerce_index].ty(*tcx, source_args),
- target_fields[coerce_index].ty(*tcx, target_args),
- )
+ let coerce_field = &source_adt_def.non_enum_variant().fields[coerce_index];
+ // We're getting a possibly unnormalized type, so normalize it.
+ let source_field =
+ tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, source_args));
+ let target_field =
+ tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, target_args));
+ find_tails_for_unsizing(tcx, source_field, target_field)
}
+
+ // `T` as `dyn* Trait` unsizes *directly*.
+ //
+ // FIXME(dyn_star): This case is a bit awkward, b/c we're not really computing
+ // a tail here. We probably should handle this separately in the *caller* of
+ // this function, rather than returning something that is semantically different
+ // than what we return above.
+ (_, &ty::Dynamic(_, _, ty::DynStar)) => (source_ty, target_ty),
+
_ => bug!(
"find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
source_ty,
@@ -1308,7 +1309,7 @@ fn visit_mentioned_item<'tcx>(
}
MentionedItem::UnsizeCast { source_ty, target_ty } => {
let (source_ty, target_ty) =
- find_vtable_types_for_unsizing(tcx.at(span), source_ty, target_ty);
+ find_tails_for_unsizing(tcx.at(span), source_ty, target_ty);
// This could also be a different Unsize instruction, like
// from a fixed sized array to a slice. But we are only
// interested in things that produce a vtable.
@@ -1689,7 +1690,7 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
let mut recursion_depths = DefIdMap::default();
collect_items_rec(
tcx,
- dummy_spanned(root),
+ dummy_spanned(*root),
&state,
&mut recursion_depths,
recursion_limit,
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 5dbae50..8f6914f 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,5 +1,4 @@
// tidy-alphabetical-start
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(array_windows)]
#![feature(file_buffered)]
#![feature(if_let_guard)]
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 0f5bdc8..94ee34c 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -111,6 +111,11 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool
}
}
+ // Zero-sized types are dropped in both ABIs, so they're safe
+ if arg.layout.is_zst() {
+ return true;
+ }
+
false
}
diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
index 55d52d5..7251ef4 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
@@ -3,7 +3,7 @@
use rustc_hir::def_id::DefId;
use rustc_middle::mir::visit::Visitor as MirVisitor;
use rustc_middle::mir::{self, Location, traversal};
-use rustc_middle::ty::{self, AssocKind, Instance, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, AssocTag, Instance, Ty, TyCtxt, TypeFoldable};
use rustc_session::Limit;
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
use rustc_span::source_map::Spanned;
@@ -194,7 +194,7 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) ->
if let Some(new) = tcx.associated_items(impl_def_id).find_by_ident_and_kind(
tcx,
fn_ident,
- AssocKind::Fn,
+ AssocTag::Fn,
def_id,
) {
return Some(new.def_id);
diff --git a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
index ebe0b25..22d593b 100644
--- a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
@@ -2,7 +2,7 @@
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, PseudoCanonicalInput, Ty, TyCtxt, TypingEnv};
use rustc_symbol_mangling::symbol_name_for_instance_in_crate;
use tracing::{debug, trace};
@@ -22,23 +22,51 @@ fn adjust_activity_to_abi<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec
for (i, ty) in sig.inputs().iter().enumerate() {
if let Some(inner_ty) = ty.builtin_deref(true) {
if inner_ty.is_slice() {
+ // Now we need to figure out the size of each slice element in memory to allow
+ // safety checks and usability improvements in the backend.
+ let sty = match inner_ty.builtin_index() {
+ Some(sty) => sty,
+ None => {
+ panic!("slice element type unknown");
+ }
+ };
+ let pci = PseudoCanonicalInput {
+ typing_env: TypingEnv::fully_monomorphized(),
+ value: sty,
+ };
+
+ let layout = tcx.layout_of(pci);
+ let elem_size = match layout {
+ Ok(layout) => layout.size,
+ Err(_) => {
+ bug!("autodiff failed to compute slice element size");
+ }
+ };
+ let elem_size: u32 = elem_size.bytes() as u32;
+
// We know that the length will be passed as extra arg.
if !da.is_empty() {
// We are looking at a slice. The length of that slice will become an
// extra integer on llvm level. Integers are always const.
// However, if the slice get's duplicated, we want to know to later check the
// size. So we mark the new size argument as FakeActivitySize.
+ // There is one FakeActivitySize per slice, so for convenience we store the
+ // slice element size in bytes in it. We will use the size in the backend.
let activity = match da[i] {
DiffActivity::DualOnly
| DiffActivity::Dual
+ | DiffActivity::Dualv
| DiffActivity::DuplicatedOnly
- | DiffActivity::Duplicated => DiffActivity::FakeActivitySize,
+ | DiffActivity::Duplicated => {
+ DiffActivity::FakeActivitySize(Some(elem_size))
+ }
DiffActivity::Const => DiffActivity::Const,
_ => bug!("unexpected activity for ptr/ref"),
};
new_activities.push(activity);
new_positions.push(i + 1);
}
+
continue;
}
}
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index 384a304..83b2465 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -92,16 +92,20 @@ fn probe_and_consider_object_bound_candidate(
let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else {
panic!("expected object type in `probe_and_consider_object_bound_candidate`");
};
- ecx.add_goals(
- GoalSource::ImplWhereBound,
- structural_traits::predicates_for_object_candidate(
- ecx,
- goal.param_env,
- goal.predicate.trait_ref(cx),
- bounds,
- ),
- );
- ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ match structural_traits::predicates_for_object_candidate(
+ ecx,
+ goal.param_env,
+ goal.predicate.trait_ref(cx),
+ bounds,
+ ) {
+ Ok(requirements) => {
+ ecx.add_goals(GoalSource::ImplWhereBound, requirements);
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+ }
+ Err(_) => {
+ ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+ }
+ }
})
}
@@ -792,37 +796,46 @@ pub(super) fn merge_candidates(
};
match proven_via {
- // Even when a trait bound has been proven using a where-bound, we
- // still need to consider alias-bounds for normalization, see
- // tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
- //
- // FIXME(const_trait_impl): should this behavior also be used by
- // constness checking. Doing so is *at least theoretically* breaking,
- // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
- let mut candidates_from_env_and_bounds: Vec<_> = candidates
- .iter()
- .filter(|c| {
- matches!(
- c.source,
- CandidateSource::AliasBound | CandidateSource::ParamEnv(_)
- )
- })
- .map(|c| c.result)
- .collect();
+ let mut considered_candidates = Vec::new();
+ considered_candidates.extend(
+ candidates
+ .iter()
+ .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
+ .map(|c| c.result),
+ );
+
+ // Even when a trait bound has been proven using a where-bound, we
+ // still need to consider alias-bounds for normalization, see
+ // tests/ui/next-solver/alias-bound-shadowed-by-env.rs.
+ //
+ // We still need to prefer where-bounds over alias-bounds however.
+ // See tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs.
+ //
+ // FIXME(const_trait_impl): should this behavior also be used by
+ // constness checking. Doing so is *at least theoretically* breaking,
+ // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
+ if considered_candidates.is_empty() {
+ considered_candidates.extend(
+ candidates
+ .iter()
+ .filter(|c| matches!(c.source, CandidateSource::AliasBound))
+ .map(|c| c.result),
+ );
+ }
// If the trait goal has been proven by using the environment, we want to treat
// aliases as rigid if there are no applicable projection bounds in the environment.
- if candidates_from_env_and_bounds.is_empty() {
+ if considered_candidates.is_empty() {
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
- candidates_from_env_and_bounds.push(response);
+ considered_candidates.push(response);
}
}
- if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) {
+ if let Some(response) = self.try_merge_responses(&considered_candidates) {
Ok(response)
} else {
- self.flounder(&candidates_from_env_and_bounds)
+ self.flounder(&considered_candidates)
}
}
TraitGoalProvenVia::Misc => {
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index c2fb592..1526049 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -5,9 +5,10 @@
use rustc_type_ir::data_structures::HashMap;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::solve::inspect::ProbeKind;
use rustc_type_ir::{
- self as ty, Interner, Movability, Mutability, TypeFoldable, TypeFolder, TypeSuperFoldable,
- Upcast as _, elaborate,
+ self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable,
+ TypeSuperFoldable, Upcast as _, elaborate,
};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use tracing::instrument;
@@ -822,22 +823,16 @@ pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
/// impl Baz for dyn Foo<Item = Ty> {}
/// ```
///
-/// However, in order to make such impls well-formed, we need to do an
+/// However, in order to make such impls non-cyclical, we need to do an
/// additional step of eagerly folding the associated types in the where
/// clauses of the impl. In this example, that means replacing
/// `<Self as Foo>::Bar` with `Ty` in the first impl.
-///
-// FIXME: This is only necessary as `<Self as Trait>::Assoc: ItemBound`
-// bounds in impls are trivially proven using the item bound candidates.
-// This is unsound in general and once that is fixed, we don't need to
-// normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9
-// for more details.
pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
- ecx: &EvalCtxt<'_, D>,
+ ecx: &mut EvalCtxt<'_, D>,
param_env: I::ParamEnv,
trait_ref: ty::TraitRef<I>,
object_bounds: I::BoundExistentialPredicates,
-) -> Vec<Goal<I, I::Predicate>>
+) -> Result<Vec<Goal<I, I::Predicate>>, Ambiguous>
where
D: SolverDelegate<Interner = I>,
I: Interner,
@@ -871,72 +866,130 @@ pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
.extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args));
}
- let mut replace_projection_with = HashMap::default();
+ let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default();
for bound in object_bounds.iter() {
if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
+ // FIXME: We *probably* should replace this with a dummy placeholder,
+ // b/c don't want to replace literal instances of this dyn type that
+ // show up in the bounds, but just ones that come from substituting
+ // `Self` with the dyn type.
let proj = proj.with_self_ty(cx, trait_ref.self_ty());
- let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));
- assert_eq!(
- old_ty,
- None,
- "{:?} has two generic parameters: {:?} and {:?}",
- proj.projection_term,
- proj.term,
- old_ty.unwrap()
- );
+ replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj));
}
}
- let mut folder =
- ReplaceProjectionWith { ecx, param_env, mapping: replace_projection_with, nested: vec![] };
- let folded_requirements = requirements.fold_with(&mut folder);
+ let mut folder = ReplaceProjectionWith {
+ ecx,
+ param_env,
+ self_ty: trait_ref.self_ty(),
+ mapping: &replace_projection_with,
+ nested: vec![],
+ };
- folder
+ let requirements = requirements.try_fold_with(&mut folder)?;
+ Ok(folder
.nested
.into_iter()
- .chain(folded_requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
- .collect()
+ .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause)))
+ .collect())
}
-struct ReplaceProjectionWith<'a, D: SolverDelegate<Interner = I>, I: Interner> {
- ecx: &'a EvalCtxt<'a, D>,
+struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate<Interner = I>> {
+ ecx: &'a mut EvalCtxt<'b, D>,
param_env: I::ParamEnv,
- mapping: HashMap<I::DefId, ty::Binder<I, ty::ProjectionPredicate<I>>>,
+ self_ty: I::Ty,
+ mapping: &'a HashMap<I::DefId, Vec<ty::Binder<I, ty::ProjectionPredicate<I>>>>,
nested: Vec<Goal<I, I::Predicate>>,
}
-impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I>
- for ReplaceProjectionWith<'_, D, I>
+impl<D, I> ReplaceProjectionWith<'_, '_, I, D>
+where
+ D: SolverDelegate<Interner = I>,
+ I: Interner,
{
+ fn projection_may_match(
+ &mut self,
+ source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
+ target_projection: ty::AliasTerm<I>,
+ ) -> bool {
+ source_projection.item_def_id() == target_projection.def_id
+ && self
+ .ecx
+ .probe(|_| ProbeKind::ProjectionCompatibility)
+ .enter(|ecx| -> Result<_, NoSolution> {
+ let source_projection = ecx.instantiate_binder_with_infer(source_projection);
+ ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
+ ecx.try_evaluate_added_goals()
+ })
+ .is_ok()
+ }
+
+ /// Try to replace an alias with the term present in the projection bounds of the self type.
+ /// Returns `Ok<None>` if this alias is not eligible to be replaced, or bail with
+ /// `Err(Ambiguous)` if it's uncertain which projection bound to replace the term with due
+ /// to multiple bounds applying.
+ fn try_eagerly_replace_alias(
+ &mut self,
+ alias_term: ty::AliasTerm<I>,
+ ) -> Result<Option<I::Term>, Ambiguous> {
+ if alias_term.self_ty() != self.self_ty {
+ return Ok(None);
+ }
+
+ let Some(replacements) = self.mapping.get(&alias_term.def_id) else {
+ return Ok(None);
+ };
+
+ // This is quite similar to the `projection_may_match` we use in unsizing,
+ // but here we want to unify a projection predicate against an alias term
+ // so we can replace it with the the projection predicate's term.
+ let mut matching_projections = replacements
+ .iter()
+ .filter(|source_projection| self.projection_may_match(**source_projection, alias_term));
+ let Some(replacement) = matching_projections.next() else {
+ // This shouldn't happen.
+ panic!("could not replace {alias_term:?} with term from from {:?}", self.self_ty);
+ };
+ // FIXME: This *may* have issues with duplicated projections.
+ if matching_projections.next().is_some() {
+ // If there's more than one projection that we can unify here, then we
+ // need to stall until inference constrains things so that there's only
+ // one choice.
+ return Err(Ambiguous);
+ }
+
+ let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
+ self.nested.extend(
+ self.ecx
+ .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
+ .expect("expected to be able to unify goal projection with dyn's projection"),
+ );
+
+ Ok(Some(replacement.term))
+ }
+}
+
+/// Marker for bailing with ambiguity.
+pub(crate) struct Ambiguous;
+
+impl<D, I> FallibleTypeFolder<I> for ReplaceProjectionWith<'_, '_, I, D>
+where
+ D: SolverDelegate<Interner = I>,
+ I: Interner,
+{
+ type Error = Ambiguous;
+
fn cx(&self) -> I {
self.ecx.cx()
}
- fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
+ fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Ambiguous> {
if let ty::Alias(ty::Projection, alias_ty) = ty.kind() {
- if let Some(replacement) = self.mapping.get(&alias_ty.def_id) {
- // We may have a case where our object type's projection bound is higher-ranked,
- // but the where clauses we instantiated are not. We can solve this by instantiating
- // the binder at the usage site.
- let proj = self.ecx.instantiate_binder_with_infer(*replacement);
- // FIXME: Technically this equate could be fallible...
- self.nested.extend(
- self.ecx
- .eq_and_get_goals(
- self.param_env,
- alias_ty,
- proj.projection_term.expect_ty(self.ecx.cx()),
- )
- .expect(
- "expected to be able to unify goal projection with dyn's projection",
- ),
- );
- proj.term.expect_ty()
- } else {
- ty.super_fold_with(self)
+ if let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? {
+ return Ok(term.expect_ty());
}
- } else {
- ty.super_fold_with(self)
}
+
+ ty.try_super_fold_with(self)
}
}
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index 4edc293..d56b0e5 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -355,7 +355,7 @@ fn compute_query_response_instantiation_values<T: ResponseT<I>>(
// exist at all (see the FIXME at the start of this method), we have to deal with
// them for now.
delegate.instantiate_canonical_var_with_infer(info, span, |idx| {
- ty::UniverseIndex::from(prev_universe.index() + idx.index())
+ prev_universe + idx.index()
})
} else if info.is_existential() {
// As an optimization we sometimes avoid creating a new inference variable here.
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 148ba02..9994c85 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -286,18 +286,23 @@ pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind {
// fixing it may cause inference breakage or introduce ambiguity.
GoalSource::Misc => PathKind::Unknown,
GoalSource::NormalizeGoal(path_kind) => path_kind,
- GoalSource::ImplWhereBound => {
+ GoalSource::ImplWhereBound => match self.current_goal_kind {
// We currently only consider a cycle coinductive if it steps
// into a where-clause of a coinductive trait.
+ CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive,
+ // While normalizing via an impl does step into a where-clause of
+ // an impl, accessing the associated item immediately steps out of
+ // it again. This means cycles/recursive calls are not guarded
+ // by impls used for normalization.
//
+ // See tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs
+ // for how this can go wrong.
+ CurrentGoalKind::NormalizesTo => PathKind::Inductive,
// We probably want to make all traits coinductive in the future,
- // so we treat cycles involving their where-clauses as ambiguous.
- if let CurrentGoalKind::CoinductiveTrait = self.current_goal_kind {
- PathKind::Coinductive
- } else {
- PathKind::Unknown
- }
- }
+ // so we treat cycles involving where-clauses of not-yet coinductive
+ // traits as ambiguous for now.
+ CurrentGoalKind::Misc => PathKind::Unknown,
+ },
// Relating types is always unproductive. If we were to map proof trees to
// corecursive functions as explained in #136824, relating types never
// introduces a constructor which could cause the recursion to be guarded.
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 2d027f1..fdeb276 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -45,7 +45,6 @@ pub(super) fn compute_normalizes_to_goal(
goal,
goal.predicate.alias,
);
- this.add_goal(GoalSource::AliasWellFormed, goal.with(cx, trait_ref));
this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
})
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index d42c998..409af85 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -164,6 +164,7 @@ fn consider_auto_trait_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
+ let cx = ecx.cx();
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
return Err(NoSolution);
}
@@ -174,20 +175,37 @@ fn consider_auto_trait_candidate(
// Only consider auto impls of unsafe traits when there are no unsafe
// fields.
- if ecx.cx().trait_is_unsafe(goal.predicate.def_id())
+ if cx.trait_is_unsafe(goal.predicate.def_id())
&& goal.predicate.self_ty().has_unsafe_fields()
{
return Err(NoSolution);
}
- // We only look into opaque types during analysis for opaque types
- // outside of their defining scope. Doing so for opaques in the
- // defining scope may require calling `typeck` on the same item we're
- // currently type checking, which will result in a fatal cycle that
- // ideally we want to avoid, since we can make progress on this goal
- // via an alias bound or a locally-inferred hidden type instead.
+ // We leak the implemented auto traits of opaques outside of their defining scope.
+ // This depends on `typeck` of the defining scope of that opaque, which may result in
+ // fatal query cycles.
+ //
+ // We only get to this point if we're outside of the defining scope as we'd otherwise
+ // be able to normalize the opaque type. We may also cycle in case `typeck` of a defining
+ // scope relies on the current context, e.g. either because it also leaks auto trait
+ // bounds of opaques defined in the current context or by evaluating the current item.
+ //
+ // To avoid this we don't try to leak auto trait bounds if they can also be proven via
+ // item bounds of the opaque. These bounds are always applicable as auto traits must not
+ // have any generic parameters. They would also get preferred over the impl candidate
+ // when merging candidates anyways.
+ //
+ // See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs.
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
+ for item_bound in cx.item_self_bounds(opaque_ty.def_id).skip_binder() {
+ if item_bound
+ .as_trait_clause()
+ .is_some_and(|b| b.def_id() == goal.predicate.def_id())
+ {
+ return Err(NoSolution);
+ }
+ }
}
ecx.probe_and_evaluate_goal_for_constituent_tys(
@@ -926,7 +944,7 @@ fn consider_builtin_upcast_to_principal(
target_projection: ty::Binder<I, ty::ExistentialProjection<I>>| {
source_projection.item_def_id() == target_projection.item_def_id()
&& ecx
- .probe(|_| ProbeKind::UpcastProjectionCompatibility)
+ .probe(|_| ProbeKind::ProjectionCompatibility)
.enter(|ecx| -> Result<_, NoSolution> {
ecx.enter_forall(target_projection, |ecx, target_projection| {
let source_projection =
@@ -1238,10 +1256,11 @@ impl<D, I> EvalCtxt<'_, D>
D: SolverDelegate<Interner = I>,
I: Interner,
{
+ #[instrument(level = "debug", skip(self, goal), ret)]
pub(super) fn merge_trait_candidates(
&mut self,
goal: Goal<I, TraitPredicate<I>>,
- candidates: Vec<Candidate<I>>,
+ mut candidates: Vec<Candidate<I>>,
) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
if let TypingMode::Coherence = self.typing_mode() {
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
@@ -1323,13 +1342,16 @@ pub(super) fn merge_trait_candidates(
// If there are *only* global where bounds, then make sure to return that this
// is still reported as being proven-via the param-env so that rigid projections
- // operate correctly.
+ // operate correctly. Otherwise, drop all global where-bounds before merging the
+ // remaining candidates.
let proven_via =
if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) {
TraitGoalProvenVia::ParamEnv
} else {
+ candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_)));
TraitGoalProvenVia::Misc
};
+
let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect();
if let Some(response) = self.try_merge_responses(&all_candidates) {
Ok((response, Some(proven_via)))
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 93fa89b..e7f17bb 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -543,7 +543,7 @@
.suggestion = types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
parse_maybe_recover_from_bad_type_plus =
- expected a path on the left-hand side of `+`, not `{$ty}`
+ expected a path on the left-hand side of `+`
parse_maybe_report_ambiguous_plus =
ambiguous `+` in a type
@@ -642,7 +642,9 @@
.suggestion = add `mut` to each binding
parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
.suggestion = remove the `mut` prefix
-parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
+
+parse_need_plus_after_trait_object_lifetime = lifetimes must be followed by `+` to form a trait object type
+ .suggestion = consider adding a trait bound after the potential lifetime bound
parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}`
.suggestion = consider creating a new `{$kw_str}` definition instead of nesting
@@ -806,9 +808,6 @@
parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before
.suggestion = move `{$kw}` before the `for<...>`
-parse_type_ascription_removed =
- if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
-
parse_unclosed_unicode_escape = unterminated unicode escape
.label = missing a closing `{"}"}`
.terminate = terminate the unicode escape
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index dfdef01..44b4e1a 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -7,8 +7,7 @@
use rustc_ast::{Path, Visibility};
use rustc_errors::codes::*;
use rustc_errors::{
- Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, SubdiagMessageOp,
- Subdiagnostic,
+ Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::errors::ExprParenthesesNeeded;
@@ -30,7 +29,6 @@ pub(crate) struct AmbiguousPlus {
#[derive(Diagnostic)]
#[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)]
pub(crate) struct BadTypePlus {
- pub ty: String,
#[primary_span]
pub span: Span,
#[subdiagnostic]
@@ -1551,11 +1549,7 @@ pub(crate) struct FnTraitMissingParen {
}
impl Subdiagnostic for FnTraitMissingParen {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
diag.span_suggestion_short(
self.span.shrink_to_hi(),
@@ -1598,9 +1592,6 @@ pub(crate) struct PathSingleColon {
#[suggestion(applicability = "machine-applicable", code = ":", style = "verbose")]
pub suggestion: Span,
-
- #[note(parse_type_ascription_removed)]
- pub type_ascription: bool,
}
#[derive(Diagnostic)]
@@ -1617,9 +1608,6 @@ pub(crate) struct ColonAsSemi {
#[primary_span]
#[suggestion(applicability = "machine-applicable", code = ";", style = "verbose")]
pub span: Span,
-
- #[note(parse_type_ascription_removed)]
- pub type_ascription: bool,
}
#[derive(Diagnostic)]
@@ -2806,6 +2794,8 @@ pub(crate) struct ReturnTypesUseThinArrow {
pub(crate) struct NeedPlusAfterTraitObjectLifetime {
#[primary_span]
pub span: Span,
+ #[suggestion(code = " + /* Trait */", applicability = "has-placeholders")]
+ pub suggestion: Span,
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index ff03b42..2bfa1ea 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -376,7 +376,7 @@ pub(super) fn check_for_substitution(
ascii_name,
})
};
- (token.clone(), sugg)
+ (*token, sugg)
}
/// Extract string if found at current position with given delimiters
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 79939aa..2edc8c8 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -4,7 +4,6 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(box_patterns)]
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index cff998f..f1bd6a2 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -120,7 +120,7 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
// produce an empty `TokenStream` if no calls were made, and omit the
// final token otherwise.
let mut cursor_snapshot = self.cursor_snapshot.clone();
- let tokens = iter::once(FlatToken::Token(self.start_token.clone()))
+ let tokens = iter::once(FlatToken::Token(self.start_token))
.chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next())))
.take(self.num_calls as usize);
@@ -186,7 +186,7 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
impl<'a> Parser<'a> {
pub(super) fn collect_pos(&self) -> CollectPos {
CollectPos {
- start_token: (self.token.clone(), self.token_spacing),
+ start_token: (self.token, self.token_spacing),
cursor_snapshot: self.token_cursor.clone(),
start_pos: self.num_bump_calls,
}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index ef044fe..7c8e014 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -322,7 +322,7 @@ pub(super) fn expected_ident_found(
let mut recovered_ident = None;
// we take this here so that the correct original token is retained in
// the diagnostic, regardless of eager recovery.
- let bad_token = self.token.clone();
+ let bad_token = self.token;
// suggest prepending a keyword in identifier position with `r#`
let suggest_raw = if let Some((ident, IdentIsRaw::No)) = self.token.ident()
@@ -382,7 +382,7 @@ pub(super) fn expected_ident_found(
// if the previous token is a valid keyword
// that might use a generic, then suggest a correct
// generic placement (later on)
- let maybe_keyword = self.prev_token.clone();
+ let maybe_keyword = self.prev_token;
if valid_prev_keywords.into_iter().any(|x| maybe_keyword.is_keyword(x)) {
// if we have a valid keyword, attempt to parse generics
// also obtain the keywords symbol
@@ -530,7 +530,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
// let y = 42;
let guar = self.dcx().emit_err(ExpectedSemi {
span: self.token.span,
- token: self.token.clone(),
+ token: self.token,
unexpected_token_label: None,
sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span),
});
@@ -555,7 +555,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
let span = self.prev_token.span.shrink_to_hi();
let guar = self.dcx().emit_err(ExpectedSemi {
span,
- token: self.token.clone(),
+ token: self.token,
unexpected_token_label: Some(self.token.span),
sugg: ExpectedSemiSugg::AddSemi(span),
});
@@ -609,6 +609,8 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
// FIXME: translation requires list formatting (for `expect`)
let mut err = self.dcx().struct_span_err(self.token.span, msg_exp);
+ self.label_expected_raw_ref(&mut err);
+
// Look for usages of '=>' where '>=' was probably intended
if self.token == token::FatArrow
&& expected.iter().any(|tok| matches!(tok, TokenType::Operator | TokenType::Le))
@@ -750,6 +752,25 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
Err(err)
}
+ /// Adds a label when `&raw EXPR` was written instead of `&raw const EXPR`/`&raw mut EXPR`.
+ ///
+ /// Given that not all parser diagnostics flow through `expected_one_of_not_found`, this
+ /// label may need added to other diagnostics emission paths as needed.
+ pub(super) fn label_expected_raw_ref(&mut self, err: &mut Diag<'_>) {
+ if self.prev_token.is_keyword(kw::Raw)
+ && self.expected_token_types.contains(TokenType::KwMut)
+ && self.expected_token_types.contains(TokenType::KwConst)
+ && self.token.can_begin_expr()
+ {
+ err.span_suggestions(
+ self.prev_token.span.shrink_to_hi(),
+ "`&raw` must be followed by `const` or `mut` to be a raw reference expression",
+ [" const".to_string(), " mut".to_string()],
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+
/// Checks if the current token or the previous token are misspelled keywords
/// and adds a helpful suggestion.
fn check_for_misspelled_kw(&self, err: &mut Diag<'_>, expected: &[TokenType]) {
@@ -801,7 +822,7 @@ pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed {
let span = self.prev_token.span.shrink_to_hi();
let mut err = self.dcx().create_err(ExpectedSemi {
span,
- token: self.token.clone(),
+ token: self.token,
unexpected_token_label: Some(self.token.span),
sugg: ExpectedSemiSugg::AddSemi(span),
});
@@ -1636,19 +1657,19 @@ pub(super) fn maybe_recover_from_bad_type_plus(&mut self, ty: &Ty) -> PResult<'a
self.bump(); // `+`
let _bounds = self.parse_generic_bounds()?;
- let sum_span = ty.span.to(self.prev_token.span);
-
let sub = match &ty.kind {
TyKind::Ref(_lifetime, mut_ty) => {
let lo = mut_ty.ty.span.shrink_to_lo();
let hi = self.prev_token.span.shrink_to_hi();
BadTypePlusSub::AddParen { suggestion: AddParen { lo, hi } }
}
- TyKind::Ptr(..) | TyKind::BareFn(..) => BadTypePlusSub::ForgotParen { span: sum_span },
- _ => BadTypePlusSub::ExpectPath { span: sum_span },
+ TyKind::Ptr(..) | TyKind::BareFn(..) => {
+ BadTypePlusSub::ForgotParen { span: ty.span.to(self.prev_token.span) }
+ }
+ _ => BadTypePlusSub::ExpectPath { span: ty.span },
};
- self.dcx().emit_err(BadTypePlus { ty: pprust::ty_to_string(ty), span: sum_span, sub });
+ self.dcx().emit_err(BadTypePlus { span: ty.span, sub });
Ok(())
}
@@ -1922,10 +1943,7 @@ pub(super) fn recover_colon_as_semi(&mut self) -> bool {
&& self.token == token::Colon
&& self.look_ahead(1, |next| line_idx(self.token.span) < line_idx(next.span))
{
- self.dcx().emit_err(ColonAsSemi {
- span: self.token.span,
- type_ascription: self.psess.unstable_features.is_nightly_build(),
- });
+ self.dcx().emit_err(ColonAsSemi { span: self.token.span });
self.bump();
return true;
}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 9c457f1..71cc814 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -344,7 +344,7 @@ fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
self.dcx().emit_err(errors::FoundExprWouldBeStmt {
span: self.token.span,
- token: self.token.clone(),
+ token: self.token,
suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
});
}
@@ -417,7 +417,7 @@ fn parse_expr_range(
cur_op_span: Span,
) -> PResult<'a, P<Expr>> {
let rhs = if self.is_at_start_of_range_notation_rhs() {
- let maybe_lt = self.token.clone();
+ let maybe_lt = self.token;
let attrs = self.parse_outer_attributes()?;
Some(
self.parse_expr_assoc_with(Bound::Excluded(prec), attrs)
@@ -611,7 +611,7 @@ fn is_mistaken_not_ident_negation(&self) -> bool {
/// Recover on `not expr` in favor of `!expr`.
fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
- let negated_token = self.look_ahead(1, |t| t.clone());
+ let negated_token = self.look_ahead(1, |t| *t);
let sub_diag = if negated_token.is_numeric_lit() {
errors::NotAsNegationOperatorSub::SuggestNotBitwise
@@ -637,9 +637,7 @@ fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
/// Returns the span of expr if it was not interpolated, or the span of the interpolated token.
fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
match self.prev_token.kind {
- TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => {
- self.prev_token.span
- }
+ TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) => self.prev_token.span,
TokenKind::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => {
// `expr.span` is the interpolated span, because invisible open
// and close delims both get marked with the same span, one
@@ -829,6 +827,18 @@ fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
if let Some(lt) = lifetime {
self.error_remove_borrow_lifetime(span, lt.ident.span.until(expr.span));
}
+
+ // Add expected tokens if we parsed `&raw` as an expression.
+ // This will make sure we see "expected `const`, `mut`", and
+ // guides recovery in case we write `&raw expr`.
+ if borrow_kind == ast::BorrowKind::Ref
+ && mutbl == ast::Mutability::Not
+ && matches!(&expr.kind, ExprKind::Path(None, p) if p.is_ident(kw::Raw))
+ {
+ self.expected_token_types.insert(TokenType::KwMut);
+ self.expected_token_types.insert(TokenType::KwConst);
+ }
+
Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
}
@@ -1386,15 +1396,7 @@ fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
let span = self.token.span;
- if let token::Interpolated(nt) = &self.token.kind {
- match &**nt {
- token::NtBlock(block) => {
- let block = block.clone();
- self.bump();
- return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None)));
- }
- };
- } else if let Some(expr) = self.eat_metavar_seq_with_matcher(
+ if let Some(expr) = self.eat_metavar_seq_with_matcher(
|mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
|this| {
// Force collection (as opposed to just `parse_expr`) is required to avoid the
@@ -1415,9 +1417,13 @@ fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
{
return Ok(lit);
- } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| {
- this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))
- }) {
+ } else if let Some(block) =
+ self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block())
+ {
+ return Ok(self.mk_expr(span, ExprKind::Block(block, None)));
+ } else if let Some(path) =
+ self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type))
+ {
return Ok(self.mk_expr(span, ExprKind::Path(None, path)));
}
@@ -1612,7 +1618,7 @@ fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a,
}
fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> {
- let maybe_eq_tok = self.prev_token.clone();
+ let maybe_eq_tok = self.prev_token;
let (qself, path) = if self.eat_lt() {
let lt_span = self.prev_token.span;
let (qself, path) = self.parse_qpath(PathStyle::Expr).map_err(|mut err| {
@@ -1671,7 +1677,7 @@ pub(super) fn parse_expr_labeled(
} else if self.eat_keyword(exp!(Loop)) {
self.parse_expr_loop(label, lo)
} else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
- || self.token.is_whole_block()
+ || self.token.is_metavar_block()
{
self.parse_expr_block(label, lo, BlockCheckMode::Default)
} else if !ate_colon
@@ -1878,13 +1884,15 @@ fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> {
let mut expr = self.parse_expr_opt()?;
if let Some(expr) = &mut expr {
if label.is_some()
- && matches!(
- expr.kind,
+ && match &expr.kind {
ExprKind::While(_, _, None)
- | ExprKind::ForLoop { label: None, .. }
- | ExprKind::Loop(_, None, _)
- | ExprKind::Block(_, None)
- )
+ | ExprKind::ForLoop { label: None, .. }
+ | ExprKind::Loop(_, None, _) => true,
+ ExprKind::Block(block, None) => {
+ matches!(block.rules, BlockCheckMode::Default)
+ }
+ _ => false,
+ }
{
self.psess.buffer_lint(
BREAK_WITH_LABEL_AND_LOOP,
@@ -2073,7 +2081,7 @@ fn handle_missing_lit<L>(
&mut self,
mk_lit_char: impl FnOnce(Symbol, Span) -> L,
) -> PResult<'a, L> {
- let token = self.token.clone();
+ let token = self.token;
let err = |self_: &Self| {
let msg = format!("unexpected token: {}", super::token_descr(&token));
self_.dcx().struct_span_err(token.span, msg)
@@ -2166,10 +2174,15 @@ fn eat_token_lit(&mut self) -> Option<token::Lit> {
let expr = self
.eat_metavar_seq(mv_kind, |this| this.parse_expr())
.expect("metavar seq expr");
- let ast::ExprKind::Lit(token_lit) = expr.kind else {
- panic!("didn't reparse an expr");
- };
- Some(token_lit)
+ if let ast::ExprKind::Lit(token_lit) = expr.kind {
+ Some(token_lit)
+ } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
+ && let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
+ {
+ None
+ } else {
+ panic!("unexpected reparsed expr: {:?}", expr.kind);
+ }
}
_ => None,
}
@@ -2349,7 +2362,7 @@ pub(super) fn parse_expr_block(
}
}
- if self.token.is_whole_block() {
+ if self.token.is_metavar_block() {
self.dcx().emit_err(errors::InvalidBlockMacroSegment {
span: self.token.span,
context: lo.to(self.token.span),
@@ -2374,7 +2387,7 @@ fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
- let before = self.prev_token.clone();
+ let before = self.prev_token;
let binder = if self.check_keyword(exp!(For)) {
let lo = self.token.span;
let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
@@ -2406,8 +2419,8 @@ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
FnRetTy::Default(_) => {
let restrictions =
self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
- let prev = self.prev_token.clone();
- let token = self.token.clone();
+ let prev = self.prev_token;
+ let token = self.token;
let attrs = self.parse_outer_attributes()?;
match self.parse_expr_res(restrictions, attrs) {
Ok((expr, _)) => expr,
@@ -2472,7 +2485,7 @@ fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P<Expr>> {
if self.may_recover()
&& self.token.can_begin_expr()
&& !matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace))
- && !self.token.is_whole_block()
+ && !self.token.is_metavar_block()
{
let snapshot = self.create_snapshot_for_diagnostic();
let restrictions =
@@ -2654,7 +2667,7 @@ fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<
}
} else {
let attrs = self.parse_outer_attributes()?; // For recovery.
- let maybe_fatarrow = self.token.clone();
+ let maybe_fatarrow = self.token;
let block = if self.check(exp!(OpenBrace)) {
self.parse_block()?
} else if let Some(block) = recover_block_from_condition(self) {
@@ -3519,7 +3532,7 @@ fn is_do_catch_block(&self) -> bool {
self.token.is_keyword(kw::Do)
&& self.is_keyword_ahead(1, &[kw::Catch])
&& self
- .look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
+ .look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block())
&& !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
}
@@ -3530,7 +3543,7 @@ fn is_do_yeet(&self) -> bool {
fn is_try_block(&self) -> bool {
self.token.is_keyword(kw::Try)
&& self
- .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
+ .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block())
&& self.token_uninterpolated_span().at_least_rust_2018()
}
@@ -3564,12 +3577,12 @@ fn is_gen_block(&self, kw: Symbol, lookahead: usize) -> bool {
// `async move {`
self.is_keyword_ahead(lookahead + 1, &[kw::Move, kw::Use])
&& self.look_ahead(lookahead + 2, |t| {
- *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()
+ *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()
})
) || (
// `async {`
self.look_ahead(lookahead + 1, |t| {
- *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()
+ *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()
})
))
}
@@ -3862,7 +3875,7 @@ fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
return Err(this.dcx().create_err(errors::ExpectedStructField {
span: this.look_ahead(1, |t| t.span),
ident_span: this.token.span,
- token: this.look_ahead(1, |t| t.clone()),
+ token: this.look_ahead(1, |t| *t),
}));
}
let (ident, expr) = if is_shorthand {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 0650181..39a0291 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1732,8 +1732,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
self.expect_semi()?;
body
} else {
- let err =
- errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone());
+ let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token);
return Err(self.dcx().create_err(err));
};
@@ -2303,7 +2302,7 @@ fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
|| self.token.is_keyword(kw::Union))
&& self.look_ahead(1, |t| t.is_ident())
{
- let kw_token = self.token.clone();
+ let kw_token = self.token;
let kw_str = pprust::token_to_string(&kw_token);
let item = self.parse_item(ForceCollect::No)?;
let mut item = item.unwrap().span;
@@ -2536,7 +2535,7 @@ fn parse_fn_body(
self.expect_semi()?;
*sig_hi = self.prev_token.span;
(AttrVec::new(), None)
- } else if self.check(exp!(OpenBrace)) || self.token.is_whole_block() {
+ } else if self.check(exp!(OpenBrace)) || self.token.is_metavar_block() {
self.parse_block_common(self.token.span, BlockCheckMode::Default, None)
.map(|(attrs, body)| (attrs, Some(body)))?
} else if self.token == token::Eq {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index fafd1b1..2221a26 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -13,7 +13,6 @@
use std::assert_matches::debug_assert_matches;
use std::ops::Range;
-use std::sync::Arc;
use std::{fmt, mem, slice};
use attr_wrapper::{AttrWrapper, UsePreAttrPos};
@@ -24,8 +23,8 @@
use path::PathStyle;
use rustc_ast::ptr::P;
use rustc_ast::token::{
- self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtExprKind, NtPatKind,
- Token, TokenKind,
+ self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, NtExprKind, NtPatKind, Token,
+ TokenKind,
};
use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree};
use rustc_ast::util::case::Case;
@@ -98,21 +97,6 @@ pub enum ForceCollect {
No,
}
-#[macro_export]
-macro_rules! maybe_whole {
- ($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
- #[allow(irrefutable_let_patterns)] // FIXME: temporary
- if let token::Interpolated(nt) = &$p.token.kind
- && let token::$constructor(x) = &**nt
- {
- #[allow(unused_mut)]
- let mut $x = x.clone();
- $p.bump();
- return Ok($e);
- }
- };
-}
-
/// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`.
#[macro_export]
macro_rules! maybe_recover_from_interpolated_ty_qpath {
@@ -342,12 +326,12 @@ fn inlined_next(&mut self) -> (Token, Spacing) {
// below can be removed.
if let Some(tree) = self.curr.curr() {
match tree {
- &TokenTree::Token(ref token, spacing) => {
+ &TokenTree::Token(token, spacing) => {
debug_assert!(!matches!(
token.kind,
token::OpenDelim(_) | token::CloseDelim(_)
));
- let res = (token.clone(), spacing);
+ let res = (token, spacing);
self.curr.bump();
return res;
}
@@ -459,7 +443,6 @@ pub fn token_descr(token: &Token) -> String {
(Some(TokenDescription::MetaVar(kind)), _) => format!("`{kind}` metavariable"),
(None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"),
(None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"),
- (None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.descr()),
(None, _) => format!("`{s}`"),
}
}
@@ -855,8 +838,10 @@ fn check_const_closure(&self) -> bool {
fn check_inline_const(&self, dist: usize) -> bool {
self.is_keyword_ahead(dist, &[kw::Const])
&& self.look_ahead(dist + 1, |t| match &t.kind {
- token::Interpolated(nt) => matches!(&**nt, token::NtBlock(..)),
token::OpenDelim(Delimiter::Brace) => true,
+ token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(
+ MetaVarKind::Block,
+ ))) => true,
_ => false,
})
}
@@ -1402,7 +1387,7 @@ fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
// Avoid const blocks and const closures to be parsed as const items
if (self.check_const_closure() == is_closure)
&& !self
- .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
+ .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block())
&& self.eat_keyword_case(exp!(Const), case)
{
Const::Yes(self.prev_token_uninterpolated_span())
@@ -1532,7 +1517,7 @@ pub fn parse_token_tree(&mut self) -> TokenTree {
_ => {
let prev_spacing = self.token_spacing;
self.bump();
- TokenTree::Token(self.prev_token.clone(), prev_spacing)
+ TokenTree::Token(self.prev_token, prev_spacing)
}
}
}
@@ -1718,7 +1703,7 @@ pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug {
dbg_fmt.field("prev_token", &self.prev_token);
let mut tokens = vec![];
for i in 0..lookahead {
- let tok = self.look_ahead(i, |tok| tok.kind.clone());
+ let tok = self.look_ahead(i, |tok| tok.kind);
let is_eof = tok == TokenKind::Eof;
tokens.push(tok);
if is_eof {
@@ -1759,7 +1744,6 @@ pub fn approx_token_stream_pos(&self) -> u32 {
pub fn token_uninterpolated_span(&self) -> Span {
match &self.token.kind {
token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span,
- token::Interpolated(nt) => nt.use_span(),
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => {
self.look_ahead(1, |t| t.span)
}
@@ -1771,7 +1755,6 @@ pub fn token_uninterpolated_span(&self) -> Span {
pub fn prev_token_uninterpolated_span(&self) -> Span {
match &self.prev_token.kind {
token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span,
- token::Interpolated(nt) => nt.use_span(),
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => {
self.look_ahead(0, |t| t.span)
}
@@ -1828,6 +1811,7 @@ pub enum ParseNtResult {
Ident(Ident, IdentIsRaw),
Lifetime(Ident, IdentIsRaw),
Item(P<ast::Item>),
+ Block(P<ast::Block>),
Stmt(P<ast::Stmt>),
Pat(P<ast::Pat>, NtPatKind),
Expr(P<ast::Expr>, NtExprKind),
@@ -1836,7 +1820,4 @@ pub enum ParseNtResult {
Meta(P<ast::AttrItem>),
Path(P<ast::Path>),
Vis(P<ast::Visibility>),
-
- /// This variant will eventually be removed, along with `Token::Interpolate`.
- Nt(Arc<Nonterminal>),
}
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index b4e540d..b6e89cd 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,14 +1,7 @@
-use std::sync::Arc;
-
-use rustc_ast::HasTokens;
use rustc_ast::ptr::P;
-use rustc_ast::token::Nonterminal::*;
use rustc_ast::token::NtExprKind::*;
use rustc_ast::token::NtPatKind::*;
-use rustc_ast::token::{
- self, Delimiter, InvisibleOrigin, MetaVarKind, Nonterminal, NonterminalKind, Token,
-};
-use rustc_ast_pretty::pprust;
+use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, NonterminalKind, Token};
use rustc_errors::PResult;
use rustc_span::{Ident, kw};
@@ -45,13 +38,6 @@ fn may_be_ident(kind: MetaVarKind) -> bool {
}
}
- /// Old variant of `may_be_ident`. Being phased out.
- fn nt_may_be_ident(nt: &Nonterminal) -> bool {
- match nt {
- NtBlock(_) => false,
- }
- }
-
match kind {
// `expr_2021` and earlier
NonterminalKind::Expr(Expr2021 { .. }) => {
@@ -83,16 +69,12 @@ fn nt_may_be_ident(nt: &Nonterminal) -> bool {
| token::Ident(..)
| token::NtIdent(..)
| token::NtLifetime(..)
- | token::Interpolated(_)
| token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => true,
_ => token.can_begin_type(),
},
NonterminalKind::Block => match &token.kind {
token::OpenDelim(Delimiter::Brace) => true,
token::NtLifetime(..) => true,
- token::Interpolated(nt) => match &**nt {
- NtBlock(_) => true,
- },
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
MetaVarKind::Block
| MetaVarKind::Stmt
@@ -112,7 +94,6 @@ fn nt_may_be_ident(nt: &Nonterminal) -> bool {
},
NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
token::PathSep | token::Ident(..) | token::NtIdent(..) => true,
- token::Interpolated(nt) => nt_may_be_ident(nt),
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => {
may_be_ident(*kind)
}
@@ -136,110 +117,85 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseN
// A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
// which requires having captured tokens available. Since we cannot determine
// in advance whether or not a proc-macro will be (transitively) invoked,
- // we always capture tokens for any `Nonterminal` which needs them.
- let mut nt = match kind {
+ // we always capture tokens for any nonterminal that needs them.
+ match kind {
// Note that TT is treated differently to all the others.
- NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())),
+ NonterminalKind::TT => Ok(ParseNtResult::Tt(self.parse_token_tree())),
NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
- Some(item) => return Ok(ParseNtResult::Item(item)),
- None => {
- return Err(self
- .dcx()
- .create_err(UnexpectedNonterminal::Item(self.token.span)));
- }
+ Some(item) => Ok(ParseNtResult::Item(item)),
+ None => Err(self.dcx().create_err(UnexpectedNonterminal::Item(self.token.span))),
},
NonterminalKind::Block => {
// While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`),
// the ':block' matcher does not support them
- NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
+ Ok(ParseNtResult::Block(self.collect_tokens_no_attrs(|this| this.parse_block())?))
}
NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
- Some(stmt) => return Ok(ParseNtResult::Stmt(P(stmt))),
+ Some(stmt) => Ok(ParseNtResult::Stmt(P(stmt))),
None => {
- return Err(self
- .dcx()
- .create_err(UnexpectedNonterminal::Statement(self.token.span)));
+ Err(self.dcx().create_err(UnexpectedNonterminal::Statement(self.token.span)))
}
},
- NonterminalKind::Pat(pat_kind) => {
- return Ok(ParseNtResult::Pat(
- self.collect_tokens_no_attrs(|this| match pat_kind {
- PatParam { .. } => this.parse_pat_no_top_alt(None, None),
- PatWithOr => this.parse_pat_no_top_guard(
- None,
- RecoverComma::No,
- RecoverColon::No,
- CommaRecoveryMode::EitherTupleOrPipe,
- ),
- })?,
- pat_kind,
- ));
- }
+ NonterminalKind::Pat(pat_kind) => Ok(ParseNtResult::Pat(
+ self.collect_tokens_no_attrs(|this| match pat_kind {
+ PatParam { .. } => this.parse_pat_no_top_alt(None, None),
+ PatWithOr => this.parse_pat_no_top_guard(
+ None,
+ RecoverComma::No,
+ RecoverColon::No,
+ CommaRecoveryMode::EitherTupleOrPipe,
+ ),
+ })?,
+ pat_kind,
+ )),
NonterminalKind::Expr(expr_kind) => {
- return Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind));
+ Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind))
}
NonterminalKind::Literal => {
// The `:literal` matcher does not support attributes.
- return Ok(ParseNtResult::Literal(
+ Ok(ParseNtResult::Literal(
self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?,
- ));
+ ))
}
- NonterminalKind::Ty => {
- return Ok(ParseNtResult::Ty(
- self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
- ));
- }
- // this could be handled like a token, since it is one
+ NonterminalKind::Ty => Ok(ParseNtResult::Ty(
+ self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
+ )),
+ // This could be handled like a token, since it is one.
NonterminalKind::Ident => {
- return if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
+ if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
self.bump();
Ok(ParseNtResult::Ident(ident, is_raw))
} else {
Err(self.dcx().create_err(UnexpectedNonterminal::Ident {
span: self.token.span,
- token: self.token.clone(),
+ token: self.token,
}))
- };
+ }
}
- NonterminalKind::Path => {
- return Ok(ParseNtResult::Path(P(
- self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?
- )));
- }
+ NonterminalKind::Path => Ok(ParseNtResult::Path(P(
+ self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?
+ ))),
NonterminalKind::Meta => {
- return Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?)));
+ Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?)))
}
NonterminalKind::Vis => {
- return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| {
- this.parse_visibility(FollowedByType::Yes)
- })?)));
+ Ok(ParseNtResult::Vis(P(self
+ .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)))
}
NonterminalKind::Lifetime => {
// We want to keep `'keyword` parsing, just like `keyword` is still
// an ident for nonterminal purposes.
- return if let Some((ident, is_raw)) = self.token.lifetime() {
+ if let Some((ident, is_raw)) = self.token.lifetime() {
self.bump();
Ok(ParseNtResult::Lifetime(ident, is_raw))
} else {
Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime {
span: self.token.span,
- token: self.token.clone(),
+ token: self.token,
}))
- };
+ }
}
- };
-
- // If tokens are supported at all, they should be collected.
- if matches!(nt.tokens_mut(), Some(None)) {
- panic!(
- "Missing tokens for nt {:?} at {:?}: {:?}",
- nt,
- nt.use_span(),
- pprust::nonterminal_to_string(&nt)
- );
}
-
- Ok(ParseNtResult::Nt(Arc::new(nt)))
}
}
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 9612f71..d5f469f 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -363,7 +363,7 @@ fn recover_trailing_vert(&mut self, lo: Option<Span>) -> bool {
self.dcx().emit_err(TrailingVertNotAllowed {
span: self.token.span,
start: lo,
- token: self.token.clone(),
+ token: self.token,
note_double_vert: matches!(self.token.kind, token::OrOr),
});
self.bump();
@@ -1519,8 +1519,8 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, PatFieldsRest)
etc = PatFieldsRest::Rest;
let mut etc_sp = self.token.span;
if first_etc_and_maybe_comma_span.is_none() {
- if let Some(comma_tok) = self
- .look_ahead(1, |t| if *t == token::Comma { Some(t.clone()) } else { None })
+ if let Some(comma_tok) =
+ self.look_ahead(1, |&t| if t == token::Comma { Some(t) } else { None })
{
let nw_span = self
.psess
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 9c6830c..0288365 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -273,7 +273,6 @@ pub(super) fn parse_path_segments(
self.dcx().emit_err(PathSingleColon {
span: self.prev_token.span,
suggestion: self.prev_token.span.shrink_to_hi(),
- type_ascription: self.psess.unstable_features.is_nightly_build(),
});
}
continue;
@@ -348,7 +347,6 @@ pub(super) fn parse_path_segment(
err = self.dcx().create_err(PathSingleColon {
span: self.token.span,
suggestion: self.prev_token.span.shrink_to_hi(),
- type_ascription: self.psess.unstable_features.is_nightly_build(),
});
}
// Attempt to find places where a missing `>` might belong.
@@ -393,8 +391,8 @@ pub(super) fn parse_path_segment(
} else {
// `(T, U) -> R`
- let prev_token_before_parsing = self.prev_token.clone();
- let token_before_parsing = self.token.clone();
+ let prev_token_before_parsing = self.prev_token;
+ let token_before_parsing = self.token;
let mut snapshot = None;
if self.may_recover()
&& prev_token_before_parsing == token::PathSep
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index e00fd40..0cc8b60 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -23,8 +23,8 @@
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
Trailing, UsePreAttrPos,
};
-use crate::errors::MalformedLoopLabel;
-use crate::{errors, exp, maybe_whole};
+use crate::errors::{self, MalformedLoopLabel};
+use crate::exp;
impl<'a> Parser<'a> {
/// Parses a statement. This stops just before trailing semicolons on everything but items.
@@ -518,7 +518,11 @@ fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'
let prev = self.prev_token.span;
let sp = self.token.span;
let mut e = self.dcx().struct_span_err(sp, msg);
- let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;
+ self.label_expected_raw_ref(&mut e);
+
+ let do_not_suggest_help = self.token.is_keyword(kw::In)
+ || self.token == token::Colon
+ || self.prev_token.is_keyword(kw::Raw);
// Check to see if the user has written something like
//
@@ -696,9 +700,11 @@ pub(super) fn parse_block_common(
blk_mode: BlockCheckMode,
loop_header: Option<Span>,
) -> PResult<'a, (AttrVec, P<Block>)> {
- maybe_whole!(self, NtBlock, |block| (AttrVec::new(), block));
+ if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) {
+ return Ok((AttrVec::new(), block));
+ }
- let maybe_ident = self.prev_token.clone();
+ let maybe_ident = self.prev_token;
self.maybe_recover_unexpected_block_label(loop_header);
if !self.eat(exp!(OpenBrace)) {
return self.error_block_no_opening_brace();
@@ -765,10 +771,6 @@ pub(crate) fn parse_block_tail(
Applicability::MaybeIncorrect,
);
}
- if self.psess.unstable_features.is_nightly_build() {
- // FIXME(Nilstrieb): Remove this again after a few months.
- err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
- }
}
}
@@ -911,7 +913,7 @@ pub fn parse_full_stmt(
{
if self.token == token::Colon
&& self.look_ahead(1, |token| {
- token.is_whole_block()
+ token.is_metavar_block()
|| matches!(
token.kind,
token::Ident(
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 49ae6cb..2f958f4 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -2554,7 +2554,7 @@ fn look(p: &Parser<'_>, dist: usize, kind: rustc_ast::token::TokenKind) {
// Do the `assert_eq` outside the closure so that `track_caller` works.
// (`#![feature(closure_track_caller)]` + `#[track_caller]` on the closure
// doesn't give the line number in the test below if the assertion fails.)
- let tok = p.look_ahead(dist, |tok| tok.clone());
+ let tok = p.look_ahead(dist, |tok| *tok);
assert_eq!(kind, tok.kind);
}
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 93705da..42ebf26 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -7,7 +7,7 @@
Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
TyKind, UnsafeBinderTy,
};
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::{Applicability, Diag, PResult};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use thin_vec::{ThinVec, thin_vec};
@@ -411,6 +411,9 @@ fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResu
TyKind::Path(None, path) if maybe_bounds => {
self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
}
+ // For `('a) + …`, we know that `'a` in type position already lead to an error being
+ // emitted. To reduce output, let's indirectly suppress E0178 (bad `+` in type) and
+ // other irrelevant consequential errors.
TyKind::TraitObject(bounds, TraitObjectSyntax::None)
if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
{
@@ -425,12 +428,60 @@ fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResu
}
fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
- let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
- let bounds = self.parse_generic_bounds_common(allow_plus)?;
- if lt_no_plus {
- self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
+ // A lifetime only begins a bare trait object type if it is followed by `+`!
+ if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
+ // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait
+ // object type with a leading lifetime bound since that seems very unlikely given the
+ // fact that `dyn`-less trait objects are *semantically* invalid.
+ if self.psess.edition.at_least_rust_2021() {
+ let lt = self.expect_lifetime();
+ let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
+ err.span_label(lo, "expected type");
+ return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
+ Ok(ref_ty) => ref_ty,
+ Err(err) => TyKind::Err(err.emit()),
+ });
+ }
+
+ self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
+ span: lo,
+ suggestion: lo.shrink_to_hi(),
+ });
}
- Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
+ Ok(TyKind::TraitObject(
+ self.parse_generic_bounds_common(allow_plus)?,
+ TraitObjectSyntax::None,
+ ))
+ }
+
+ fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
+ &mut self,
+ lt: Lifetime,
+ lo: Span,
+ mut err: Diag<'cx>,
+ ) -> Result<TyKind, Diag<'cx>> {
+ if !self.may_recover() {
+ return Err(err);
+ }
+ let snapshot = self.create_snapshot_for_diagnostic();
+ let mutbl = self.parse_mutability();
+ match self.parse_ty_no_plus() {
+ Ok(ty) => {
+ err.span_suggestion_verbose(
+ lo.shrink_to_lo(),
+ "you might have meant to write a reference type here",
+ "&",
+ Applicability::MaybeIncorrect,
+ );
+ err.emit();
+ Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
+ }
+ Err(diag) => {
+ diag.cancel();
+ self.restore_snapshot(snapshot);
+ Err(err)
+ }
+ }
}
fn parse_remaining_bounds_path(
@@ -547,7 +598,7 @@ fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
// Recovery
mutbl = Mutability::Mut;
- let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing);
+ let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
self.bump();
self.bump_with((dyn_tok, dyn_tok_sp));
}
@@ -886,7 +937,7 @@ fn can_begin_bound(&mut self) -> bool {
/// ```
fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
let lo = self.token.span;
- let leading_token = self.prev_token.clone();
+ let leading_token = self.prev_token;
let has_parens = self.eat(exp!(OpenParen));
let bound = if self.token.is_lifetime() {
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 6bbd650..b518fca 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -157,7 +157,7 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: &Attribute) {
let attr_item = attr.get_normal_item();
- if safety == AttributeSafety::Unsafe {
+ if let AttributeSafety::Unsafe { unsafe_since } = safety {
if let ast::Safety::Default = attr_item.unsafety {
let path_span = attr_item.path.span;
@@ -167,7 +167,13 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr:
// square bracket respectively.
let diag_span = attr_item.span();
- if attr.span.at_least_rust_2024() {
+ // Attributes can be safe in earlier editions, and become unsafe in later ones.
+ let emit_error = match unsafe_since {
+ None => true,
+ Some(unsafe_since) => attr.span.edition() >= unsafe_since,
+ };
+
+ if emit_error {
psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe {
span: path_span,
suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {
@@ -188,6 +194,12 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr:
}
}
} else if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
+ // Allow (but don't require) `#[unsafe(naked)]` so that compiler-builtins can upgrade to it.
+ // FIXME(#139797): remove this special case when compiler-builtins has upgraded.
+ if attr.has_name(sym::naked) {
+ return;
+ }
+
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
span: unsafe_span,
name: attr_item.path.clone(),
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index bea8680..99789b7 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -404,7 +404,7 @@
passes_invalid_attr_at_crate_level_item =
the inner attribute doesn't annotate this {$kind}
-passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
+passes_invalid_macro_export_arguments = invalid `#[macro_export]` argument
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
@@ -742,9 +742,6 @@
passes_transparent_incompatible =
transparent {$target} cannot have other repr hints
-passes_undefined_naked_function_abi =
- Rust ABI is unsupported in naked functions
-
passes_unknown_external_lang_item =
unknown external lang item: `{$lang_item}`
@@ -774,8 +771,8 @@
.label_orig = any code following this expression is unreachable
.note = this expression has type `{$ty}`, which is uninhabited
-passes_unrecognized_field =
- unrecognized field name `{$name}`
+passes_unrecognized_argument =
+ unrecognized argument
passes_unstable_attr_for_already_stable_feature =
can't mark as unstable using an already stable feature
diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs
index 671b7d7..b139ed6 100644
--- a/compiler/rustc_passes/src/abi_test.rs
+++ b/compiler/rustc_passes/src/abi_test.rs
@@ -9,7 +9,7 @@
use rustc_target::callconv::FnAbi;
use super::layout_test::ensure_wf;
-use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField};
+use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedArgument};
pub fn test_abi(tcx: TyCtxt<'_>) {
if !tcx.features().rustc_attrs() {
@@ -77,8 +77,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
// The `..` are the names of fields to dump.
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
- match meta_item.name_or_empty() {
- sym::debug => {
+ match meta_item.name() {
+ Some(sym::debug) => {
let fn_name = tcx.item_name(item_def_id.into());
tcx.dcx().emit_err(AbiOf {
span: tcx.def_span(item_def_id),
@@ -88,8 +88,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
});
}
- name => {
- tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
+ _ => {
+ tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
}
}
}
@@ -118,8 +118,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
}
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
- match meta_item.name_or_empty() {
- sym::debug => {
+ match meta_item.name() {
+ Some(sym::debug) => {
let ty::FnPtr(sig_tys, hdr) = ty.kind() else {
span_bug!(
meta_item.span(),
@@ -138,7 +138,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
let fn_name = tcx.item_name(item_def_id.into());
tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) });
}
- sym::assert_eq => {
+ Some(sym::assert_eq) => {
let ty::Tuple(fields) = ty.kind() else {
span_bug!(
meta_item.span(),
@@ -188,8 +188,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
});
}
}
- name => {
- tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
+ _ => {
+ tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
}
}
}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 9161b23..cbe5058 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -523,9 +523,9 @@ fn check_optimize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Ta
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
if let Some(list) = attr.meta_item_list() {
for item in list.iter() {
- let sym = item.name_or_empty();
+ let sym = item.name();
match sym {
- sym::address | sym::hwaddress => {
+ Some(s @ sym::address | s @ sym::hwaddress) => {
let is_valid =
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
if !is_valid {
@@ -533,7 +533,7 @@ fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
attr_span: item.span(),
defn_span: span,
accepted_kind: "a function or static",
- attr_str: sym.as_str(),
+ attr_str: s.as_str(),
});
}
}
@@ -544,7 +544,10 @@ fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
attr_span: item.span(),
defn_span: span,
accepted_kind: "a function",
- attr_str: sym.as_str(),
+ attr_str: &match sym {
+ Some(name) => name.to_string(),
+ None => "...".to_string(),
+ },
});
}
}
@@ -561,12 +564,15 @@ fn check_generic_attr(
allowed_target: Target,
) {
if target != allowed_target {
+ let path = attr.path();
+ let path: Vec<_> = path.iter().map(|s| s.as_str()).collect();
+ let attr_name = path.join("::");
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::OnlyHasEffectOn {
- attr_name: attr.name_or_empty(),
+ attr_name,
target_name: allowed_target.name().replace(' ', "_"),
},
);
@@ -589,7 +595,8 @@ fn check_naked(
// * `#[track_caller]`
// * `#[test]`, `#[ignore]`, `#[should_panic]`
//
- // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
+ // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains
+ // accurate.
const ALLOW_LIST: &[rustc_span::Symbol] = &[
// conditional compilation
sym::cfg_trace,
@@ -624,6 +631,21 @@ fn check_naked(
match target {
Target::Fn
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
+ let fn_sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
+ let abi = fn_sig.header.abi;
+ if abi.is_rustic_abi() && !self.tcx.features().naked_functions_rustic_abi() {
+ feature_err(
+ &self.tcx.sess,
+ sym::naked_functions_rustic_abi,
+ fn_sig.span,
+ format!(
+ "`#[naked]` is currently unstable on `extern \"{}\"` functions",
+ abi.as_str()
+ ),
+ )
+ .emit();
+ }
+
for other_attr in attrs {
// this covers "sugared doc comments" of the form `/// ...`
// it does not cover `#[doc = "..."]`, which is handled below
@@ -657,11 +679,11 @@ fn check_naked(
}
}
- if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) {
+ if !other_attr.has_any_name(ALLOW_LIST) {
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
span: other_attr.span(),
naked_span: attr.span(),
- attr: other_attr.name_or_empty(),
+ attr: other_attr.name().unwrap(),
});
return;
@@ -1109,6 +1131,7 @@ fn check_doc_search_unbox(&self, meta: &MetaItemInner, hir_id: HirId) {
ItemKind::Trait(_, _, _, generics, _, items)
if generics.params.len() != 0
|| items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) => {}
+ ItemKind::TyAlias(_, _, generics) if generics.params.len() != 0 => {}
_ => {
self.dcx().emit_err(errors::DocSearchUnboxInvalid { span: meta.span() });
}
@@ -1134,7 +1157,7 @@ fn check_doc_inline(
) {
match target {
Target::Use | Target::ExternCrate => {
- let do_inline = meta.name_or_empty() == sym::inline;
+ let do_inline = meta.has_name(sym::inline);
if let Some((prev_inline, prev_span)) = *specified_inline {
if do_inline != prev_inline {
let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
@@ -1244,8 +1267,8 @@ fn check_attr_crate_level(
fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) {
if let Some(metas) = meta.meta_item_list() {
for i_meta in metas {
- match (i_meta.name_or_empty(), i_meta.meta_item()) {
- (sym::attr | sym::no_crate_inject, _) => {}
+ match (i_meta.name(), i_meta.meta_item()) {
+ (Some(sym::attr | sym::no_crate_inject), _) => {}
(_, Some(m)) => {
self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
@@ -1306,61 +1329,63 @@ fn check_doc_attrs(
if let Some(list) = attr.meta_item_list() {
for meta in &list {
if let Some(i_meta) = meta.meta_item() {
- match i_meta.name_or_empty() {
- sym::alias => {
+ match i_meta.name() {
+ Some(sym::alias) => {
if self.check_attr_not_crate_level(meta, hir_id, "alias") {
self.check_doc_alias(meta, hir_id, target, aliases);
}
}
- sym::keyword => {
+ Some(sym::keyword) => {
if self.check_attr_not_crate_level(meta, hir_id, "keyword") {
self.check_doc_keyword(meta, hir_id);
}
}
- sym::fake_variadic => {
+ Some(sym::fake_variadic) => {
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
self.check_doc_fake_variadic(meta, hir_id);
}
}
- sym::search_unbox => {
+ Some(sym::search_unbox) => {
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
self.check_doc_search_unbox(meta, hir_id);
}
}
- sym::test => {
+ Some(sym::test) => {
if self.check_attr_crate_level(attr, meta, hir_id) {
self.check_test_attr(meta, hir_id);
}
}
- sym::html_favicon_url
- | sym::html_logo_url
- | sym::html_playground_url
- | sym::issue_tracker_base_url
- | sym::html_root_url
- | sym::html_no_source => {
+ Some(
+ sym::html_favicon_url
+ | sym::html_logo_url
+ | sym::html_playground_url
+ | sym::issue_tracker_base_url
+ | sym::html_root_url
+ | sym::html_no_source,
+ ) => {
self.check_attr_crate_level(attr, meta, hir_id);
}
- sym::cfg_hide => {
+ Some(sym::cfg_hide) => {
if self.check_attr_crate_level(attr, meta, hir_id) {
self.check_doc_cfg_hide(meta, hir_id);
}
}
- sym::inline | sym::no_inline => {
+ Some(sym::inline | sym::no_inline) => {
self.check_doc_inline(attr, meta, hir_id, target, specified_inline)
}
- sym::masked => self.check_doc_masked(attr, meta, hir_id, target),
+ Some(sym::masked) => self.check_doc_masked(attr, meta, hir_id, target),
- sym::cfg | sym::hidden | sym::notable_trait => {}
+ Some(sym::cfg | sym::hidden | sym::notable_trait) => {}
- sym::rust_logo => {
+ Some(sym::rust_logo) => {
if self.check_attr_crate_level(attr, meta, hir_id)
&& !self.tcx.features().rustdoc_internals()
{
@@ -2283,7 +2308,7 @@ fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target:
}
fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
- let name = attr.name_or_empty();
+ let name = attr.name().unwrap();
match target {
Target::ExternCrate | Target::Mod => {}
_ => {
@@ -2315,12 +2340,12 @@ fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
attr.span(),
errors::MacroExport::TooManyItems,
);
- } else if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
+ } else if !meta_item_list[0].has_name(sym::local_inner_macros) {
self.tcx.emit_node_span_lint(
INVALID_MACRO_EXPORT_ARGUMENTS,
hir_id,
meta_item_list[0].span(),
- errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() },
+ errors::MacroExport::InvalidArgument,
);
}
} else {
@@ -2365,33 +2390,28 @@ fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
}
// Warn on useless empty attributes.
- let note = if (matches!(
- attr.name_or_empty(),
- sym::macro_use
- | sym::allow
- | sym::expect
- | sym::warn
- | sym::deny
- | sym::forbid
- | sym::feature
- | sym::target_feature
- ) && attr.meta_item_list().is_some_and(|list| list.is_empty()))
+ let note = if attr.has_any_name(&[
+ sym::macro_use,
+ sym::allow,
+ sym::expect,
+ sym::warn,
+ sym::deny,
+ sym::forbid,
+ sym::feature,
+ sym::target_feature,
+ ]) && attr.meta_item_list().is_some_and(|list| list.is_empty())
{
- errors::UnusedNote::EmptyList { name: attr.name_or_empty() }
- } else if matches!(
- attr.name_or_empty(),
- sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
- ) && let Some(meta) = attr.meta_item_list()
+ errors::UnusedNote::EmptyList { name: attr.name().unwrap() }
+ } else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
+ && let Some(meta) = attr.meta_item_list()
&& let [meta] = meta.as_slice()
&& let Some(item) = meta.meta_item()
&& let MetaItemKind::NameValue(_) = &item.kind
&& item.path == sym::reason
{
- errors::UnusedNote::NoLints { name: attr.name_or_empty() }
- } else if matches!(
- attr.name_or_empty(),
- sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
- ) && let Some(meta) = attr.meta_item_list()
+ errors::UnusedNote::NoLints { name: attr.name().unwrap() }
+ } else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
+ && let Some(meta) = attr.meta_item_list()
&& meta.iter().any(|meta| {
meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
})
@@ -2424,7 +2444,7 @@ fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
return;
}
}
- } else if attr.name_or_empty() == sym::default_method_body_is_const {
+ } else if attr.has_name(sym::default_method_body_is_const) {
errors::UnusedNote::DefaultMethodBodyConst
} else {
return;
@@ -2881,10 +2901,11 @@ fn check_duplicates(
if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() {
return;
}
+ let attr_name = attr.name().unwrap();
match duplicates {
DuplicatesOk => {}
WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => {
- match seen.entry(attr.name_or_empty()) {
+ match seen.entry(attr_name) {
Entry::Occupied(mut entry) => {
let (this, other) = if matches!(duplicates, FutureWarnPreceding) {
let to_remove = entry.insert(attr.span());
@@ -2911,7 +2932,7 @@ fn check_duplicates(
}
}
}
- ErrorFollowing | ErrorPreceding => match seen.entry(attr.name_or_empty()) {
+ ErrorFollowing | ErrorPreceding => match seen.entry(attr_name) {
Entry::Occupied(mut entry) => {
let (this, other) = if matches!(duplicates, ErrorPreceding) {
let to_remove = entry.insert(attr.span());
@@ -2919,11 +2940,7 @@ fn check_duplicates(
} else {
(attr.span(), *entry.get())
};
- tcx.dcx().emit_err(errors::UnusedMultiple {
- this,
- other,
- name: attr.name_or_empty(),
- });
+ tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name });
}
Entry::Vacant(entry) => {
entry.insert(attr.span());
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 062d56a..7a7a817 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -28,17 +28,17 @@ fn check_for_debugger_visualizer(&mut self, attr: &Attribute) {
return;
};
- let (visualizer_type, visualizer_path) =
- match (meta_item.name_or_empty(), meta_item.value_str()) {
- (sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value),
- (sym::gdb_script_file, Some(value)) => {
- (DebuggerVisualizerType::GdbPrettyPrinter, value)
- }
- (_, _) => {
- self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
- return;
- }
- };
+ let (visualizer_type, visualizer_path) = match (meta_item.name(), meta_item.value_str())
+ {
+ (Some(sym::natvis_file), Some(value)) => (DebuggerVisualizerType::Natvis, value),
+ (Some(sym::gdb_script_file), Some(value)) => {
+ (DebuggerVisualizerType::GdbPrettyPrinter, value)
+ }
+ (_, _) => {
+ self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
+ return;
+ }
+ };
let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) {
Ok(file) => file,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 4e3e032..4052264 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -5,7 +5,7 @@
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
- MultiSpan, SubdiagMessageOp, Subdiagnostic,
+ MultiSpan, Subdiagnostic,
};
use rustc_hir::{self as hir, ExprKind, Target};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -756,7 +756,7 @@ pub(crate) enum MacroExport {
OnDeclMacro,
#[diag(passes_invalid_macro_export_arguments)]
- UnknownItem { name: Symbol },
+ InvalidArgument,
#[diag(passes_invalid_macro_export_arguments_too_many_items)]
TooManyItems,
@@ -1045,11 +1045,10 @@ pub(crate) struct AbiInvalidAttribute {
}
#[derive(Diagnostic)]
-#[diag(passes_unrecognized_field)]
-pub(crate) struct UnrecognizedField {
+#[diag(passes_unrecognized_argument)]
+pub(crate) struct UnrecognizedArgument {
#[primary_span]
pub span: Span,
- pub name: Symbol,
}
#[derive(Diagnostic)]
@@ -1197,10 +1196,6 @@ pub(crate) struct UnlabeledCfInWhileCondition<'a> {
pub cf_type: &'a str,
}
-#[derive(LintDiagnostic)]
-#[diag(passes_undefined_naked_function_abi)]
-pub(crate) struct UndefinedNakedFunctionAbi;
-
#[derive(Diagnostic)]
#[diag(passes_no_patterns)]
pub(crate) struct NoPatterns {
@@ -1437,7 +1432,7 @@ pub(crate) struct UselessAssignment<'a> {
#[derive(LintDiagnostic)]
#[diag(passes_only_has_effect_on)]
pub(crate) struct OnlyHasEffectOn {
- pub attr_name: Symbol,
+ pub attr_name: String,
pub target_name: String,
}
@@ -1856,11 +1851,7 @@ pub(crate) struct UnusedVariableStringInterp {
}
impl Subdiagnostic for UnusedVariableStringInterp {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation);
diag.multipart_suggestion(
crate::fluent_generated::passes_string_interpolation_only_works,
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index d4512c9..a19faf0 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -13,7 +13,7 @@
use crate::errors::{
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
- LayoutSize, UnrecognizedField,
+ LayoutSize, UnrecognizedArgument,
};
pub fn test_layout(tcx: TyCtxt<'_>) {
@@ -79,28 +79,28 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
// The `..` are the names of fields to dump.
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
- match meta_item.name_or_empty() {
+ match meta_item.name() {
// FIXME: this never was about ABI and now this dump arg is confusing
- sym::abi => {
+ Some(sym::abi) => {
tcx.dcx().emit_err(LayoutAbi {
span,
abi: format!("{:?}", ty_layout.backend_repr),
});
}
- sym::align => {
+ Some(sym::align) => {
tcx.dcx().emit_err(LayoutAlign {
span,
align: format!("{:?}", ty_layout.align),
});
}
- sym::size => {
+ Some(sym::size) => {
tcx.dcx()
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
}
- sym::homogeneous_aggregate => {
+ Some(sym::homogeneous_aggregate) => {
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
span,
homogeneous_aggregate: format!(
@@ -111,15 +111,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
});
}
- sym::debug => {
+ Some(sym::debug) => {
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
// FIXME: using the `Debug` impl here isn't ideal.
let ty_layout = format!("{:#?}", *ty_layout);
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
}
- name => {
- tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
+ _ => {
+ tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
}
}
}
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 6f6115a..93ff0f6 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -6,7 +6,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(let_chains)]
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 06eb76c..4e9b7fd 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -578,8 +578,7 @@ fn write_vars<F>(&self, wr: &mut dyn Write, mut test: F) -> io::Result<()>
where
F: FnMut(Variable) -> bool,
{
- for var_idx in 0..self.ir.var_kinds.len() {
- let var = Variable::from(var_idx);
+ for var in self.ir.var_kinds.indices() {
if test(var) {
write!(wr, " {var:?}")?;
}
@@ -609,8 +608,8 @@ fn log_liveness(&self, entry_ln: LiveNode, hir_id: HirId) {
debug!(
"^^ liveness computation results for body {} (entry={:?})",
{
- for ln_idx in 0..self.ir.lnks.len() {
- debug!("{:?}", self.ln_str(LiveNode::from(ln_idx)));
+ for ln_idx in self.ir.lnks.indices() {
+ debug!("{:?}", self.ln_str(ln_idx));
}
hir_id
},
@@ -1021,7 +1020,10 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
}
hir::ExprKind::Call(ref f, args) => {
- let succ = self.check_is_ty_uninhabited(expr, succ);
+ let is_ctor = |f: &Expr<'_>| matches!(f.kind, hir::ExprKind::Path(hir::QPath::Resolved(_, path)) if matches!(path.res, rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Ctor(_, _), _)));
+ let succ =
+ if !is_ctor(f) { self.check_is_ty_uninhabited(expr, succ) } else { succ };
+
let succ = self.propagate_through_exprs(args, succ);
self.propagate_through_expr(f, succ)
}
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index d35aedf..3c9f8b7 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -1,6 +1,5 @@
//! Checks validity of naked functions.
-use rustc_abi::ExternAbi;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
@@ -10,12 +9,11 @@
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::TyCtxt;
-use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
use rustc_span::{Span, sym};
use crate::errors::{
NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns,
- ParamsNotAllowed, UndefinedNakedFunctionAbi,
+ ParamsNotAllowed,
};
pub(crate) fn provide(providers: &mut Providers) {
@@ -29,26 +27,21 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
continue;
}
- let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) {
+ let body = match tcx.hir_node_by_def_id(def_id) {
hir::Node::Item(hir::Item {
- kind: hir::ItemKind::Fn { sig, body: body_id, .. },
- ..
+ kind: hir::ItemKind::Fn { body: body_id, .. }, ..
})
| hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
+ kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)),
..
})
| hir::Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::Fn(sig, body_id),
- ..
- }) => (sig.header, *body_id),
+ kind: hir::ImplItemKind::Fn(_, body_id), ..
+ }) => tcx.hir_body(*body_id),
_ => continue,
};
- let body = tcx.hir_body(body_id);
-
if tcx.has_attr(def_id, sym::naked) {
- check_abi(tcx, def_id, fn_header.abi);
check_no_patterns(tcx, body.params);
check_no_parameters_use(tcx, body);
check_asm(tcx, def_id, body);
@@ -60,20 +53,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
}
}
-/// Checks that function uses non-Rust ABI.
-fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: ExternAbi) {
- if abi == ExternAbi::Rust {
- let hir_id = tcx.local_def_id_to_hir_id(def_id);
- let span = tcx.def_span(def_id);
- tcx.emit_node_span_lint(
- UNDEFINED_NAKED_FUNCTION_ABI,
- hir_id,
- span,
- UndefinedNakedFunctionAbi,
- );
- }
-}
-
/// Checks that parameters don't use patterns. Mirrors the checks for function declarations.
fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
for param in params {
diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs
index 1f7852e..e60930d 100644
--- a/compiler/rustc_pattern_analysis/src/errors.rs
+++ b/compiler/rustc_pattern_analysis/src/errors.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
+use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic};
use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;
@@ -55,11 +55,7 @@ pub struct Overlap {
}
impl Subdiagnostic for Overlap {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let Overlap { span, range } = self;
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
@@ -103,11 +99,7 @@ pub struct GappedRange {
}
impl Subdiagnostic for GappedRange {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let GappedRange { span, gap, first_range } = self;
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 643b82f..c7bab82 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,6 +1,5 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(associated_type_defaults)]
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 30a9e71..3c329dd 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -3,7 +3,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(unused_parens)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(min_specialization)]
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 56fd3a6..0d56db1 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -1174,8 +1174,7 @@ pub(super) struct CurrentDepGraph<D: Deps> {
/// ID from the previous session. In order to side-step this problem, we make
/// sure that anonymous `NodeId`s allocated in different sessions don't overlap.
/// This is implemented by mixing a session-key into the ID fingerprint of
- /// each anon node. The session-key is just a random number generated when
- /// the `DepGraph` is created.
+ /// each anon node. The session-key is a hash of the number of previous sessions.
anon_id_seed: Fingerprint,
/// These are simple counters that are for profiling and
@@ -1193,12 +1192,8 @@ fn new(
record_stats: bool,
previous: Arc<SerializedDepGraph>,
) -> Self {
- use std::time::{SystemTime, UNIX_EPOCH};
-
- let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
- let nanos = duration.as_nanos();
let mut stable_hasher = StableHasher::new();
- nanos.hash(&mut stable_hasher);
+ previous.session_count().hash(&mut stable_hasher);
let anon_id_seed = stable_hasher.finish();
#[cfg(debug_assertions)]
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 7556a24..ac246284 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -92,6 +92,9 @@ pub struct SerializedDepGraph {
/// Stores a map from fingerprints to nodes per dep node kind.
/// This is the reciprocal of `nodes`.
index: Vec<UnhashMap<PackedFingerprint, SerializedDepNodeIndex>>,
+ /// The number of previous compilation sessions. This is used to generate
+ /// unique anon dep nodes per session.
+ session_count: u64,
}
impl SerializedDepGraph {
@@ -146,6 +149,11 @@ pub fn fingerprint_by_index(&self, dep_node_index: SerializedDepNodeIndex) -> Fi
pub fn node_count(&self) -> usize {
self.nodes.len()
}
+
+ #[inline]
+ pub fn session_count(&self) -> u64 {
+ self.session_count
+ }
}
/// A packed representation of an edge's start index and byte width.
@@ -226,12 +234,12 @@ pub fn decode<D: Deps>(d: &mut MemDecoder<'_>, deps: &D) -> Arc<SerializedDepGra
// If the length of this node's edge list is small, the length is stored in the header.
// If it is not, we fall back to another decoder call.
- let num_edges = node_header.len().unwrap_or_else(|| d.read_usize());
+ let num_edges = node_header.len().unwrap_or_else(|| d.read_u32());
// The edges index list uses the same varint strategy as rmeta tables; we select the
// number of byte elements per-array not per-element. This lets us read the whole edge
// list for a node with one decoder call and also use the on-disk format in memory.
- let edges_len_bytes = node_header.bytes_per_index() * num_edges;
+ let edges_len_bytes = node_header.bytes_per_index() * (num_edges as usize);
// The in-memory structure for the edges list stores the byte width of the edges on
// this node with the offset into the global edge data array.
let edges_header = node_header.edges_header(&edge_list_data);
@@ -252,6 +260,8 @@ pub fn decode<D: Deps>(d: &mut MemDecoder<'_>, deps: &D) -> Arc<SerializedDepGra
.map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default()))
.collect();
+ let session_count = d.read_u64();
+
for (idx, node) in nodes.iter_enumerated() {
if index[node.kind.as_usize()].insert(node.hash, idx).is_some() {
// Side effect nodes can have duplicates
@@ -273,6 +283,7 @@ pub fn decode<D: Deps>(d: &mut MemDecoder<'_>, deps: &D) -> Arc<SerializedDepGra
edge_list_indices,
edge_list_data,
index,
+ session_count,
})
}
}
@@ -296,7 +307,7 @@ struct SerializedNodeHeader<D> {
// The fields of a `SerializedNodeHeader`, this struct is an implementation detail and exists only
// to make the implementation of `SerializedNodeHeader` simpler.
struct Unpacked {
- len: Option<usize>,
+ len: Option<u32>,
bytes_per_index: usize,
kind: DepKind,
hash: PackedFingerprint,
@@ -352,7 +363,7 @@ fn new(
assert_eq!(fingerprint, res.fingerprint());
assert_eq!(node, res.node());
if let Some(len) = res.len() {
- assert_eq!(edge_count, len);
+ assert_eq!(edge_count, len as usize);
}
}
Self { bytes, _marker: PhantomData }
@@ -366,7 +377,7 @@ fn unpack(&self) -> Unpacked {
let kind = head & mask(Self::KIND_BITS) as u16;
let bytes_per_index = (head >> Self::KIND_BITS) & mask(Self::WIDTH_BITS) as u16;
- let len = (head as usize) >> (Self::WIDTH_BITS + Self::KIND_BITS);
+ let len = (head as u32) >> (Self::WIDTH_BITS + Self::KIND_BITS);
Unpacked {
len: len.checked_sub(1),
@@ -378,7 +389,7 @@ fn unpack(&self) -> Unpacked {
}
#[inline]
- fn len(&self) -> Option<usize> {
+ fn len(&self) -> Option<u32> {
self.unpack().len
}
@@ -421,7 +432,8 @@ fn encode<D: Deps>(&self, e: &mut FileEncoder) {
e.write_array(header.bytes);
if header.len().is_none() {
- e.emit_usize(edges.len());
+ // The edges are all unique and the number of unique indices is less than u32::MAX.
+ e.emit_u32(edges.len().try_into().unwrap());
}
let bytes_per_index = header.bytes_per_index();
@@ -456,7 +468,8 @@ fn encode_promoted<D: Deps>(
e.write_array(header.bytes);
if header.len().is_none() {
- e.emit_usize(edge_count);
+ // The edges are all unique and the number of unique indices is less than u32::MAX.
+ e.emit_u32(edge_count.try_into().unwrap());
}
let bytes_per_index = header.bytes_per_index();
@@ -601,7 +614,7 @@ fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
stats: _,
kind_stats,
marker: _,
- previous: _,
+ previous,
} = self;
let node_count = total_node_count.try_into().unwrap();
@@ -612,6 +625,8 @@ fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
count.encode(&mut encoder);
}
+ previous.session_count.checked_add(1).unwrap().encode(&mut encoder);
+
debug!(?node_count, ?edge_count);
debug!("position: {:?}", encoder.position());
IntEncodedWithFixedSize(node_count).encode(&mut encoder);
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 9ea9c58..0fcc3d8 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -18,7 +18,6 @@
rustc_feature = { path = "../rustc_feature" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
-rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 4368f78..cb32802 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1207,7 +1207,7 @@ fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: Nod
for (rule_i, rule_span) in &self.r.macro_map[&def_id.to_def_id()].rule_spans {
self.r
.unused_macro_rules
- .entry(def_id)
+ .entry(node_id)
.or_default()
.insert(*rule_i, (ident, *rule_span));
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 56bc826..363a7591 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -170,10 +170,10 @@ pub(crate) fn report_errors(&mut self, krate: &Crate) {
fn report_with_use_injections(&mut self, krate: &Crate) {
for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in
- self.use_injections.drain(..)
+ std::mem::take(&mut self.use_injections)
{
let (span, found_use) = if let Some(def_id) = def_id.as_local() {
- UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id])
+ UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id))
} else {
(None, FoundUse::No)
};
@@ -1435,7 +1435,7 @@ pub(crate) fn unresolved_macro_suggestions(
let import_suggestions =
self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() {
- Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]),
+ Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)),
None => (None, FoundUse::No),
};
show_candidates(
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 0b3633a..762e08b 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -639,38 +639,38 @@ pub(crate) fn check_hidden_glob_reexports(
}
if let Some(glob_binding) = resolution.shadowed_glob {
- let binding_id = match binding.kind {
- NameBindingKind::Res(res) => {
- Some(self.def_id_to_node_id[res.def_id().expect_local()])
- }
- NameBindingKind::Module(module) => {
- Some(self.def_id_to_node_id[module.def_id().expect_local()])
- }
- NameBindingKind::Import { import, .. } => import.id(),
- };
-
if binding.res() != Res::Err
&& glob_binding.res() != Res::Err
&& let NameBindingKind::Import { import: glob_import, .. } =
glob_binding.kind
- && let Some(binding_id) = binding_id
&& let Some(glob_import_id) = glob_import.id()
&& let glob_import_def_id = self.local_def_id(glob_import_id)
&& self.effective_visibilities.is_exported(glob_import_def_id)
&& glob_binding.vis.is_public()
&& !binding.vis.is_public()
{
- self.lint_buffer.buffer_lint(
- HIDDEN_GLOB_REEXPORTS,
- binding_id,
- binding.span,
- BuiltinLintDiag::HiddenGlobReexports {
- name: key.ident.name.to_string(),
- namespace: key.ns.descr().to_owned(),
- glob_reexport_span: glob_binding.span,
- private_item_span: binding.span,
- },
- );
+ let binding_id = match binding.kind {
+ NameBindingKind::Res(res) => {
+ Some(self.def_id_to_node_id(res.def_id().expect_local()))
+ }
+ NameBindingKind::Module(module) => {
+ Some(self.def_id_to_node_id(module.def_id().expect_local()))
+ }
+ NameBindingKind::Import { import, .. } => import.id(),
+ };
+ if let Some(binding_id) = binding_id {
+ self.lint_buffer.buffer_lint(
+ HIDDEN_GLOB_REEXPORTS,
+ binding_id,
+ binding.span,
+ BuiltinLintDiag::HiddenGlobReexports {
+ name: key.ident.name.to_string(),
+ namespace: key.ns.descr().to_owned(),
+ glob_reexport_span: glob_binding.span,
+ private_item_span: binding.span,
+ },
+ );
+ }
}
}
}
@@ -1012,7 +1012,7 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
// 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = import.module_path.clone();
- full_path.push(Segment::from_ident(Ident::empty()));
+ full_path.push(Segment::from_ident(Ident::dummy()));
self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 1389e8c..bae2fde 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1948,7 +1948,7 @@ fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
self.record_lifetime_res(
anchor_id,
- LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) },
+ LifetimeRes::ElidedAnchor { start: id, end: id + 1 },
LifetimeElisionCandidate::Ignore,
);
self.resolve_anonymous_lifetime(<, anchor_id, true);
@@ -4606,6 +4606,11 @@ fn resolve_qpath(
}
};
+ // Fix up partial res of segment from `resolve_path` call.
+ if let Some(id) = path[0].id {
+ self.r.partial_res_map.insert(id, PartialRes::new(Res::PrimTy(prim)));
+ }
+
PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1)
}
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
@@ -5007,8 +5012,7 @@ fn is_invalid_proc_macro_item_for_doc(&self, did: DefId) -> bool {
return false;
}
let Some(local_did) = did.as_local() else { return true };
- let Some(node_id) = self.r.def_id_to_node_id.get(local_did) else { return true };
- !self.r.proc_macros.contains(node_id)
+ !self.r.proc_macros.contains(&local_did)
}
fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c2761bd..d4fe446 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1994,7 +1994,7 @@ fn suggest_alternative_construction_methods(
.iter()
.flat_map(|i| self.r.tcx.associated_items(i).in_definition_order())
// Only assoc fn with no receivers.
- .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter)
+ .filter(|item| item.is_fn() && !item.is_method())
.filter_map(|item| {
// Only assoc fns that return `Self`
let fn_sig = self.r.tcx.fn_sig(item.def_id).skip_binder();
@@ -2007,8 +2007,9 @@ fn suggest_alternative_construction_methods(
if def.did() != def_id {
return None;
}
- let order = !item.name.as_str().starts_with("new");
- Some((order, item.name, input_len))
+ let name = item.name();
+ let order = !name.as_str().starts_with("new");
+ Some((order, name, input_len))
})
.collect::<Vec<_>>();
items.sort_by_key(|(order, _, _)| *order);
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index e147681..b121755 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -56,7 +56,6 @@
};
use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
use rustc_hir::{PrimTy, TraitCandidate};
-use rustc_index::IndexVec;
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::privacy::EffectiveVisibilities;
@@ -1141,7 +1140,7 @@ pub struct Resolver<'ra, 'tcx> {
ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>>,
unused_macros: FxIndexMap<LocalDefId, (NodeId, Ident)>,
/// A map from the macro to all its potentially unused arms.
- unused_macro_rules: FxIndexMap<LocalDefId, UnordMap<usize, (Ident, Span)>>,
+ unused_macro_rules: FxIndexMap<NodeId, UnordMap<usize, (Ident, Span)>>,
proc_macro_stubs: FxHashSet<LocalDefId>,
/// Traces collected during macro resolution and validated when it's complete.
single_segment_macro_resolutions:
@@ -1184,7 +1183,6 @@ pub struct Resolver<'ra, 'tcx> {
next_node_id: NodeId,
node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
- def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
/// Indices of unnamed struct or variant fields with unresolved attributes.
placeholder_field_indices: FxHashMap<NodeId, usize>,
@@ -1202,7 +1200,7 @@ pub struct Resolver<'ra, 'tcx> {
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
- proc_macros: Vec<NodeId>,
+ proc_macros: Vec<LocalDefId>,
confused_type_with_std_module: FxIndexMap<Span, Span>,
/// Whether lifetime elision was successful.
lifetime_elision_allowed: FxHashSet<NodeId>,
@@ -1339,12 +1337,12 @@ fn create_def(
expn_id: ExpnId,
span: Span,
) -> TyCtxtFeed<'tcx, LocalDefId> {
- let data = def_kind.def_path_data(name);
assert!(
!self.node_id_to_def_id.contains_key(&node_id),
- "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
+ "adding a def for node-id {:?}, name {:?}, data {:?} but a previous def exists: {:?}",
node_id,
- data,
+ name,
+ def_kind,
self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()),
);
@@ -1369,7 +1367,6 @@ fn create_def(
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
self.node_id_to_def_id.insert(node_id, feed.downgrade());
}
- assert_eq!(self.def_id_to_node_id.push(node_id), def_id);
feed
}
@@ -1385,6 +1382,19 @@ fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
pub fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
+
+ /// This function is very slow, as it iterates over the entire
+ /// [Resolver::node_id_to_def_id] map just to find the [NodeId]
+ /// that corresponds to the given [LocalDefId]. Only use this in
+ /// diagnostics code paths.
+ fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
+ self.node_id_to_def_id
+ .items()
+ .filter(|(_, v)| v.key() == def_id)
+ .map(|(k, _)| *k)
+ .get_only()
+ .unwrap()
+ }
}
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
@@ -1417,8 +1427,6 @@ pub fn new(
&mut Default::default(),
);
- let mut def_id_to_node_id = IndexVec::default();
- assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID);
let mut node_id_to_def_id = NodeMap::default();
let crate_feed = tcx.create_local_crate_def_id(crate_span);
@@ -1553,7 +1561,6 @@ pub fn new(
lint_buffer: LintBuffer::default(),
next_node_id: CRATE_NODE_ID,
node_id_to_def_id,
- def_id_to_node_id,
placeholder_field_indices: Default::default(),
invocation_parents,
legacy_const_generic_args: Default::default(),
@@ -1633,7 +1640,7 @@ fn feed_visibility(&mut self, feed: Feed<'tcx, LocalDefId>, vis: ty::Visibility)
}
pub fn into_outputs(self) -> ResolverOutputs {
- let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
+ let proc_macros = self.proc_macros;
let expn_that_defined = self.expn_that_defined;
let extern_crate_map = self.extern_crate_map;
let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
@@ -2000,16 +2007,16 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'ra> {
result,
result.map(|r| r.expn_data())
);
- // Then find the last semi-transparent mark from the end if it exists.
+ // Then find the last semi-opaque mark from the end if it exists.
for (mark, transparency) in iter {
- if transparency == Transparency::SemiTransparent {
+ if transparency == Transparency::SemiOpaque {
result = Some(mark);
} else {
break;
}
}
debug!(
- "resolve_crate_root: found semi-transparent mark {:?} {:?}",
+ "resolve_crate_root: found semi-opaque mark {:?} {:?}",
result,
result.map(|r| r.expn_data())
);
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index e2f783d..749b7f2 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -323,8 +323,7 @@ fn resolve_macro_invocation(
}
fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) {
- let did = self.local_def_id(id);
- if let Some(rules) = self.unused_macro_rules.get_mut(&did) {
+ if let Some(rules) = self.unused_macro_rules.get_mut(&id) {
rules.remove(&rule_i);
}
}
@@ -337,15 +336,12 @@ fn check_unused_macros(&mut self) {
ident.span,
BuiltinLintDiag::UnusedMacroDefinition(ident.name),
);
+ // Do not report unused individual rules if the entire macro is unused
+ self.unused_macro_rules.swap_remove(&node_id);
}
- for (&def_id, unused_arms) in self.unused_macro_rules.iter() {
+ for (&node_id, unused_arms) in self.unused_macro_rules.iter() {
for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() {
- if self.unused_macros.contains_key(&def_id) {
- // We already lint the entire macro as unused
- continue;
- }
- let node_id = self.def_id_to_node_id[def_id];
self.lint_buffer.buffer_lint(
UNUSED_MACRO_RULES,
node_id,
@@ -466,7 +462,7 @@ fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
}
fn declare_proc_macro(&mut self, id: NodeId) {
- self.proc_macros.push(id)
+ self.proc_macros.push(self.local_def_id(id))
}
fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem) {
@@ -932,7 +928,7 @@ pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
.invocation_parents
.get(&parent_scope.expansion)
.map_or(ast::CRATE_NODE_ID, |parent| {
- self.def_id_to_node_id[parent.parent_def]
+ self.def_id_to_node_id(parent.parent_def)
});
self.lint_buffer.buffer_lint(
LEGACY_DERIVE_HELPERS,
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index d56ca9c..4b1b390 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -721,7 +721,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
| hir::definitions::DefPathData::Use
| hir::definitions::DefPathData::GlobalAsm
| hir::definitions::DefPathData::MacroNs(..)
- | hir::definitions::DefPathData::LifetimeNs(..) => {
+ | hir::definitions::DefPathData::LifetimeNs(..)
+ | hir::definitions::DefPathData::AnonAssocTy => {
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
}
});
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 129a32c..d291747 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -240,7 +240,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
.flat_map(|super_poly_trait_ref| {
tcx.associated_items(super_poly_trait_ref.def_id())
.in_definition_order()
- .filter(|item| item.kind == ty::AssocKind::Type)
+ .filter(|item| item.is_type())
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.map(move |assoc_ty| {
super_poly_trait_ref.map_bound(|super_trait_ref| {
@@ -446,7 +446,7 @@ pub(crate) fn transform_instance<'tcx>(
let call = tcx
.associated_items(trait_id)
.in_definition_order()
- .find(|it| it.kind == ty::AssocKind::Fn)
+ .find(|it| it.is_fn())
.expect("No call-family function on closure-like Fn trait?")
.def_id;
diff --git a/compiler/rustc_sanitizers/src/lib.rs b/compiler/rustc_sanitizers/src/lib.rs
index c4a9cab..e479256 100644
--- a/compiler/rustc_sanitizers/src/lib.rs
+++ b/compiler/rustc_sanitizers/src/lib.rs
@@ -4,7 +4,6 @@
//! compiler.
// tidy-alphabetical-start
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(let_chains)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 81f6266..0a55504 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -19,7 +19,7 @@
pub const MAGIC_END_BYTES: &[u8] = b"rust-end-file";
/// The size of the buffer in `FileEncoder`.
-const BUF_SIZE: usize = 8192;
+const BUF_SIZE: usize = 64 * 1024;
/// `FileEncoder` encodes data to file via fixed-size buffer.
///
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index a087725..63772a3 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -7,6 +7,7 @@
# tidy-alphabetical-start
bitflags = "2.4.1"
getopts = "0.2"
+rand = "0.9.0"
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index b4597ae..6b18d45 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -72,7 +72,7 @@ pub struct TypeSizeInfo {
#[derive(Default)]
pub struct CodeStats {
- type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
+ pub type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
}
impl CodeStats {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 56b3fe2..ff7ea5b 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -14,6 +14,7 @@
use std::sync::LazyLock;
use std::{cmp, fmt, fs, iter};
+use externs::{ExternOpt, split_extern_opt};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
use rustc_errors::emitter::HumanReadableErrorType;
@@ -39,6 +40,7 @@
use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
mod cfg;
+mod externs;
mod native_libs;
pub mod sigpipe;
@@ -1015,11 +1017,14 @@ pub fn file_for_writing(
&self,
outputs: &OutputFilenames,
flavor: OutputType,
- codegen_unit_name: Option<&str>,
+ codegen_unit_name: &str,
+ invocation_temp: Option<&str>,
) -> PathBuf {
match *self {
OutFileName::Real(ref path) => path.clone(),
- OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name),
+ OutFileName::Stdout => {
+ outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp)
+ }
}
}
@@ -1094,40 +1099,59 @@ fn output_path(&self, flavor: OutputType) -> PathBuf {
/// Gets the path where a compilation artifact of the given type for the
/// given codegen unit should be placed on disk. If codegen_unit_name is
/// None, a path distinct from those of any codegen unit will be generated.
- pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf {
+ pub fn temp_path_for_cgu(
+ &self,
+ flavor: OutputType,
+ codegen_unit_name: &str,
+ invocation_temp: Option<&str>,
+ ) -> PathBuf {
let extension = flavor.extension();
- self.temp_path_ext(extension, codegen_unit_name)
+ self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp)
}
/// Like `temp_path`, but specifically for dwarf objects.
- pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf {
- self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name)
+ pub fn temp_path_dwo_for_cgu(
+ &self,
+ codegen_unit_name: &str,
+ invocation_temp: Option<&str>,
+ ) -> PathBuf {
+ self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp)
}
/// Like `temp_path`, but also supports things where there is no corresponding
/// OutputType, like noopt-bitcode or lto-bitcode.
- pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf {
- let mut extension = String::new();
+ pub fn temp_path_ext_for_cgu(
+ &self,
+ ext: &str,
+ codegen_unit_name: &str,
+ invocation_temp: Option<&str>,
+ ) -> PathBuf {
+ let mut extension = codegen_unit_name.to_string();
- if let Some(codegen_unit_name) = codegen_unit_name {
- extension.push_str(codegen_unit_name);
+ // Append `.{invocation_temp}` to ensure temporary files are unique.
+ if let Some(rng) = invocation_temp {
+ extension.push('.');
+ extension.push_str(rng);
}
+ // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty.
+ // Append `.rcgu.{ext}`.
if !ext.is_empty() {
- if !extension.is_empty() {
- extension.push('.');
- extension.push_str(RUST_CGU_EXT);
- extension.push('.');
- }
-
+ extension.push('.');
+ extension.push_str(RUST_CGU_EXT);
+ extension.push('.');
extension.push_str(ext);
}
let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
-
self.with_directory_and_extension(temps_directory, &extension)
}
+ pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf {
+ let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
+ self.with_directory_and_extension(temps_directory, &ext)
+ }
+
pub fn with_extension(&self, extension: &str) -> PathBuf {
self.with_directory_and_extension(&self.out_directory, extension)
}
@@ -1144,10 +1168,11 @@ pub fn split_dwarf_path(
&self,
split_debuginfo_kind: SplitDebuginfo,
split_dwarf_kind: SplitDwarfKind,
- cgu_name: Option<&str>,
+ cgu_name: &str,
+ invocation_temp: Option<&str>,
) -> Option<PathBuf> {
- let obj_out = self.temp_path(OutputType::Object, cgu_name);
- let dwo_out = self.temp_path_dwo(cgu_name);
+ let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp);
+ let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp);
match (split_debuginfo_kind, split_dwarf_kind) {
(SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None,
// Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes
@@ -1537,9 +1562,10 @@ pub fn make_opt(
)
});
-static PRINT_KINDS_STRING: LazyLock<String> = LazyLock::new(|| {
+static PRINT_HELP: LazyLock<String> = LazyLock::new(|| {
format!(
- "[{}]",
+ "Compiler information to print on stdout (or to a file)\n\
+ INFO may be one of ({}).",
PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::<Vec<_>>().join("|")
)
});
@@ -1598,14 +1624,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
"Comma separated list of types of output for the compiler to emit",
"[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]",
),
- opt(
- Stable,
- Multi,
- "",
- "print",
- "Compiler information to print on stdout",
- &PRINT_KINDS_STRING,
- ),
+ opt(Stable, Multi, "", "print", &PRINT_HELP, "INFO[=FILE]"),
opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
opt(Stable, Opt, "o", "", "Write output to <filename>", "FILENAME"),
@@ -2046,7 +2065,8 @@ fn collect_print_requests(
check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind));
*print_kind
} else {
- emit_unknown_print_request_help(early_dcx, req)
+ let is_nightly = nightly_options::match_is_nightly_build(matches);
+ emit_unknown_print_request_help(early_dcx, req, is_nightly)
};
let out = out.unwrap_or(OutFileName::Stdout);
@@ -2070,25 +2090,37 @@ fn check_print_request_stability(
unstable_opts: &UnstableOptions,
(print_name, print_kind): (&str, PrintKind),
) {
+ if !is_print_request_stable(print_kind) && !unstable_opts.unstable_options {
+ early_dcx.early_fatal(format!(
+ "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \
+ print option"
+ ));
+ }
+}
+
+fn is_print_request_stable(print_kind: PrintKind) -> bool {
match print_kind {
PrintKind::AllTargetSpecsJson
| PrintKind::CheckCfg
| PrintKind::CrateRootLintLevels
| PrintKind::SupportedCrateTypes
- | PrintKind::TargetSpecJson
- if !unstable_opts.unstable_options =>
- {
- early_dcx.early_fatal(format!(
- "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \
- print option"
- ));
- }
- _ => {}
+ | PrintKind::TargetSpecJson => false,
+ _ => true,
}
}
-fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! {
- let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
+fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! {
+ let prints = PRINT_KINDS
+ .iter()
+ .filter_map(|(name, kind)| {
+ // If we're not on nightly, we don't want to print unstable options
+ if !is_nightly && !is_print_request_stable(*kind) {
+ None
+ } else {
+ Some(format!("`{name}`"))
+ }
+ })
+ .collect::<Vec<_>>();
let prints = prints.join(", ");
let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
@@ -2188,44 +2220,13 @@ pub fn parse_externs(
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
) -> Externs {
- fn is_ascii_ident(string: &str) -> bool {
- let mut chars = string.chars();
- if let Some(start) = chars.next()
- && (start.is_ascii_alphabetic() || start == '_')
- {
- chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
- } else {
- false
- }
- }
-
let is_unstable_enabled = unstable_opts.unstable_options;
let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
for arg in matches.opt_strs("extern") {
- let (name, path) = match arg.split_once('=') {
- None => (arg, None),
- Some((name, path)) => (name.to_string(), Some(Path::new(path))),
- };
- let (options, name) = match name.split_once(':') {
- None => (None, name),
- Some((opts, name)) => (Some(opts), name.to_string()),
- };
+ let ExternOpt { crate_name: name, path, options } =
+ split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit());
- if !is_ascii_ident(&name) {
- let mut error = early_dcx.early_struct_fatal(format!(
- "crate name `{name}` passed to `--extern` is not a valid ASCII identifier"
- ));
- let adjusted_name = name.replace('-', "_");
- if is_ascii_ident(&adjusted_name) {
- #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
- error.help(format!(
- "consider replacing the dashes with underscores: `{adjusted_name}`"
- ));
- }
- error.emit();
- }
-
- let path = path.map(|p| CanonicalizedPath::new(p));
+ let path = path.map(|p| CanonicalizedPath::new(p.as_path()));
let entry = externs.entry(name.to_owned());
diff --git a/compiler/rustc_session/src/config/externs.rs b/compiler/rustc_session/src/config/externs.rs
new file mode 100644
index 0000000..1420ee3
--- /dev/null
+++ b/compiler/rustc_session/src/config/externs.rs
@@ -0,0 +1,79 @@
+//! This module contains code to help parse and manipulate `--extern` arguments.
+
+use std::path::PathBuf;
+
+use rustc_errors::{Diag, FatalAbort};
+
+use super::UnstableOptions;
+use crate::EarlyDiagCtxt;
+
+#[cfg(test)]
+mod tests;
+
+/// Represents the pieces of an `--extern` argument.
+pub(crate) struct ExternOpt {
+ pub(crate) crate_name: String,
+ pub(crate) path: Option<PathBuf>,
+ pub(crate) options: Option<String>,
+}
+
+/// Breaks out the major components of an `--extern` argument.
+///
+/// The options field will be a string containing comma-separated options that will need further
+/// parsing and processing.
+pub(crate) fn split_extern_opt<'a>(
+ early_dcx: &'a EarlyDiagCtxt,
+ unstable_opts: &UnstableOptions,
+ extern_opt: &str,
+) -> Result<ExternOpt, Diag<'a, FatalAbort>> {
+ let (name, path) = match extern_opt.split_once('=') {
+ None => (extern_opt.to_string(), None),
+ Some((name, path)) => (name.to_string(), Some(PathBuf::from(path))),
+ };
+ let (options, crate_name) = match name.split_once(':') {
+ None => (None, name),
+ Some((opts, crate_name)) => {
+ if unstable_opts.namespaced_crates && crate_name.starts_with(':') {
+ // If the name starts with `:`, we know this was actually something like `foo::bar` and
+ // not a set of options. We can just use the original name as the crate name.
+ (None, name)
+ } else {
+ (Some(opts.to_string()), crate_name.to_string())
+ }
+ }
+ };
+
+ if !valid_crate_name(&crate_name, unstable_opts) {
+ let mut error = early_dcx.early_struct_fatal(format!(
+ "crate name `{crate_name}` passed to `--extern` is not a valid ASCII identifier"
+ ));
+ let adjusted_name = crate_name.replace('-', "_");
+ if is_ascii_ident(&adjusted_name) {
+ #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
+ error
+ .help(format!("consider replacing the dashes with underscores: `{adjusted_name}`"));
+ }
+ return Err(error);
+ }
+
+ Ok(ExternOpt { crate_name, path, options })
+}
+
+fn valid_crate_name(name: &str, unstable_opts: &UnstableOptions) -> bool {
+ match name.split_once("::") {
+ Some((a, b)) if unstable_opts.namespaced_crates => is_ascii_ident(a) && is_ascii_ident(b),
+ Some(_) => false,
+ None => is_ascii_ident(name),
+ }
+}
+
+fn is_ascii_ident(string: &str) -> bool {
+ let mut chars = string.chars();
+ if let Some(start) = chars.next()
+ && (start.is_ascii_alphabetic() || start == '_')
+ {
+ chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
+ } else {
+ false
+ }
+}
diff --git a/compiler/rustc_session/src/config/externs/tests.rs b/compiler/rustc_session/src/config/externs/tests.rs
new file mode 100644
index 0000000..6544886
--- /dev/null
+++ b/compiler/rustc_session/src/config/externs/tests.rs
@@ -0,0 +1,92 @@
+use std::path::PathBuf;
+
+use super::split_extern_opt;
+use crate::EarlyDiagCtxt;
+use crate::config::UnstableOptions;
+
+/// Verifies split_extern_opt handles the supported cases.
+#[test]
+fn test_split_extern_opt() {
+ let early_dcx = EarlyDiagCtxt::new(<_>::default());
+ let unstable_opts = &UnstableOptions::default();
+
+ let extern_opt =
+ split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo=libbar.rlib").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo");
+ assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
+ assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
+
+ let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo");
+ assert_eq!(extern_opt.path, None);
+ assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
+
+ let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo=libbar.rlib").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo");
+ assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
+ assert_eq!(extern_opt.options, None);
+
+ let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo");
+ assert_eq!(extern_opt.path, None);
+ assert_eq!(extern_opt.options, None);
+}
+
+/// Tests some invalid cases for split_extern_opt.
+#[test]
+fn test_split_extern_opt_invalid() {
+ let early_dcx = EarlyDiagCtxt::new(<_>::default());
+ let unstable_opts = &UnstableOptions::default();
+
+ // too many `:`s
+ let result = split_extern_opt(&early_dcx, unstable_opts, "priv:noprelude:foo=libbar.rlib");
+ assert!(result.is_err());
+ let _ = result.map_err(|e| e.cancel());
+
+ // can't nest externs without the unstable flag
+ let result = split_extern_opt(&early_dcx, unstable_opts, "noprelude:foo::bar=libbar.rlib");
+ assert!(result.is_err());
+ let _ = result.map_err(|e| e.cancel());
+}
+
+/// Tests some cases for split_extern_opt with nested crates like `foo::bar`.
+#[test]
+fn test_split_extern_opt_nested() {
+ let early_dcx = EarlyDiagCtxt::new(<_>::default());
+ let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() };
+
+ let extern_opt =
+ split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar=libbar.rlib").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo::bar");
+ assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
+ assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
+
+ let extern_opt =
+ split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo::bar");
+ assert_eq!(extern_opt.path, None);
+ assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
+
+ let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar=libbar.rlib").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo::bar");
+ assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
+ assert_eq!(extern_opt.options, None);
+
+ let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar").unwrap();
+ assert_eq!(extern_opt.crate_name, "foo::bar");
+ assert_eq!(extern_opt.path, None);
+ assert_eq!(extern_opt.options, None);
+}
+
+/// Tests some invalid cases for split_extern_opt with nested crates like `foo::bar`.
+#[test]
+fn test_split_extern_opt_nested_invalid() {
+ let early_dcx = EarlyDiagCtxt::new(<_>::default());
+ let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() };
+
+ // crates can only be nested one deep.
+ let result =
+ split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar::baz=libbar.rlib");
+ assert!(result.is_err());
+ let _ = result.map_err(|e| e.cancel());
+}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c70f150..1b0794f 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1956,6 +1956,9 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
"allow the linker to link its default libraries (default: no)"),
dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"import library generation tool (ignored except when targeting windows-gnu)"),
+ #[rustc_lint_opt_deny_field_access("use `Session::dwarf_version` instead of this field")]
+ dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
+ "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
embed_bitcode: bool = (true, parse_bool, [TRACKED],
"emit bitcode in rlibs (default: yes)"),
extra_filename: String = (String::new(), parse_string, [UNTRACKED],
@@ -2331,6 +2334,8 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
"the size at which the `large_assignments` lint starts to be emitted"),
mutable_noalias: bool = (true, parse_bool, [TRACKED],
"emit noalias metadata for mutable references (default: yes)"),
+ namespaced_crates: bool = (false, parse_bool, [TRACKED],
+ "allow crates to be namespaced by other crates (default: no)"),
next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED],
"enable and configure the next generation trait solver used by rustc"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index a24919e..46dae91 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -177,6 +177,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C
// If we're generating a test executable, then ignore all other output
// styles at all other locations
if session.opts.test {
+ if !session.target.executables {
+ session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget {
+ crate_type: CrateType::Executable,
+ target_triple: &session.opts.target_triple,
+ });
+ return Vec::new();
+ }
return vec![CrateType::Executable];
}
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index fb4a437..010ae42 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -6,6 +6,8 @@
use std::sync::atomic::AtomicBool;
use std::{env, fmt, io};
+use rand::{RngCore, rng};
+use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
@@ -203,6 +205,14 @@ pub struct Session {
target_filesearch: FileSearch,
host_filesearch: FileSearch,
+
+ /// A random string generated per invocation of rustc.
+ ///
+ /// This is prepended to all temporary files so that they do not collide
+ /// during concurrent invocations of rustc, or past invocations that were
+ /// preserved with a flag like `-C save-temps`, since these files may be
+ /// hard linked.
+ pub invocation_temp: Option<String>,
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -754,7 +764,11 @@ pub fn split_debuginfo(&self) -> SplitDebuginfo {
/// Returns the DWARF version passed on the CLI or the default for the target.
pub fn dwarf_version(&self) -> u32 {
- self.opts.unstable_opts.dwarf_version.unwrap_or(self.target.default_dwarf_version)
+ self.opts
+ .cg
+ .dwarf_version
+ .or(self.opts.unstable_opts.dwarf_version)
+ .unwrap_or(self.target.default_dwarf_version)
}
pub fn stack_protector(&self) -> StackProtector {
@@ -1117,6 +1131,12 @@ pub fn build_session(
let target_filesearch =
filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target);
let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host);
+
+ let invocation_temp = sopts
+ .incremental
+ .as_ref()
+ .map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string());
+
let sess = Session {
target,
host,
@@ -1140,6 +1160,7 @@ pub fn build_session(
expanded_args,
target_filesearch,
host_filesearch,
+ invocation_temp,
};
validate_commandline_args_with_session_available(&sess);
@@ -1310,7 +1331,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
sess.dcx().emit_err(errors::BranchProtectionRequiresAArch64);
}
- if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
+ if let Some(dwarf_version) =
+ sess.opts.cg.dwarf_version.or(sess.opts.unstable_opts.dwarf_version)
+ {
// DWARF 1 is not supported by LLVM and DWARF 6 is not yet finalized.
if dwarf_version < 2 || dwarf_version > 5 {
sess.dcx().emit_err(errors::UnsupportedDwarfVersion { dwarf_version });
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index 5d465bc..77e5f34 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -9,7 +9,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::usage_of_ty_tykind)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
test(attr(allow(unused_variables), deny(warnings)))
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index a546a44..146ba17 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -244,6 +244,7 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
/// ```ignore(needs-extern-crate)
/// # extern crate rustc_driver;
/// # extern crate rustc_interface;
+/// # extern crate rustc_middle;
/// # #[macro_use]
/// # extern crate rustc_smir;
/// # extern crate stable_mir;
@@ -264,6 +265,7 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
/// ```ignore(needs-extern-crate)
/// # extern crate rustc_driver;
/// # extern crate rustc_interface;
+/// # extern crate rustc_middle;
/// # #[macro_use]
/// # extern crate rustc_smir;
/// # extern crate stable_mir;
@@ -328,6 +330,7 @@ macro_rules! run_driver {
use rustc_driver::{Callbacks, Compilation, run_compiler};
use rustc_middle::ty::TyCtxt;
use rustc_interface::interface;
+ use rustc_smir::rustc_internal;
use stable_mir::CompilerError;
use std::ops::ControlFlow;
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 28fc68d..a757329 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -894,12 +894,21 @@ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
impl<'tcx> Stable<'tcx> for ty::AssocKind {
type T = stable_mir::ty::AssocKind;
- fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
- use stable_mir::ty::AssocKind;
- match self {
- ty::AssocKind::Const => AssocKind::Const,
- ty::AssocKind::Fn => AssocKind::Fn,
- ty::AssocKind::Type => AssocKind::Type,
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+ use stable_mir::ty::{AssocKind, AssocTypeData};
+ match *self {
+ ty::AssocKind::Const { name } => AssocKind::Const { name: name.to_string() },
+ ty::AssocKind::Fn { name, has_self } => {
+ AssocKind::Fn { name: name.to_string(), has_self }
+ }
+ ty::AssocKind::Type { data } => AssocKind::Type {
+ data: match data {
+ ty::AssocTypeData::Normal(name) => AssocTypeData::Normal(name.to_string()),
+ ty::AssocTypeData::Rpitit(rpitit) => {
+ AssocTypeData::Rpitit(rpitit.stable(tables))
+ }
+ },
+ },
}
}
}
@@ -922,12 +931,9 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem {
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
stable_mir::ty::AssocItem {
def_id: tables.assoc_def(self.def_id),
- name: self.name.to_string(),
kind: self.kind.stable(tables),
container: self.container.stable(tables),
trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)),
- fn_has_self_parameter: self.fn_has_self_parameter,
- opt_rpitit_info: self.opt_rpitit_info.map(|rpitit| rpitit.stable(tables)),
}
}
}
diff --git a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs
index 439ebe9..8a6be0c 100644
--- a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs
+++ b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs
@@ -22,9 +22,10 @@ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
impl Display for AssocKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
- AssocKind::Fn => write!(f, "method"),
- AssocKind::Const => write!(f, "associated const"),
- AssocKind::Type => write!(f, "associated type"),
+ AssocKind::Fn { has_self: true, .. } => write!(f, "method"),
+ AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"),
+ AssocKind::Const { .. } => write!(f, "associated const"),
+ AssocKind::Type { .. } => write!(f, "associated type"),
}
}
}
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 3fcbbb0..4b15300 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1578,29 +1578,28 @@ fn to_index(&self) -> usize {
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct AssocItem {
pub def_id: AssocDef,
- pub name: Symbol,
pub kind: AssocKind,
pub container: AssocItemContainer,
/// If this is an item in an impl of a trait then this is the `DefId` of
/// the associated item on the trait that this implements.
pub trait_item_def_id: Option<AssocDef>,
+}
- /// Whether this is a method with an explicit self
- /// as its first parameter, allowing method calls.
- pub fn_has_self_parameter: bool,
-
- /// `Some` if the associated item (an associated type) comes from the
- /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
- /// provides additional information about its source.
- pub opt_rpitit_info: Option<ImplTraitInTraitData>,
+#[derive(Clone, PartialEq, Debug, Eq, Serialize)]
+pub enum AssocTypeData {
+ Normal(Symbol),
+ /// The associated type comes from an RPITIT. It has no name, and the
+ /// `ImplTraitInTraitData` provides additional information about its
+ /// source.
+ Rpitit(ImplTraitInTraitData),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub enum AssocKind {
- Const,
- Fn,
- Type,
+ Const { name: Symbol },
+ Fn { name: Symbol, has_self: bool },
+ Type { data: AssocTypeData },
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
@@ -1617,6 +1616,6 @@ pub enum ImplTraitInTraitData {
impl AssocItem {
pub fn is_impl_trait_in_trait(&self) -> bool {
- self.opt_rpitit_info.is_some()
+ matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) })
}
}
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 9be16f8..d1da68e 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -56,44 +56,33 @@ impl !PartialOrd for SyntaxContext {}
/// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal.
/// The other fields are only for caching.
-type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
+pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
#[derive(Clone, Copy, Debug)]
struct SyntaxContextData {
outer_expn: ExpnId,
outer_transparency: Transparency,
parent: SyntaxContext,
- /// This context, but with all transparent and semi-transparent expansions filtered away.
+ /// This context, but with all transparent and semi-opaque expansions filtered away.
opaque: SyntaxContext,
/// This context, but with all transparent expansions filtered away.
- opaque_and_semitransparent: SyntaxContext,
+ opaque_and_semiopaque: SyntaxContext,
/// Name of the crate to which `$crate` with this context would resolve.
dollar_crate_name: Symbol,
}
-/// Same as `SyntaxContextData`, but `opaque(_and_semitransparent)` cannot be recursive
-/// and use `None` if they need to refer to self. Used for encoding and decoding metadata.
-#[derive(Encodable, Decodable)]
-pub struct SyntaxContextDataNonRecursive {
- outer_expn: ExpnId,
- outer_transparency: Transparency,
- parent: SyntaxContext,
- opaque: Option<SyntaxContext>,
- opaque_and_semitransparent: Option<SyntaxContext>,
-}
-
impl SyntaxContextData {
fn new(
(parent, outer_expn, outer_transparency): SyntaxContextKey,
opaque: SyntaxContext,
- opaque_and_semitransparent: SyntaxContext,
+ opaque_and_semiopaque: SyntaxContext,
) -> SyntaxContextData {
SyntaxContextData {
outer_expn,
outer_transparency,
parent,
opaque,
- opaque_and_semitransparent,
+ opaque_and_semiopaque,
dollar_crate_name: kw::DollarCrate,
}
}
@@ -104,7 +93,7 @@ fn root() -> SyntaxContextData {
outer_transparency: Transparency::Opaque,
parent: SyntaxContext::root(),
opaque: SyntaxContext::root(),
- opaque_and_semitransparent: SyntaxContext::root(),
+ opaque_and_semiopaque: SyntaxContext::root(),
dollar_crate_name: kw::DollarCrate,
}
}
@@ -122,19 +111,6 @@ fn key(&self) -> SyntaxContextKey {
}
}
-impl SyntaxContextDataNonRecursive {
- fn recursive(&self, ctxt: SyntaxContext) -> SyntaxContextData {
- SyntaxContextData {
- outer_expn: self.outer_expn,
- outer_transparency: self.outer_transparency,
- parent: self.parent,
- opaque: self.opaque.unwrap_or(ctxt),
- opaque_and_semitransparent: self.opaque_and_semitransparent.unwrap_or(ctxt),
- dollar_crate_name: kw::DollarCrate,
- }
- }
-}
-
rustc_index::newtype_index! {
/// A unique ID associated with a macro invocation and expansion.
#[orderable]
@@ -228,13 +204,13 @@ pub enum Transparency {
/// Identifier produced by a transparent expansion is always resolved at call-site.
/// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
Transparent,
- /// Identifier produced by a semi-transparent expansion may be resolved
+ /// Identifier produced by a semi-opaque expansion may be resolved
/// either at call-site or at definition-site.
/// If it's a local variable, label or `$crate` then it's resolved at def-site.
/// Otherwise it's resolved at call-site.
/// `macro_rules` macros behave like this, built-in macros currently behave like this too,
/// but that's an implementation detail.
- SemiTransparent,
+ SemiOpaque,
/// Identifier produced by an opaque expansion is always resolved at definition-site.
/// Def-site spans in procedural macros, identifiers from `macro` by default use this.
Opaque,
@@ -242,7 +218,7 @@ pub enum Transparency {
impl Transparency {
pub fn fallback(macro_rules: bool) -> Self {
- if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque }
+ if macro_rules { Transparency::SemiOpaque } else { Transparency::Opaque }
}
}
@@ -490,7 +466,7 @@ fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
- self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
+ self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque
}
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
@@ -583,7 +559,7 @@ fn apply_mark(
}
let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
- let mut call_site_ctxt = if transparency == Transparency::SemiTransparent {
+ let mut call_site_ctxt = if transparency == Transparency::SemiOpaque {
self.normalize_to_macros_2_0(call_site_ctxt)
} else {
self.normalize_to_macro_rules(call_site_ctxt)
@@ -629,48 +605,34 @@ fn alloc_ctxt(
self.syntax_context_data.push(SyntaxContextData::decode_placeholder());
self.syntax_context_map.insert(key, ctxt);
- // Opaque and semi-transparent versions of the parent. Note that they may be equal to the
+ // Opaque and semi-opaque versions of the parent. Note that they may be equal to the
// parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques,
- // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques
- // and semi-transparents.
+ // and `parent_opaque_and_semiopaque` == `parent` if the expn contains only (semi-)opaques.
let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque;
- let parent_opaque_and_semitransparent =
- self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent;
+ let parent_opaque_and_semiopaque =
+ self.syntax_context_data[parent.0 as usize].opaque_and_semiopaque;
- // Evaluate opaque and semi-transparent versions of the new syntax context.
- let (opaque, opaque_and_semitransparent) = match transparency {
- Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent),
- Transparency::SemiTransparent => (
+ // Evaluate opaque and semi-opaque versions of the new syntax context.
+ let (opaque, opaque_and_semiopaque) = match transparency {
+ Transparency::Transparent => (parent_opaque, parent_opaque_and_semiopaque),
+ Transparency::SemiOpaque => (
parent_opaque,
- // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
- self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+ // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques.
+ self.alloc_ctxt(parent_opaque_and_semiopaque, expn_id, transparency),
),
Transparency::Opaque => (
// Will be the same as `ctxt` if the expn chain contains only opaques.
self.alloc_ctxt(parent_opaque, expn_id, transparency),
- // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents.
- self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency),
+ // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques.
+ self.alloc_ctxt(parent_opaque_and_semiopaque, expn_id, transparency),
),
};
// Fill the full data, now that we have it.
self.syntax_context_data[ctxt.as_u32() as usize] =
- SyntaxContextData::new(key, opaque, opaque_and_semitransparent);
+ SyntaxContextData::new(key, opaque, opaque_and_semiopaque);
ctxt
}
-
- fn non_recursive_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContextDataNonRecursive {
- debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder());
- let data = &self.syntax_context_data[ctxt.0 as usize];
- SyntaxContextDataNonRecursive {
- outer_expn: data.outer_expn,
- outer_transparency: data.outer_transparency,
- parent: data.parent,
- opaque: (data.opaque != ctxt).then_some(data.opaque),
- opaque_and_semitransparent: (data.opaque_and_semitransparent != ctxt)
- .then_some(data.opaque_and_semitransparent),
- }
- }
}
pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
@@ -1300,7 +1262,7 @@ pub fn schedule_expn_data_for_encoding(&self, expn: ExpnId) {
pub fn encode<T>(
&self,
encoder: &mut T,
- mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextDataNonRecursive),
+ mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey),
mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash),
) {
// When we serialize a `SyntaxContextData`, we may end up serializing
@@ -1425,10 +1387,7 @@ pub fn decode_expn_id(
// to track which `SyntaxContext`s we have already decoded.
// The provided closure will be invoked to deserialize a `SyntaxContextData`
// if we haven't already seen the id of the `SyntaxContext` we are deserializing.
-pub fn decode_syntax_context<
- D: Decoder,
- F: FnOnce(&mut D, u32) -> SyntaxContextDataNonRecursive,
->(
+pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContextKey>(
d: &mut D,
context: &HygieneDecodeContext,
decode_data: F,
@@ -1450,16 +1409,9 @@ pub fn decode_syntax_context<
// Don't try to decode data while holding the lock, since we need to
// be able to recursively decode a SyntaxContext
- let ctxt_data = decode_data(d, raw_id);
-
- let ctxt = HygieneData::with(|hygiene_data| {
- let ctxt_key = (ctxt_data.parent, ctxt_data.outer_expn, ctxt_data.outer_transparency);
- *hygiene_data.syntax_context_map.entry(ctxt_key).or_insert_with(|| {
- let ctxt = SyntaxContext::from_usize(hygiene_data.syntax_context_data.len());
- hygiene_data.syntax_context_data.push(ctxt_data.recursive(ctxt));
- ctxt
- })
- });
+ let (parent, expn_id, transparency) = decode_data(d, raw_id);
+ let ctxt =
+ HygieneData::with(|hygiene_data| hygiene_data.alloc_ctxt(parent, expn_id, transparency));
let mut inner = context.inner.lock();
let new_len = raw_id as usize + 1;
@@ -1471,12 +1423,21 @@ pub fn decode_syntax_context<
ctxt
}
-fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &SyntaxContextDataNonRecursive)>(
+fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &SyntaxContextKey)>(
ctxts: impl Iterator<Item = SyntaxContext>,
mut f: F,
) {
- let all_data: Vec<_> =
- HygieneData::with(|data| ctxts.map(|ctxt| (ctxt, data.non_recursive_ctxt(ctxt))).collect());
+ let all_data: Vec<_> = HygieneData::with(|data| {
+ ctxts
+ .map(|ctxt| {
+ (ctxt, {
+ let item = data.syntax_context_data[ctxt.0 as usize];
+ debug_assert!(!item.is_decode_placeholder());
+ item.key()
+ })
+ })
+ .collect()
+ });
for (ctxt, data) in all_data.into_iter() {
f(ctxt.0, ctxt, &data);
}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index c95c03b..f788fd4 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1117,7 +1117,7 @@ pub fn with_call_site_ctxt(self, expn_id: ExpnId) -> Span {
/// Equivalent of `Span::mixed_site` from the proc macro API,
/// except that the location is taken from the `self` span.
pub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span {
- self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent)
+ self.with_ctxt_from_mark(expn_id, Transparency::SemiOpaque)
}
/// Produces a span with the same location as `self` and context produced by a macro with the
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 6fdf8e4..0273bb0 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -633,6 +633,24 @@ pub fn span_extend_to_prev_char(&self, sp: Span, c: char, accept_newlines: bool)
sp
}
+ /// Extends the given `Span` to just before the previous occurrence of `c`. Return the same span
+ /// if an error occurred while retrieving the code snippet.
+ pub fn span_extend_to_prev_char_before(
+ &self,
+ sp: Span,
+ c: char,
+ accept_newlines: bool,
+ ) -> Span {
+ if let Ok(prev_source) = self.span_to_prev_source(sp) {
+ let prev_source = prev_source.rsplit(c).next().unwrap_or("");
+ if accept_newlines || !prev_source.contains('\n') {
+ return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32 - 1_u32));
+ }
+ }
+
+ sp
+ }
+
/// Extends the given `Span` to just after the previous occurrence of `pat` when surrounded by
/// whitespace. Returns None if the pattern could not be found or if an error occurred while
/// retrieving the code snippet.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6bf7430..f7b10d3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -454,6 +454,7 @@
and_then,
anon,
anon_adt,
+ anon_assoc,
anonymous_lifetime_in_impl_trait,
any,
append_const_msg,
@@ -915,6 +916,7 @@
expf16,
expf32,
expf64,
+ explicit_extern_abis,
explicit_generic_args_with_impl_trait,
explicit_tail_calls,
export_name,
@@ -1067,7 +1069,6 @@
ge,
gen_blocks,
gen_future,
- gen_kill,
generator_clone,
generators,
generic_arg_infer,
@@ -1185,6 +1186,7 @@
instruction_set,
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
integral,
+ internal_features,
into_async_iter_into_iter,
into_future,
into_iter,
@@ -1399,6 +1401,7 @@
naked,
naked_asm,
naked_functions,
+ naked_functions_rustic_abi,
naked_functions_target_feature,
name,
names,
@@ -1881,6 +1884,7 @@
select_unpredictable,
self_in_typedefs,
self_struct_ctor,
+ semiopaque,
semitransparent,
sha2,
sha3,
@@ -2213,7 +2217,8 @@
unsafe_extern_blocks,
unsafe_fields,
unsafe_no_drop_flag,
- unsafe_pin_internals,
+ unsafe_pinned,
+ unsafe_unpin,
unsize,
unsized_const_param_ty,
unsized_const_params,
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index c9b1515..cc33974 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -89,7 +89,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(let_chains)]
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 8edfd16..f310aa6 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -615,7 +615,7 @@ fn print_dyn_existential(
cx.print_def_path(trait_ref.def_id, trait_ref.args)?;
}
ty::ExistentialPredicate::Projection(projection) => {
- let name = cx.tcx.associated_item(projection.def_id).name;
+ let name = cx.tcx.associated_item(projection.def_id).name();
cx.push("p");
cx.push_ident(name.as_str());
match projection.term.unpack() {
@@ -776,7 +776,7 @@ fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
self.push_disambiguator(
disambiguated_field.disambiguator as u64,
);
- self.push_ident(field_name.unwrap_or(kw::Empty).as_str());
+ self.push_ident(field_name.unwrap().as_str());
field.print(self)?;
}
@@ -858,7 +858,8 @@ fn path_append(
| DefPathData::GlobalAsm
| DefPathData::Impl
| DefPathData::MacroNs(_)
- | DefPathData::LifetimeNs(_) => {
+ | DefPathData::LifetimeNs(_)
+ | DefPathData::AnonAssocTy => {
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
}
};
diff --git a/compiler/rustc_target/src/spec/base/lynxos178.rs b/compiler/rustc_target/src/spec/base/lynxos178.rs
new file mode 100644
index 0000000..b9434ff
--- /dev/null
+++ b/compiler/rustc_target/src/spec/base/lynxos178.rs
@@ -0,0 +1,31 @@
+use std::borrow::Cow;
+
+use crate::spec::{
+ PanicStrategy, RelocModel, RelroLevel, SplitDebuginfo, StackProbeType, TargetOptions, cvs,
+};
+
+pub(crate) fn opts() -> TargetOptions {
+ TargetOptions {
+ os: "lynxos178".into(),
+ dynamic_linking: false,
+ families: cvs!["unix"],
+ position_independent_executables: false,
+ static_position_independent_executables: false,
+ relro_level: RelroLevel::Full,
+ has_thread_local: false,
+ crt_static_respected: true,
+ panic_strategy: PanicStrategy::Abort,
+ linker: Some(Cow::Borrowed("x86_64-lynx-lynxos178-gcc")),
+ no_default_libraries: false,
+ eh_frame_header: false, // GNU ld (GNU Binutils) 2.37.50 does not support --eh-frame-hdr
+ max_atomic_width: Some(64),
+ supported_split_debuginfo: Cow::Borrowed(&[
+ SplitDebuginfo::Packed,
+ SplitDebuginfo::Unpacked,
+ SplitDebuginfo::Off,
+ ]),
+ relocation_model: RelocModel::Static,
+ stack_probes: StackProbeType::Inline,
+ ..Default::default()
+ }
+}
diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs
index 71b6528..b368d93 100644
--- a/compiler/rustc_target/src/spec/base/mod.rs
+++ b/compiler/rustc_target/src/spec/base/mod.rs
@@ -19,6 +19,7 @@
pub(crate) mod linux_ohos;
pub(crate) mod linux_uclibc;
pub(crate) mod linux_wasm;
+pub(crate) mod lynxos178;
pub(crate) mod msvc;
pub(crate) mod netbsd;
pub(crate) mod nto_qnx;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 64171fc..3c769da 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2078,6 +2078,7 @@ fn $module() {
("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf),
("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf),
("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf),
+ ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178),
("x86_64-pc-cygwin", x86_64_pc_cygwin),
}
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
index 9f02ed4..b9176c9 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".into(),
- features: "+m,+a,+f,+d,+c,+zicsr,+zifencei,+zba,+zbb,+zbs,+v".into(),
+ features: "+m,+a,+f,+d,+c,+b,+v,+zicsr,+zifencei".into(),
llvm_abiname: "lp64d".into(),
supported_sanitizers: SanitizerSet::ADDRESS,
max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_lynx_lynxos178.rs b/compiler/rustc_target/src/spec/targets/x86_64_lynx_lynxos178.rs
new file mode 100644
index 0000000..654ae7c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/x86_64_lynx_lynxos178.rs
@@ -0,0 +1,34 @@
+use crate::spec::{SanitizerSet, StackProbeType, Target, base};
+
+pub(crate) fn target() -> Target {
+ let mut base = base::lynxos178::opts();
+ base.cpu = "x86-64".into();
+ base.plt_by_default = false;
+ base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
+ base.static_position_independent_executables = false;
+ base.supported_sanitizers = SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::KCFI
+ | SanitizerSet::DATAFLOW
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::SAFESTACK
+ | SanitizerSet::THREAD;
+ base.supports_xray = true;
+
+ Target {
+ llvm_target: "x86_64-unknown-unknown-gnu".into(),
+ metadata: crate::spec::TargetMetadata {
+ description: Some("LynxOS-178".into()),
+ tier: Some(3),
+ host_tools: Some(false),
+ std: Some(false),
+ },
+ pointer_width: 64,
+ data_layout:
+ "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
+ arch: "x86_64".into(),
+ options: base,
+ }
+}
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index b4ec187..aeace6a 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -491,7 +491,8 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
("a", Stable, &["zaamo", "zalrsc"]),
- ("c", Stable, &[]),
+ ("b", Unstable(sym::riscv_target_feature), &["zba", "zbb", "zbs"]),
+ ("c", Stable, &["zca"]),
("d", Unstable(sym::riscv_target_feature), &["f"]),
("e", Unstable(sym::riscv_target_feature), &[]),
("f", Unstable(sym::riscv_target_feature), &["zicsr"]),
@@ -520,17 +521,25 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
("zbkc", Stable, &[]),
("zbkx", Stable, &[]),
("zbs", Stable, &[]),
+ ("zca", Unstable(sym::riscv_target_feature), &[]),
+ ("zcb", Unstable(sym::riscv_target_feature), &["zca"]),
+ ("zcmop", Unstable(sym::riscv_target_feature), &["zca"]),
("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
+ ("zfa", Unstable(sym::riscv_target_feature), &["f"]),
("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]),
("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
+ ("zicboz", Unstable(sym::riscv_target_feature), &[]),
("zicntr", Unstable(sym::riscv_target_feature), &["zicsr"]),
+ ("zicond", Unstable(sym::riscv_target_feature), &[]),
("zicsr", Unstable(sym::riscv_target_feature), &[]),
("zifencei", Unstable(sym::riscv_target_feature), &[]),
+ ("zihintntl", Unstable(sym::riscv_target_feature), &[]),
("zihintpause", Unstable(sym::riscv_target_feature), &[]),
("zihpm", Unstable(sym::riscv_target_feature), &["zicsr"]),
+ ("zimop", Unstable(sym::riscv_target_feature), &[]),
("zk", Stable, &["zkn", "zkr", "zkt"]),
("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
("zknd", Stable, &[]),
@@ -541,6 +550,7 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
("zksed", Stable, &[]),
("zksh", Stable, &[]),
("zkt", Stable, &[]),
+ ("ztso", Unstable(sym::riscv_target_feature), &[]),
("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]),
("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 05bbb42..74e38f5 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -268,8 +268,8 @@
trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
.label = opaque type defined here
trait_selection_opaque_type_non_generic_param =
- expected generic {$kind} parameter, found `{$ty}`
- .label = {STREQ($ty, "'static") ->
+ expected generic {$kind} parameter, found `{$arg}`
+ .label = {STREQ($arg, "'static") ->
[true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
*[other] this generic parameter must be used with a generic {$kind} parameter
}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 40f8af1..fdd5474 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -2334,13 +2334,13 @@ fn as_failure_code_diag(
subdiags: Vec<TypeErrorAdditionalDiags>,
) -> ObligationCauseFailureCode {
match self.code() {
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => {
ObligationCauseFailureCode::MethodCompat { span, subdiags }
}
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => {
ObligationCauseFailureCode::TypeCompat { span, subdiags }
}
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => {
ObligationCauseFailureCode::ConstCompat { span, subdiags }
}
ObligationCauseCode::BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => {
@@ -2398,13 +2398,13 @@ fn as_failure_code_diag(
fn as_requirement_str(&self) -> &'static str {
match self.code() {
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => {
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => {
"method type is compatible with trait"
}
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => {
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => {
"associated type is compatible with trait"
}
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => {
"const is compatible with trait"
}
ObligationCauseCode::MainFunctionType => "`main` function has the correct type",
@@ -2422,9 +2422,13 @@ fn as_requirement_str(&self) -> &'static str {
impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
let kind = match self.0.code() {
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat",
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat",
- ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => {
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => {
+ "method_compat"
+ }
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => {
+ "type_compat"
+ }
+ ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => {
"const_compat"
}
ObligationCauseCode::MainFunctionType => "fn_main_correct_type",
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index 3559c66..eaa06d8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -6,7 +6,7 @@
use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
use rustc_hir::{
self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime,
- LifetimeName, LifetimeParamKind, MissingLifetimeKind, Node, TyKind,
+ LifetimeKind, LifetimeParamKind, MissingLifetimeKind, Node, TyKind,
};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::LocalDefId;
@@ -165,7 +165,7 @@ pub fn suggest_new_region_bound(
if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg {
GenericBound::Outlives(Lifetime {
- res: LifetimeName::Static, ident, ..
+ kind: LifetimeKind::Static, ident, ..
}) => Some(ident.span),
_ => None,
}) {
@@ -253,7 +253,7 @@ pub fn suggest_new_region_bound(
}
}
TyKind::TraitObject(_, lt) => {
- if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
+ if let LifetimeKind::ImplicitObjectLifetimeDefault = lt.kind {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
format!("{declare} the trait object {captures}, {explicit}",),
@@ -414,7 +414,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) {
impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) {
if let TyKind::TraitObject(poly_trait_refs, lifetime_ptr) = t.kind
- && let Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. } =
+ && let Lifetime { kind: LifetimeKind::ImplicitObjectLifetimeDefault, .. } =
lifetime_ptr.pointer()
{
for ptr in poly_trait_refs {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
index 7420592..b66bd2c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
@@ -98,7 +98,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) {
let assoc_item = self.tcx().associated_item(trait_item_def_id);
let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
match assoc_item.kind {
- ty::AssocKind::Fn => {
+ ty::AssocKind::Fn { .. } => {
if let Some(hir_id) =
assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id))
{
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
index fd2d2fa..4a71ab4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
@@ -158,6 +158,6 @@ pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: LocalDefId) -> b
&& self
.tcx()
.opt_associated_item(scope_def_id.to_def_id())
- .is_some_and(|i| i.fn_has_self_parameter)
+ .is_some_and(|i| i.is_method())
}
}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index 5583ded..be508c8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -782,8 +782,8 @@ fn point_at_methods_that_satisfy_associated_type(
let methods: Vec<(Span, String)> = items
.in_definition_order()
.filter(|item| {
- ty::AssocKind::Fn == item.kind
- && Some(item.name) != current_method_ident
+ item.is_fn()
+ && Some(item.name()) != current_method_ident
&& !tcx.is_doc_hidden(item.def_id)
})
.filter_map(|item| {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index 49c6ace..1cf1ac5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -850,14 +850,14 @@ pub fn suggest_name_region(
add_lt_suggs: &mut Vec<(Span, String)>,
) -> String {
struct LifetimeReplaceVisitor<'a> {
- needle: hir::LifetimeName,
+ needle: hir::LifetimeKind,
new_lt: &'a str,
add_lt_suggs: &'a mut Vec<(Span, String)>,
}
impl<'hir> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'_> {
fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
- if lt.res == self.needle {
+ if lt.kind == self.needle {
self.add_lt_suggs.push(lt.suggestion(self.new_lt));
}
}
@@ -894,7 +894,7 @@ fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
};
let mut visitor = LifetimeReplaceVisitor {
- needle: hir::LifetimeName::Param(lifetime_def_id),
+ needle: hir::LifetimeKind::Param(lifetime_def_id),
add_lt_suggs,
new_lt: &new_lt,
};
@@ -1017,7 +1017,7 @@ fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_>
infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
" for lifetime parameter {}in trait containing associated type `{}`",
br_string(br),
- self.tcx.associated_item(def_id).name
+ self.tcx.associated_item(def_id).name()
),
infer::RegionParameterDefinition(_, name) => {
format!(" for lifetime parameter `{name}`")
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index 59c93db..54b5085 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -348,11 +348,11 @@ pub(super) fn maybe_report_ambiguity(
&& let None = self.tainted_by_errors()
{
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
- ty::AssocKind::Const => ("refer to the", "constant"),
- ty::AssocKind::Fn => ("call", "function"),
+ ty::AssocKind::Const { .. } => ("refer to the", "constant"),
+ ty::AssocKind::Fn { .. } => ("call", "function"),
// This is already covered by E0223, but this following single match
// arm doesn't hurt here.
- ty::AssocKind::Type => ("refer to the", "type"),
+ ty::AssocKind::Type { .. } => ("refer to the", "type"),
};
// Replace the more general E0283 with a more specific error
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index b963e4a..7d95a7b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -2112,16 +2112,20 @@ pub(super) fn suggest_fully_qualified_path(
trait_ref: DefId,
) {
if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) {
- if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
+ if let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind {
err.note(format!(
"{}s cannot be accessed directly on a `trait`, they can only be \
accessed through a specific `impl`",
- self.tcx.def_kind_descr(assoc_item.kind.as_def_kind(), item_def_id)
+ self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id)
));
err.span_suggestion(
span,
"use the fully qualified path to an implementation",
- format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.name),
+ format!(
+ "<Type as {}>::{}",
+ self.tcx.def_path_str(trait_ref),
+ assoc_item.name()
+ ),
Applicability::HasPlaceholders,
);
}
@@ -5411,7 +5415,7 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind(
tcx,
Ident::with_dummy_span(name),
- ty::AssocKind::Type,
+ ty::AssocTag::Type,
data.impl_or_alias_def_id,
)
{
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index bb4aba9..756d9a5 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -4,7 +4,7 @@
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
- EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
+ EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic,
};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -107,11 +107,7 @@ pub enum AdjustSignatureBorrow {
}
impl Subdiagnostic for AdjustSignatureBorrow {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
AdjustSignatureBorrow::Borrow { to_borrow } => {
diag.arg("len", to_borrow.len());
@@ -381,11 +377,7 @@ pub enum RegionOriginNote<'a> {
}
impl Subdiagnostic for RegionOriginNote<'_> {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut label_or_note = |span, msg: DiagMessage| {
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
@@ -446,11 +438,7 @@ pub enum LifetimeMismatchLabels {
}
impl Subdiagnostic for LifetimeMismatchLabels {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
diag.span_label(param_span, fluent::trait_selection_declared_different);
@@ -495,11 +483,7 @@ pub struct AddLifetimeParamsSuggestion<'a> {
}
impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut mk_suggestion = || {
let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
else {
@@ -689,11 +673,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq {
}
impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- mut self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(mut self, diag: &mut Diag<'_, G>) {
self.unmet_requirements
.push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static);
diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req);
@@ -1008,17 +988,13 @@ pub struct ConsiderBorrowingParamHelp {
}
impl Subdiagnostic for ConsiderBorrowingParamHelp {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut type_param_span: MultiSpan = self.spans.clone().into();
for &span in &self.spans {
// Seems like we can't call f() here as Into<DiagMessage> is required
type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing);
}
- let msg = f(diag, fluent::trait_selection_tid_param_help.into());
+ let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help);
diag.span_help(type_param_span, msg);
}
}
@@ -1053,18 +1029,14 @@ pub struct DynTraitConstraintSuggestion {
}
impl Subdiagnostic for DynTraitConstraintSuggestion {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut multi_span: MultiSpan = vec![self.span].into();
multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label);
multi_span
.push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement);
- let msg = f(diag, fluent::trait_selection_dtcs_has_req_note.into());
+ let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note);
diag.span_note(multi_span, msg);
- let msg = f(diag, fluent::trait_selection_dtcs_suggestion.into());
+ let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion);
diag.span_suggestion_verbose(
self.span.shrink_to_hi(),
msg,
@@ -1101,11 +1073,7 @@ pub struct ReqIntroducedLocations {
}
impl Subdiagnostic for ReqIntroducedLocations {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- mut self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(mut self, diag: &mut Diag<'_, G>) {
for sp in self.spans {
self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here);
}
@@ -1114,7 +1082,7 @@ fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by);
}
self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of);
- let msg = f(diag, fluent::trait_selection_ril_static_introduced_by.into());
+ let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by);
diag.span_note(self.span, msg);
}
}
@@ -1513,13 +1481,9 @@ pub struct SuggestTuplePatternMany {
}
impl Subdiagnostic for SuggestTuplePatternMany {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("path", self.path);
- let message = f(diag, crate::fluent_generated::trait_selection_stp_wrap_many.into());
+ let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many);
diag.multipart_suggestions(
message,
self.compatible_variants.into_iter().map(|variant| {
@@ -1752,11 +1716,7 @@ pub struct AddPreciseCapturingAndParams {
}
impl Subdiagnostic for AddPreciseCapturingAndParams {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("new_lifetime", self.new_lifetime);
diag.multipart_suggestion_verbose(
fluent::trait_selection_precise_capturing_new_but_apit,
@@ -1896,11 +1856,7 @@ pub struct AddPreciseCapturingForOvercapture {
}
impl Subdiagnostic for AddPreciseCapturingForOvercapture {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- _f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let applicability = if self.apit_spans.is_empty() {
Applicability::MachineApplicable
} else {
@@ -1926,7 +1882,7 @@ fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
#[derive(Diagnostic)]
#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)]
pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
- pub ty: GenericArg<'tcx>,
+ pub arg: GenericArg<'tcx>,
pub kind: &'a str,
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
index e4ab78b..84e7686 100644
--- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic};
+use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::bug;
use rustc_middle::ty::{self, TyCtxt};
@@ -162,17 +162,13 @@ pub fn new<'tcx>(
}
impl Subdiagnostic for RegionExplanation<'_> {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
- self,
- diag: &mut Diag<'_, G>,
- f: &F,
- ) {
+ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("pref_kind", self.prefix);
diag.arg("suff_kind", self.suffix);
diag.arg("desc_kind", self.desc.kind);
diag.arg("desc_arg", self.desc.arg);
- let msg = f(diag, fluent::trait_selection_region_explanation.into());
+ let msg = diag.eagerly_translate(fluent::trait_selection_region_explanation);
if let Some(span) = self.desc.span {
diag.span_note(span, msg);
} else {
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index 309bf4d..cce67b0 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -70,7 +70,7 @@ pub fn check_opaque_type_parameter_valid<'tcx>(
opaque_env.param_is_error(i)?;
return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam {
- ty: arg,
+ arg,
kind,
span,
param_span: tcx.def_span(opaque_param.def_id),
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 48a05ad..24b8700 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -292,7 +292,7 @@ fn candidates_recur(
inspect::ProbeStep::NestedProbe(ref probe) => {
match probe.kind {
// These never assemble candidates for the goal we're trying to solve.
- inspect::ProbeKind::UpcastProjectionCompatibility
+ inspect::ProbeKind::ProjectionCompatibility
| inspect::ProbeKind::ShadowedEnvProbing => continue,
inspect::ProbeKind::NormalizedSelfTyAssembly
@@ -314,8 +314,10 @@ fn candidates_recur(
}
match probe.kind {
- inspect::ProbeKind::UpcastProjectionCompatibility
- | inspect::ProbeKind::ShadowedEnvProbing => bug!(),
+ inspect::ProbeKind::ProjectionCompatibility
+ | inspect::ProbeKind::ShadowedEnvProbing => {
+ bug!()
+ }
inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {}
diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs
index 4437fc5..4fdaf74 100644
--- a/compiler/rustc_trait_selection/src/solve/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/select.rs
@@ -177,7 +177,7 @@ fn to_selection<'tcx>(
},
ProbeKind::NormalizedSelfTyAssembly
| ProbeKind::UnsizeAssembly
- | ProbeKind::UpcastProjectionCompatibility
+ | ProbeKind::ProjectionCompatibility
| ProbeKind::OpaqueTypeStorageLookup { result: _ }
| ProbeKind::Root { result: _ }
| ProbeKind::ShadowedEnvProbing
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index bf9fcb0..5193946 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -188,7 +188,7 @@ fn predicates_reference_self(
tcx.associated_items(trait_def_id)
.in_definition_order()
// We're only looking at associated type bounds
- .filter(|item| item.kind == ty::AssocKind::Type)
+ .filter(|item| item.is_type())
// Ignore GATs with `Self: Sized`
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
@@ -298,31 +298,33 @@ pub fn dyn_compatibility_violations_for_assoc_item(
match item.kind {
// Associated consts are never dyn-compatible, as they can't have `where` bounds yet at all,
// and associated const bounds in trait objects aren't a thing yet either.
- ty::AssocKind::Const => {
- vec![DynCompatibilityViolation::AssocConst(item.name, item.ident(tcx).span)]
+ ty::AssocKind::Const { name } => {
+ vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)]
}
- ty::AssocKind::Fn => virtual_call_violations_for_method(tcx, trait_def_id, item)
- .into_iter()
- .map(|v| {
- let node = tcx.hir_get_if_local(item.def_id);
- // Get an accurate span depending on the violation.
- let span = match (&v, node) {
- (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
- (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
- (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
- (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
- node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
- }
- _ => item.ident(tcx).span,
- };
+ ty::AssocKind::Fn { name, .. } => {
+ virtual_call_violations_for_method(tcx, trait_def_id, item)
+ .into_iter()
+ .map(|v| {
+ let node = tcx.hir_get_if_local(item.def_id);
+ // Get an accurate span depending on the violation.
+ let span = match (&v, node) {
+ (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
+ (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
+ (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
+ (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
+ node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
+ }
+ _ => item.ident(tcx).span,
+ };
- DynCompatibilityViolation::Method(item.name, v, span)
- })
- .collect(),
+ DynCompatibilityViolation::Method(name, v, span)
+ })
+ .collect()
+ }
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
- ty::AssocKind::Type => {
+ ty::AssocKind::Type { .. } => {
if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
- vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)]
+ vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)]
} else {
// We will permit associated types if they are explicitly mentioned in the trait object.
// We can't check this here, as here we only check if it is guaranteed to not be possible.
@@ -344,7 +346,7 @@ fn virtual_call_violations_for_method<'tcx>(
let sig = tcx.fn_sig(method.def_id).instantiate_identity();
// The method's first parameter must be named `self`
- if !method.fn_has_self_parameter {
+ if !method.is_method() {
let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
generics,
kind: hir::TraitItemKind::Fn(sig, _),
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e98a240..1b76d48 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -24,10 +24,10 @@
};
use crate::error_reporting::InferCtxtErrorExt;
use crate::infer::{InferCtxt, TyOrConstInferVar};
-use crate::traits::EvaluateConstErr;
use crate::traits::normalize::normalize_with_depth_to;
use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _};
use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::traits::{EvaluateConstErr, sizedness_fast_path};
pub(crate) type PendingPredicateObligations<'tcx> = ThinVec<PendingPredicateObligation<'tcx>>;
@@ -335,6 +335,10 @@ fn process_obligation(
let infcx = self.selcx.infcx;
+ if sizedness_fast_path(infcx.tcx, obligation.predicate) {
+ return ProcessResult::Changed(thin_vec::thin_vec![]);
+ }
+
if obligation.predicate.has_aliases() {
let mut obligations = PredicateObligations::new();
let predicate = normalize_with_depth_to(
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index de33771..0987c5b 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -65,8 +65,8 @@
pub use self::structural_normalize::StructurallyNormalizeExt;
pub use self::util::{
BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final,
- supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, upcast_choices,
- with_replaced_escaping_bound_vars,
+ sizedness_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item,
+ upcast_choices, with_replaced_escaping_bound_vars,
};
use crate::error_reporting::InferCtxtErrorExt;
use crate::infer::outlives::env::OutlivesEnvironment;
@@ -643,7 +643,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
) -> GenericArgsRef<'tcx> {
struct ReplaceParamAndInferWithPlaceholder<'tcx> {
tcx: TyCtxt<'tcx>,
- idx: u32,
+ idx: ty::BoundVar,
}
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceParamAndInferWithPlaceholder<'tcx> {
@@ -653,19 +653,13 @@ fn cx(&self) -> TyCtxt<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Infer(_) = t.kind() {
- let idx = {
- let idx = self.idx;
- self.idx += 1;
- idx
- };
+ let idx = self.idx;
+ self.idx += 1;
Ty::new_placeholder(
self.tcx,
ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
- bound: ty::BoundTy {
- var: ty::BoundVar::from_u32(idx),
- kind: ty::BoundTyKind::Anon,
- },
+ bound: ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon },
},
)
} else {
@@ -675,16 +669,11 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
if let ty::ConstKind::Infer(_) = c.kind() {
+ let idx = self.idx;
+ self.idx += 1;
ty::Const::new_placeholder(
self.tcx,
- ty::PlaceholderConst {
- universe: ty::UniverseIndex::ROOT,
- bound: ty::BoundVar::from_u32({
- let idx = self.idx;
- self.idx += 1;
- idx
- }),
- },
+ ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, bound: idx },
)
} else {
c.super_fold_with(self)
@@ -692,7 +681,7 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
}
}
- args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
+ args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: ty::BoundVar::ZERO })
}
/// Normalizes the predicates and checks whether they hold in an empty environment. If this
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8359121..0dce504 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1393,7 +1393,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
coroutine_sig,
);
- debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
+ debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Output);
let predicate = ty::ProjectionPredicate {
projection_term: ty::AliasTerm::new_from_args(
@@ -1439,7 +1439,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>(
gen_sig,
);
- debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
+ debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item);
let predicate = ty::ProjectionPredicate {
projection_term: ty::AliasTerm::new_from_args(
@@ -1485,7 +1485,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>(
gen_sig,
);
- debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
+ debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item);
let ty::Adt(_poll_adt, args) = *yield_ty.kind() else {
bug!();
@@ -2005,7 +2005,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
if !assoc_ty.item.defaultness(tcx).has_value() {
debug!(
"confirm_impl_candidate: no associated type {:?} for {:?}",
- assoc_ty.item.name, obligation.predicate
+ assoc_ty.item.name(),
+ obligation.predicate
);
if tcx.impl_self_is_guaranteed_unsized(impl_def_id) {
// We treat this projection as rigid here, which is represented via
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 4f9e2e79..87fc532 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -1,4 +1,3 @@
-use rustc_hir::LangItem;
use rustc_infer::traits::Obligation;
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::query::NoSolution;
@@ -7,7 +6,7 @@
use rustc_span::Span;
use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
-use crate::traits::ObligationCtxt;
+use crate::traits::{ObligationCtxt, sizedness_fast_path};
impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
type QueryResponse = ();
@@ -16,15 +15,7 @@ fn try_fast_path(
tcx: TyCtxt<'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
- // Proving Sized, very often on "obviously sized" types like
- // `&T`, accounts for about 60% percentage of the predicates
- // we have to prove. No need to canonicalize and all that for
- // such cases.
- if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
- key.value.predicate.kind().skip_binder()
- && tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized)
- && trait_ref.self_ty().is_trivially_sized(tcx)
- {
+ if sizedness_fast_path(tcx, key.value.predicate) {
return Some(());
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 69e7b2a..d71d1e9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -594,9 +594,7 @@ fn confirm_object_candidate(
// Associated types that require `Self: Sized` do not show up in the built-in
// implementation of `Trait for dyn Trait`, and can be dropped here.
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
- .filter_map(
- |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
- )
+ .filter_map(|item| if item.is_type() { Some(item.def_id) } else { None })
.collect();
for assoc_type in assoc_types {
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 56ff46e..4d88a23 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -49,7 +49,9 @@
use crate::solve::InferCtxtSelectExt as _;
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt};
-use crate::traits::{EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects};
+use crate::traits::{
+ EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects, sizedness_fast_path,
+};
mod _match;
mod candidate_assembly;
@@ -603,6 +605,10 @@ fn evaluate_predicate_recursively<'o>(
None => self.check_recursion_limit(&obligation, &obligation)?,
}
+ if sizedness_fast_path(self.tcx(), obligation.predicate) {
+ return Ok(EvaluatedToOk);
+ }
+
ensure_sufficient_stack(|| {
let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 9f20cd7..035fd38 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -1,6 +1,7 @@
use std::collections::{BTreeMap, VecDeque};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_hir::LangItem;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferCtxt;
pub use rustc_infer::traits::util::*;
@@ -504,3 +505,21 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
}
}
}
+
+pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool {
+ // Proving `Sized` very often on "obviously sized" types like `&T`, accounts for about 60%
+ // percentage of the predicates we have to prove. No need to canonicalize and all that for
+ // such cases.
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
+ predicate.kind().skip_binder()
+ {
+ if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized)
+ && trait_ref.self_ty().is_trivially_sized(tcx)
+ {
+ debug!("fast path -- trivial sizedness");
+ return true;
+ }
+ }
+
+ false
+}
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 165174c..3565c11 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -197,10 +197,8 @@ fn own_existential_vtable_entries_iter(
tcx: TyCtxt<'_>,
trait_def_id: DefId,
) -> impl Iterator<Item = DefId> {
- let trait_methods = tcx
- .associated_items(trait_def_id)
- .in_definition_order()
- .filter(|item| item.kind == ty::AssocKind::Fn);
+ let trait_methods =
+ tcx.associated_items(trait_def_id).in_definition_order().filter(|item| item.is_fn());
// Now list each method's DefId (for within its trait).
let own_entries = trait_methods.filter_map(move |&trait_method| {
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 4a889ab..88f02d1 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -6,11 +6,11 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::bug;
use rustc_middle::traits::CodegenObligationError;
-use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, Upcast};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
- Unimplemented,
+ Unimplemented, sizedness_fast_path,
};
use tracing::debug;
@@ -34,6 +34,13 @@ pub(crate) fn codegen_select_candidate<'tcx>(
let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
let mut selcx = SelectionContext::new(&infcx);
+ if sizedness_fast_path(tcx, trait_ref.upcast(tcx)) {
+ return Ok(&*tcx.arena.alloc(ImplSource::Builtin(
+ ty::solve::BuiltinImplSource::Trivial,
+ Default::default(),
+ )));
+ }
+
let obligation_cause = ObligationCause::dummy();
let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index c9ad096..7771db8 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -5,6 +5,7 @@
use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
use rustc_trait_selection::traits::{
EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode,
+ sizedness_fast_path,
};
use tracing::debug;
@@ -23,6 +24,10 @@ fn evaluate_obligation<'tcx>(
debug!("evaluate_obligation: goal={:#?}", goal);
let ParamEnvAnd { param_env, value: predicate } = goal;
+ if sizedness_fast_path(tcx, predicate) {
+ return Ok(EvaluationResult::EvaluatedToOk);
+ }
+
let mut selcx = SelectionContext::with_query_mode(infcx, TraitQueryMode::Canonical);
let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 7d800e4..0092813 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -1,5 +1,4 @@
// tidy-alphabetical-start
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![feature(never_type)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
index 4d81382..69a6b1b 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
@@ -1,93 +1,115 @@
use itertools::Itertools;
use super::query_context::test::{Def, UltraMinimal};
-use crate::maybe_transmutable::MaybeTransmutableQuery;
-use crate::{Reason, layout};
+use crate::{Answer, Assume, Reason, layout};
+
+type Tree = layout::Tree<Def, !>;
+type Dfa = layout::Dfa<!>;
+
+trait Representation {
+ fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!>;
+}
+
+impl Representation for Tree {
+ fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!> {
+ crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
+ .answer()
+ }
+}
+
+impl Representation for Dfa {
+ fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!> {
+ crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
+ .answer()
+ }
+}
+
+fn is_transmutable<R: Representation + Clone>(
+ src: &R,
+ dst: &R,
+ assume: Assume,
+) -> crate::Answer<!> {
+ let src = src.clone();
+ let dst = dst.clone();
+ // The only dimension of the transmutability analysis we want to test
+ // here is the safety analysis. To ensure this, we disable all other
+ // toggleable aspects of the transmutability analysis.
+ R::is_transmutable(src, dst, assume)
+}
mod safety {
use super::*;
use crate::Answer;
- type Tree = layout::Tree<Def, !>;
-
const DST_HAS_SAFETY_INVARIANTS: Answer<!> =
Answer::No(crate::Reason::DstMayHaveSafetyInvariants);
- fn is_transmutable(src: &Tree, dst: &Tree, assume_safety: bool) -> crate::Answer<!> {
- let src = src.clone();
- let dst = dst.clone();
- // The only dimension of the transmutability analysis we want to test
- // here is the safety analysis. To ensure this, we disable all other
- // toggleable aspects of the transmutability analysis.
- let assume = crate::Assume {
- alignment: true,
- lifetimes: true,
- validity: true,
- safety: assume_safety,
- };
- crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
- .answer()
- }
-
#[test]
fn src_safe_dst_safe() {
let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
- assert_eq!(is_transmutable(&src, &dst, false), Answer::Yes);
- assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes);
+ assert_eq!(is_transmutable(&src, &dst, Assume::default()), Answer::Yes);
+ assert_eq!(
+ is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
+ Answer::Yes
+ );
}
#[test]
fn src_safe_dst_unsafe() {
let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
- assert_eq!(is_transmutable(&src, &dst, false), DST_HAS_SAFETY_INVARIANTS);
- assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes);
+ assert_eq!(is_transmutable(&src, &dst, Assume::default()), DST_HAS_SAFETY_INVARIANTS);
+ assert_eq!(
+ is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
+ Answer::Yes
+ );
}
#[test]
fn src_unsafe_dst_safe() {
let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8());
- assert_eq!(is_transmutable(&src, &dst, false), Answer::Yes);
- assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes);
+ assert_eq!(is_transmutable(&src, &dst, Assume::default()), Answer::Yes);
+ assert_eq!(
+ is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
+ Answer::Yes
+ );
}
#[test]
fn src_unsafe_dst_unsafe() {
let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8());
- assert_eq!(is_transmutable(&src, &dst, false), DST_HAS_SAFETY_INVARIANTS);
- assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes);
+ assert_eq!(is_transmutable(&src, &dst, Assume::default()), DST_HAS_SAFETY_INVARIANTS);
+ assert_eq!(
+ is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }),
+ Answer::Yes
+ );
}
}
mod bool {
use super::*;
- use crate::Answer;
#[test]
fn should_permit_identity_transmutation_tree() {
- let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
- layout::Tree::<Def, !>::bool(),
- layout::Tree::<Def, !>::bool(),
- crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false },
- UltraMinimal,
- )
- .answer();
- assert_eq!(answer, Answer::Yes);
+ let src = Tree::bool();
+ assert_eq!(is_transmutable(&src, &src, Assume::default()), Answer::Yes);
+ assert_eq!(
+ is_transmutable(&src, &src, Assume { validity: true, ..Assume::default() }),
+ Answer::Yes
+ );
}
#[test]
fn should_permit_identity_transmutation_dfa() {
- let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
- layout::Dfa::<!>::bool(),
- layout::Dfa::<!>::bool(),
- crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false },
- UltraMinimal,
- )
- .answer();
- assert_eq!(answer, Answer::Yes);
+ let src = Dfa::bool();
+ assert_eq!(is_transmutable(&src, &src, Assume::default()), Answer::Yes);
+ assert_eq!(
+ is_transmutable(&src, &src, Assume { validity: true, ..Assume::default() }),
+ Answer::Yes
+ );
}
#[test]
@@ -122,13 +144,7 @@ fn should_permit_validity_expansion_and_reject_contraction() {
if src_set.is_subset(&dst_set) {
assert_eq!(
Answer::Yes,
- MaybeTransmutableQuery::new(
- src_layout.clone(),
- dst_layout.clone(),
- crate::Assume { validity: false, ..crate::Assume::default() },
- UltraMinimal,
- )
- .answer(),
+ is_transmutable(&src_layout, &dst_layout, Assume::default()),
"{:?} SHOULD be transmutable into {:?}",
src_layout,
dst_layout
@@ -136,13 +152,11 @@ fn should_permit_validity_expansion_and_reject_contraction() {
} else if !src_set.is_disjoint(&dst_set) {
assert_eq!(
Answer::Yes,
- MaybeTransmutableQuery::new(
- src_layout.clone(),
- dst_layout.clone(),
- crate::Assume { validity: true, ..crate::Assume::default() },
- UltraMinimal,
- )
- .answer(),
+ is_transmutable(
+ &src_layout,
+ &dst_layout,
+ Assume { validity: true, ..Assume::default() }
+ ),
"{:?} SHOULD be transmutable (assuming validity) into {:?}",
src_layout,
dst_layout
@@ -150,13 +164,7 @@ fn should_permit_validity_expansion_and_reject_contraction() {
} else {
assert_eq!(
Answer::No(Reason::DstIsBitIncompatible),
- MaybeTransmutableQuery::new(
- src_layout.clone(),
- dst_layout.clone(),
- crate::Assume { validity: false, ..crate::Assume::default() },
- UltraMinimal,
- )
- .answer(),
+ is_transmutable(&src_layout, &dst_layout, Assume::default()),
"{:?} should NOT be transmutable into {:?}",
src_layout,
dst_layout
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index b7684e8..6cb9fdc 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -6,7 +6,6 @@
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
use rustc_middle::{bug, span_bug};
-use rustc_span::kw;
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
@@ -129,39 +128,35 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem {
let owner_id = trait_item_ref.id.owner_id;
- let (kind, has_self) = match trait_item_ref.kind {
- hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
- hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
- hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+ let name = trait_item_ref.ident.name;
+ let kind = match trait_item_ref.kind {
+ hir::AssocItemKind::Const => ty::AssocKind::Const { name },
+ hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self },
+ hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) },
};
ty::AssocItem {
- name: trait_item_ref.ident.name,
kind,
def_id: owner_id.to_def_id(),
trait_item_def_id: Some(owner_id.to_def_id()),
container: ty::AssocItemContainer::Trait,
- fn_has_self_parameter: has_self,
- opt_rpitit_info: None,
}
}
fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem {
let def_id = impl_item_ref.id.owner_id;
- let (kind, has_self) = match impl_item_ref.kind {
- hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
- hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
- hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+ let name = impl_item_ref.ident.name;
+ let kind = match impl_item_ref.kind {
+ hir::AssocItemKind::Const => ty::AssocKind::Const { name },
+ hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self },
+ hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) },
};
ty::AssocItem {
- name: impl_item_ref.ident.name,
kind,
def_id: def_id.to_def_id(),
trait_item_def_id: impl_item_ref.trait_item_def_id,
container: ty::AssocItemContainer::Impl,
- fn_has_self_parameter: has_self,
- opt_rpitit_info: None,
}
}
@@ -252,7 +247,7 @@ fn associated_type_for_impl_trait_in_trait(
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
let span = tcx.def_span(opaque_ty_def_id);
- // No name because this is a synthetic associated type.
+ // No name because this is an anonymous associated type.
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy);
let local_def_id = trait_assoc_ty.def_id();
@@ -264,16 +259,15 @@ fn associated_type_for_impl_trait_in_trait(
trait_assoc_ty.def_ident_span(Some(span));
trait_assoc_ty.associated_item(ty::AssocItem {
- name: kw::Empty,
- kind: ty::AssocKind::Type,
+ kind: ty::AssocKind::Type {
+ data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Trait {
+ fn_def_id: fn_def_id.to_def_id(),
+ opaque_def_id: opaque_ty_def_id.to_def_id(),
+ }),
+ },
def_id,
trait_item_def_id: None,
container: ty::AssocItemContainer::Trait,
- fn_has_self_parameter: false,
- opt_rpitit_info: Some(ImplTraitInTraitData::Trait {
- fn_def_id: fn_def_id.to_def_id(),
- opaque_def_id: opaque_ty_def_id.to_def_id(),
- }),
});
// Copy visility of the containing function.
@@ -305,7 +299,7 @@ fn associated_type_for_impl_trait_in_impl(
hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
hir::FnRetTy::Return(ty) => ty.span,
};
- // No name because this is a synthetic associated type.
+ // No name because this is an anonymous associated type.
let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy);
let local_def_id = impl_assoc_ty.def_id();
@@ -317,13 +311,14 @@ fn associated_type_for_impl_trait_in_impl(
impl_assoc_ty.def_ident_span(Some(span));
impl_assoc_ty.associated_item(ty::AssocItem {
- name: kw::Empty,
- kind: ty::AssocKind::Type,
+ kind: ty::AssocKind::Type {
+ data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Impl {
+ fn_def_id: impl_fn_def_id.to_def_id(),
+ }),
+ },
def_id,
trait_item_def_id: Some(trait_assoc_def_id),
container: ty::AssocItemContainer::Impl,
- fn_has_self_parameter: false,
- opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
});
// Copy visility of the containing function.
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 0017186..1915ba6 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -514,6 +514,9 @@ fn layout_of_uncached<'tcx>(
return map_layout(cx.calc.layout_of_union(&def.repr(), &variants));
}
+ // UnsafeCell and UnsafePinned both disable niche optimizations
+ let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned();
+
let get_discriminant_type =
|min, max| abi::Integer::repr_discr(tcx, ty, &def.repr(), min, max);
@@ -542,7 +545,7 @@ fn layout_of_uncached<'tcx>(
&def.repr(),
&variants,
def.is_enum(),
- def.is_unsafe_cell(),
+ is_special_no_niche,
tcx.layout_scalar_valid_range(def.did()),
get_discriminant_type,
discriminants_iter(),
@@ -568,7 +571,7 @@ fn layout_of_uncached<'tcx>(
&def.repr(),
&variants,
def.is_enum(),
- def.is_unsafe_cell(),
+ is_special_no_niche,
tcx.layout_scalar_valid_range(def.did()),
get_discriminant_type,
discriminants_iter(),
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 143b7d5..35cc6f3 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -6,7 +6,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index e905594..27ea4e2 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -122,6 +122,10 @@ impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Binder<I, T> {
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_binder(self)
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ folder.fold_binder(self)
+ }
}
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Binder<I, T> {
@@ -135,7 +139,11 @@ fn try_super_fold_with<F: FallibleTypeFolder<I>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
- self.try_map_bound(|ty| ty.try_fold_with(folder))
+ self.try_map_bound(|t| t.try_fold_with(folder))
+ }
+
+ fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ self.map_bound(|t| t.fold_with(folder))
}
}
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index 6a24982..e9d3a14 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -1,3 +1,9 @@
+use std::slice;
+
+use crate::inherent::*;
+use crate::visit::Flags;
+use crate::{self as ty, Interner};
+
bitflags::bitflags! {
/// Flags that we track on types. These flags are propagated upwards
/// through the type during type construction, so that we can quickly check
@@ -128,3 +134,362 @@ pub struct TypeFlags: u32 {
const HAS_BINDER_VARS = 1 << 23;
}
}
+
+#[derive(Debug)]
+pub struct FlagComputation<I> {
+ pub flags: TypeFlags,
+
+ /// see `Ty::outer_exclusive_binder` for details
+ pub outer_exclusive_binder: ty::DebruijnIndex,
+
+ interner: std::marker::PhantomData<I>,
+}
+
+impl<I: Interner> FlagComputation<I> {
+ fn new() -> FlagComputation<I> {
+ FlagComputation {
+ flags: TypeFlags::empty(),
+ outer_exclusive_binder: ty::INNERMOST,
+ interner: std::marker::PhantomData,
+ }
+ }
+
+ #[allow(rustc::usage_of_ty_tykind)]
+ pub fn for_kind(kind: &ty::TyKind<I>) -> FlagComputation<I> {
+ let mut result = FlagComputation::new();
+ result.add_kind(kind);
+ result
+ }
+
+ pub fn for_predicate(binder: ty::Binder<I, ty::PredicateKind<I>>) -> FlagComputation<I> {
+ let mut result = FlagComputation::new();
+ result.add_predicate(binder);
+ result
+ }
+
+ pub fn for_const_kind(kind: &ty::ConstKind<I>) -> FlagComputation<I> {
+ let mut result = FlagComputation::new();
+ result.add_const_kind(kind);
+ result
+ }
+
+ pub fn for_clauses(clauses: &[I::Clause]) -> FlagComputation<I> {
+ let mut result = FlagComputation::new();
+ for c in clauses {
+ result.add_flags(c.as_predicate().flags());
+ result.add_exclusive_binder(c.as_predicate().outer_exclusive_binder());
+ }
+ result
+ }
+
+ fn add_flags(&mut self, flags: TypeFlags) {
+ self.flags = self.flags | flags;
+ }
+
+ /// indicates that `self` refers to something at binding level `binder`
+ fn add_bound_var(&mut self, binder: ty::DebruijnIndex) {
+ let exclusive_binder = binder.shifted_in(1);
+ self.add_exclusive_binder(exclusive_binder);
+ }
+
+ /// indicates that `self` refers to something *inside* binding
+ /// level `binder` -- not bound by `binder`, but bound by the next
+ /// binder internal to it
+ fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) {
+ self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder);
+ }
+
+ /// Adds the flags/depth from a set of types that appear within the current type, but within a
+ /// region binder.
+ fn bound_computation<T, F>(&mut self, value: ty::Binder<I, T>, f: F)
+ where
+ F: FnOnce(&mut Self, T),
+ {
+ let mut computation = FlagComputation::new();
+
+ if !value.bound_vars().is_empty() {
+ computation.add_flags(TypeFlags::HAS_BINDER_VARS);
+ }
+
+ f(&mut computation, value.skip_binder());
+
+ self.add_flags(computation.flags);
+
+ // The types that contributed to `computation` occurred within
+ // a region binder, so subtract one from the region depth
+ // within when adding the depth to `self`.
+ let outer_exclusive_binder = computation.outer_exclusive_binder;
+ if outer_exclusive_binder > ty::INNERMOST {
+ self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
+ } // otherwise, this binder captures nothing
+ }
+
+ #[allow(rustc::usage_of_ty_tykind)]
+ fn add_kind(&mut self, kind: &ty::TyKind<I>) {
+ match *kind {
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Float(_)
+ | ty::Uint(_)
+ | ty::Never
+ | ty::Str
+ | ty::Foreign(..) => {}
+
+ ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
+
+ ty::Param(_) => {
+ self.add_flags(TypeFlags::HAS_TY_PARAM);
+ }
+
+ ty::Closure(_, args)
+ | ty::Coroutine(_, args)
+ | ty::CoroutineClosure(_, args)
+ | ty::CoroutineWitness(_, args) => {
+ self.add_args(args.as_slice());
+ }
+
+ ty::Bound(debruijn, _) => {
+ self.add_bound_var(debruijn);
+ self.add_flags(TypeFlags::HAS_TY_BOUND);
+ }
+
+ ty::Placeholder(..) => {
+ self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
+ }
+
+ ty::Infer(infer) => match infer {
+ ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
+ self.add_flags(TypeFlags::HAS_TY_FRESH)
+ }
+
+ ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => {
+ self.add_flags(TypeFlags::HAS_TY_INFER)
+ }
+ },
+
+ ty::Adt(_, args) => {
+ self.add_args(args.as_slice());
+ }
+
+ ty::Alias(kind, data) => {
+ self.add_flags(match kind {
+ ty::Projection => TypeFlags::HAS_TY_PROJECTION,
+ ty::Weak => TypeFlags::HAS_TY_WEAK,
+ ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
+ ty::Inherent => TypeFlags::HAS_TY_INHERENT,
+ });
+
+ self.add_alias_ty(data);
+ }
+
+ ty::Dynamic(obj, r, _) => {
+ for predicate in obj.iter() {
+ self.bound_computation(predicate, |computation, predicate| match predicate {
+ ty::ExistentialPredicate::Trait(tr) => {
+ computation.add_args(tr.args.as_slice())
+ }
+ ty::ExistentialPredicate::Projection(p) => {
+ computation.add_existential_projection(&p);
+ }
+ ty::ExistentialPredicate::AutoTrait(_) => {}
+ });
+ }
+
+ self.add_region(r);
+ }
+
+ ty::Array(tt, len) => {
+ self.add_ty(tt);
+ self.add_const(len);
+ }
+
+ ty::Pat(ty, pat) => {
+ self.add_ty(ty);
+ self.add_flags(pat.flags());
+ }
+
+ ty::Slice(tt) => self.add_ty(tt),
+
+ ty::RawPtr(ty, _) => {
+ self.add_ty(ty);
+ }
+
+ ty::Ref(r, ty, _) => {
+ self.add_region(r);
+ self.add_ty(ty);
+ }
+
+ ty::Tuple(types) => {
+ self.add_tys(types);
+ }
+
+ ty::FnDef(_, args) => {
+ self.add_args(args.as_slice());
+ }
+
+ ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| {
+ computation.add_tys(sig_tys.inputs_and_output);
+ }),
+
+ ty::UnsafeBinder(bound_ty) => {
+ self.bound_computation(bound_ty.into(), |computation, ty| {
+ computation.add_ty(ty);
+ })
+ }
+ }
+ }
+
+ fn add_predicate(&mut self, binder: ty::Binder<I, ty::PredicateKind<I>>) {
+ self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom));
+ }
+
+ fn add_predicate_atom(&mut self, atom: ty::PredicateKind<I>) {
+ match atom {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
+ self.add_args(trait_pred.trait_ref.args.as_slice());
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
+ trait_ref,
+ constness: _,
+ })) => {
+ self.add_args(trait_ref.args.as_slice());
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+ a,
+ b,
+ ))) => {
+ self.add_region(a);
+ self.add_region(b);
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
+ ty,
+ region,
+ ))) => {
+ self.add_ty(ty);
+ self.add_region(region);
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
+ self.add_const(ct);
+ self.add_ty(ty);
+ }
+ ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
+ self.add_ty(a);
+ self.add_ty(b);
+ }
+ ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
+ self.add_ty(a);
+ self.add_ty(b);
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
+ projection_term,
+ term,
+ })) => {
+ self.add_alias_term(projection_term);
+ self.add_term(term);
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+ self.add_args(slice::from_ref(&arg));
+ }
+ ty::PredicateKind::DynCompatible(_def_id) => {}
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
+ self.add_const(uv);
+ }
+ ty::PredicateKind::ConstEquate(expected, found) => {
+ self.add_const(expected);
+ self.add_const(found);
+ }
+ ty::PredicateKind::Ambiguous => {}
+ ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => {
+ self.add_alias_term(alias);
+ self.add_term(term);
+ }
+ ty::PredicateKind::AliasRelate(t1, t2, _) => {
+ self.add_term(t1);
+ self.add_term(t2);
+ }
+ }
+ }
+
+ fn add_ty(&mut self, ty: I::Ty) {
+ self.add_flags(ty.flags());
+ self.add_exclusive_binder(ty.outer_exclusive_binder());
+ }
+
+ fn add_tys(&mut self, tys: I::Tys) {
+ for ty in tys.iter() {
+ self.add_ty(ty);
+ }
+ }
+
+ fn add_region(&mut self, r: I::Region) {
+ self.add_flags(r.flags());
+ if let ty::ReBound(debruijn, _) = r.kind() {
+ self.add_bound_var(debruijn);
+ }
+ }
+
+ fn add_const(&mut self, c: I::Const) {
+ self.add_flags(c.flags());
+ self.add_exclusive_binder(c.outer_exclusive_binder());
+ }
+
+ fn add_const_kind(&mut self, c: &ty::ConstKind<I>) {
+ match *c {
+ ty::ConstKind::Unevaluated(uv) => {
+ self.add_args(uv.args.as_slice());
+ self.add_flags(TypeFlags::HAS_CT_PROJECTION);
+ }
+ ty::ConstKind::Infer(infer) => match infer {
+ ty::InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
+ ty::InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
+ },
+ ty::ConstKind::Bound(debruijn, _) => {
+ self.add_bound_var(debruijn);
+ self.add_flags(TypeFlags::HAS_CT_BOUND);
+ }
+ ty::ConstKind::Param(_) => {
+ self.add_flags(TypeFlags::HAS_CT_PARAM);
+ }
+ ty::ConstKind::Placeholder(_) => {
+ self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
+ }
+ ty::ConstKind::Value(cv) => self.add_ty(cv.ty()),
+ ty::ConstKind::Expr(e) => self.add_args(e.args().as_slice()),
+ ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
+ }
+ }
+
+ fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<I>) {
+ self.add_args(projection.args.as_slice());
+ match projection.term.kind() {
+ ty::TermKind::Ty(ty) => self.add_ty(ty),
+ ty::TermKind::Const(ct) => self.add_const(ct),
+ }
+ }
+
+ fn add_alias_ty(&mut self, alias_ty: ty::AliasTy<I>) {
+ self.add_args(alias_ty.args.as_slice());
+ }
+
+ fn add_alias_term(&mut self, alias_term: ty::AliasTerm<I>) {
+ self.add_args(alias_term.args.as_slice());
+ }
+
+ fn add_args(&mut self, args: &[I::GenericArg]) {
+ for kind in args {
+ match kind.kind() {
+ ty::GenericArgKind::Type(ty) => self.add_ty(ty),
+ ty::GenericArgKind::Lifetime(lt) => self.add_region(lt),
+ ty::GenericArgKind::Const(ct) => self.add_const(ct),
+ }
+ }
+ }
+
+ fn add_term(&mut self, term: I::Term) {
+ match term.kind() {
+ ty::TermKind::Ty(ty) => self.add_ty(ty),
+ ty::TermKind::Const(ct) => self.add_const(ct),
+ }
+ }
+}
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index e58f25f..ce11880 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -45,6 +45,7 @@
//! - u.fold_with(folder)
//! ```
+use std::convert::Infallible;
use std::mem;
use std::sync::Arc;
@@ -56,12 +57,6 @@
use crate::visit::{TypeVisitable, TypeVisitableExt as _};
use crate::{self as ty, Interner, TypeFlags};
-#[cfg(feature = "nightly")]
-type Never = !;
-
-#[cfg(not(feature = "nightly"))]
-type Never = std::convert::Infallible;
-
/// This trait is implemented for every type that can be folded,
/// providing the skeleton of the traversal.
///
@@ -82,18 +77,24 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> + Clone {
///
/// For types of interest (such as `Ty`), the implementation of this method
/// calls a folder method specifically for that type (such as
- /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
- /// to `TypeFolder`.
+ /// `F::try_fold_ty`). This is where control transfers from [`TypeFoldable`]
+ /// to [`FallibleTypeFolder`].
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error>;
- /// A convenient alternative to `try_fold_with` for use with infallible
- /// folders. Do not override this method, to ensure coherence with
- /// `try_fold_with`.
- fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
- match self.try_fold_with(folder) {
- Ok(t) => t,
- }
- }
+ /// The entry point for folding. To fold a value `t` with a folder `f`
+ /// call: `t.fold_with(f)`.
+ ///
+ /// For most types, this just traverses the value, calling `fold_with`
+ /// on each field/element.
+ ///
+ /// For types of interest (such as `Ty`), the implementation of this method
+ /// calls a folder method specifically for that type (such as
+ /// `F::fold_ty`). This is where control transfers from `TypeFoldable`
+ /// to `TypeFolder`.
+ ///
+ /// Same as [`TypeFoldable::try_fold_with`], but not fallible. Make sure to keep
+ /// the behavior in sync across functions.
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
}
// This trait is implemented for types of interest.
@@ -112,11 +113,7 @@ fn try_super_fold_with<F: FallibleTypeFolder<I>>(
/// A convenient alternative to `try_super_fold_with` for use with
/// infallible folders. Do not override this method, to ensure coherence
/// with `try_super_fold_with`.
- fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
- match self.try_super_fold_with(folder) {
- Ok(t) => t,
- }
- }
+ fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
}
/// This trait is implemented for every infallible folding traversal. There is
@@ -128,7 +125,7 @@ fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
/// A blanket implementation of [`FallibleTypeFolder`] will defer to
/// the infallible methods of this trait to ensure that the two APIs
/// are coherent.
-pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
+pub trait TypeFolder<I: Interner>: Sized {
fn cx(&self) -> I;
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
@@ -195,42 +192,6 @@ fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::
}
}
-// This blanket implementation of the fallible trait for infallible folders
-// delegates to infallible methods to ensure coherence.
-impl<I: Interner, F> FallibleTypeFolder<I> for F
-where
- F: TypeFolder<I>,
-{
- type Error = Never;
-
- fn cx(&self) -> I {
- TypeFolder::cx(self)
- }
-
- fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Never>
- where
- T: TypeFoldable<I>,
- {
- Ok(self.fold_binder(t))
- }
-
- fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never> {
- Ok(self.fold_ty(t))
- }
-
- fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Never> {
- Ok(self.fold_region(r))
- }
-
- fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never> {
- Ok(self.fold_const(c))
- }
-
- fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never> {
- Ok(self.fold_predicate(p))
- }
-}
-
///////////////////////////////////////////////////////////////////////////
// Traversal implementations.
@@ -238,6 +199,10 @@ impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ (self.0.fold_with(folder), self.1.fold_with(folder))
+ }
}
impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
@@ -253,6 +218,10 @@ fn try_fold_with<F: FallibleTypeFolder<I>>(
self.2.try_fold_with(folder)?,
))
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
+ }
}
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
@@ -262,6 +231,10 @@ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self,
None => None,
})
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ Some(self?.fold_with(folder))
+ }
}
impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
@@ -271,41 +244,61 @@ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self,
Err(e) => Err(e.try_fold_with(folder)?),
})
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ match self {
+ Ok(v) => Ok(v.fold_with(folder)),
+ Err(e) => Err(e.fold_with(folder)),
+ }
+ }
+}
+
+fn fold_arc<T: Clone, E>(
+ mut arc: Arc<T>,
+ fold: impl FnOnce(T) -> Result<T, E>,
+) -> Result<Arc<T>, E> {
+ // We merely want to replace the contained `T`, if at all possible,
+ // so that we don't needlessly allocate a new `Arc` or indeed clone
+ // the contained type.
+ unsafe {
+ // First step is to ensure that we have a unique reference to
+ // the contained type, which `Arc::make_mut` will accomplish (by
+ // allocating a new `Arc` and cloning the `T` only if required).
+ // This is done *before* casting to `Arc<ManuallyDrop<T>>` so that
+ // panicking during `make_mut` does not leak the `T`.
+ Arc::make_mut(&mut arc);
+
+ // Casting to `Arc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
+ // is `repr(transparent)`.
+ let ptr = Arc::into_raw(arc).cast::<mem::ManuallyDrop<T>>();
+ let mut unique = Arc::from_raw(ptr);
+
+ // Call to `Arc::make_mut` above guarantees that `unique` is the
+ // sole reference to the contained value, so we can avoid doing
+ // a checked `get_mut` here.
+ let slot = Arc::get_mut(&mut unique).unwrap_unchecked();
+
+ // Semantically move the contained type out from `unique`, fold
+ // it, then move the folded value back into `unique`. Should
+ // folding fail, `ManuallyDrop` ensures that the "moved-out"
+ // value is not re-dropped.
+ let owned = mem::ManuallyDrop::take(slot);
+ let folded = fold(owned)?;
+ *slot = mem::ManuallyDrop::new(folded);
+
+ // Cast back to `Arc<T>`.
+ Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
+ }
}
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Arc<T> {
- fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
- // We merely want to replace the contained `T`, if at all possible,
- // so that we don't needlessly allocate a new `Arc` or indeed clone
- // the contained type.
- unsafe {
- // First step is to ensure that we have a unique reference to
- // the contained type, which `Arc::make_mut` will accomplish (by
- // allocating a new `Arc` and cloning the `T` only if required).
- // This is done *before* casting to `Arc<ManuallyDrop<T>>` so that
- // panicking during `make_mut` does not leak the `T`.
- Arc::make_mut(&mut self);
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ fold_arc(self, |t| t.try_fold_with(folder))
+ }
- // Casting to `Arc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
- // is `repr(transparent)`.
- let ptr = Arc::into_raw(self).cast::<mem::ManuallyDrop<T>>();
- let mut unique = Arc::from_raw(ptr);
-
- // Call to `Arc::make_mut` above guarantees that `unique` is the
- // sole reference to the contained value, so we can avoid doing
- // a checked `get_mut` here.
- let slot = Arc::get_mut(&mut unique).unwrap_unchecked();
-
- // Semantically move the contained type out from `unique`, fold
- // it, then move the folded value back into `unique`. Should
- // folding fail, `ManuallyDrop` ensures that the "moved-out"
- // value is not re-dropped.
- let owned = mem::ManuallyDrop::take(slot);
- let folded = owned.try_fold_with(folder)?;
- *slot = mem::ManuallyDrop::new(folded);
-
- // Cast back to `Arc<T>`.
- Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ match fold_arc::<T, Infallible>(self, |t| Ok(t.fold_with(folder))) {
+ Ok(t) => t,
}
}
}
@@ -315,30 +308,51 @@ fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<S
*self = (*self).try_fold_with(folder)?;
Ok(self)
}
+
+ fn fold_with<F: TypeFolder<I>>(mut self, folder: &mut F) -> Self {
+ *self = (*self).fold_with(folder);
+ self
+ }
}
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.into_iter().map(|t| t.try_fold_with(folder)).collect()
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ self.into_iter().map(|t| t.fold_with(folder)).collect()
+ }
}
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for ThinVec<T> {
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.into_iter().map(|t| t.try_fold_with(folder)).collect()
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ self.into_iter().map(|t| t.fold_with(folder)).collect()
+ }
}
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<[T]> {
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
Vec::from(self).try_fold_with(folder).map(Vec::into_boxed_slice)
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ Vec::into_boxed_slice(Vec::from(self).fold_with(folder))
+ }
}
impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.raw.try_fold_with(folder).map(IndexVec::from_raw)
}
+
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ IndexVec::from_raw(self.raw.fold_with(folder))
+ }
}
///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 6e6c405..417803e 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -583,7 +583,7 @@ pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
pub trait SliceLike: Sized + Copy {
type Item: Copy;
- type IntoIter: Iterator<Item = Self::Item>;
+ type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator;
fn iter(self) -> Self::IntoIter;
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index a9e6764..71bfeab 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -31,6 +31,7 @@ pub trait Interner:
+ IrPrint<ty::SubtypePredicate<Self>>
+ IrPrint<ty::CoercePredicate<Self>>
+ IrPrint<ty::FnSig<Self>>
+ + IrPrint<ty::PatternKind<Self>>
{
type DefId: DefId<Self>;
type LocalDefId: Copy + Debug + Hash + Eq + Into<Self::DefId> + TypeFoldable<Self>;
@@ -104,7 +105,14 @@ fn mk_tracked<T: Debug + Clone>(
type ErrorGuaranteed: Copy + Debug + Hash + Eq;
type BoundExistentialPredicates: BoundExistentialPredicates<Self>;
type AllocId: Copy + Debug + Hash + Eq;
- type Pat: Copy + Debug + Hash + Eq + Debug + Relate<Self>;
+ type Pat: Copy
+ + Debug
+ + Hash
+ + Eq
+ + Debug
+ + Relate<Self>
+ + Flags
+ + IntoKind<Kind = ty::PatternKind<Self>>;
type Safety: Safety<Self>;
type Abi: Abi<Self>;
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
index 0c71f3a..388ad09 100644
--- a/compiler/rustc_type_ir/src/ir_print.rs
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -2,8 +2,8 @@
use crate::{
AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
- HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, ProjectionPredicate,
- SubtypePredicate, TraitPredicate, TraitRef,
+ HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, PatternKind,
+ ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
};
pub trait IrPrint<T> {
@@ -57,9 +57,10 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
AliasTy,
AliasTerm,
FnSig,
+ PatternKind,
);
-define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);
+define_debug_via_print!(TraitRef, ExistentialTraitRef, PatternKind);
impl<I: Interner, T> fmt::Display for OutlivesPredicate<I, T>
where
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index bdc61e95..792090e 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -31,6 +31,7 @@
pub mod relate;
pub mod search_graph;
pub mod solve;
+pub mod walk;
// These modules are not `pub` since they are glob-imported.
#[macro_use]
@@ -44,6 +45,7 @@
mod infer_ctxt;
mod interner;
mod opaque_ty;
+mod pattern;
mod predicate;
mod predicate_kind;
mod region_kind;
@@ -67,6 +69,7 @@
pub use infer_ctxt::*;
pub use interner::*;
pub use opaque_ty::*;
+pub use pattern::*;
pub use predicate::*;
pub use predicate_kind::*;
pub use region_kind::*;
diff --git a/compiler/rustc_type_ir/src/pattern.rs b/compiler/rustc_type_ir/src/pattern.rs
new file mode 100644
index 0000000..d74a82d
--- /dev/null
+++ b/compiler/rustc_type_ir/src/pattern.rs
@@ -0,0 +1,16 @@
+use derive_where::derive_where;
+#[cfg(feature = "nightly")]
+use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
+use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
+
+use crate::Interner;
+
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(
+ feature = "nightly",
+ derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
+)]
+pub enum PatternKind<I: Interner> {
+ Range { start: I::Const, end: I::Const },
+}
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 22d0fa2..8e10636 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -374,7 +374,7 @@ pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>>
}
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs
index 18fb71d..b10641b 100644
--- a/compiler/rustc_type_ir/src/solve/inspect.rs
+++ b/compiler/rustc_type_ir/src/solve/inspect.rs
@@ -118,10 +118,12 @@ pub enum ProbeKind<I: Interner> {
/// Used in the probe that wraps normalizing the non-self type for the unsize
/// trait, which is also structurally matched on.
UnsizeAssembly,
- /// During upcasting from some source object to target object type, used to
- /// do a probe to find out what projection type(s) may be used to prove that
- /// the source type upholds all of the target type's object bounds.
- UpcastProjectionCompatibility,
+ /// Used to do a probe to find out what projection type(s) match a given
+ /// alias bound or projection predicate. For trait upcasting, this is used
+ /// to prove that the source type upholds all of the target type's object
+ /// bounds. For object type bounds, this is used when eagerly replacing
+ /// supertrait aliases.
+ ProjectionCompatibility,
/// Looking for param-env candidates that satisfy the trait ref for a projection.
ShadowedEnvProbing,
/// Try to unify an opaque type with an existing key in the storage.
diff --git a/compiler/rustc_type_ir/src/walk.rs b/compiler/rustc_type_ir/src/walk.rs
new file mode 100644
index 0000000..5683e1f
--- /dev/null
+++ b/compiler/rustc_type_ir/src/walk.rs
@@ -0,0 +1,173 @@
+//! An iterator over the type substructure.
+//! WARNING: this does not keep track of the region depth.
+
+use smallvec::{SmallVec, smallvec};
+use tracing::debug;
+
+use crate::data_structures::SsoHashSet;
+use crate::inherent::*;
+use crate::{self as ty, Interner};
+
+// The TypeWalker's stack is hot enough that it's worth going to some effort to
+// avoid heap allocations.
+type TypeWalkerStack<I> = SmallVec<[<I as Interner>::GenericArg; 8]>;
+
+pub struct TypeWalker<I: Interner> {
+ stack: TypeWalkerStack<I>,
+ last_subtree: usize,
+ pub visited: SsoHashSet<I::GenericArg>,
+}
+
+/// An iterator for walking the type tree.
+///
+/// It's very easy to produce a deeply
+/// nested type tree with a lot of
+/// identical subtrees. In order to work efficiently
+/// in this situation walker only visits each type once.
+/// It maintains a set of visited types and
+/// skips any types that are already there.
+impl<I: Interner> TypeWalker<I> {
+ pub fn new(root: I::GenericArg) -> Self {
+ Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() }
+ }
+
+ /// Skips the subtree corresponding to the last type
+ /// returned by `next()`.
+ ///
+ /// Example: Imagine you are walking `Foo<Bar<i32>, usize>`.
+ ///
+ /// ```ignore (illustrative)
+ /// let mut iter: TypeWalker = ...;
+ /// iter.next(); // yields Foo
+ /// iter.next(); // yields Bar<i32>
+ /// iter.skip_current_subtree(); // skips i32
+ /// iter.next(); // yields usize
+ /// ```
+ pub fn skip_current_subtree(&mut self) {
+ self.stack.truncate(self.last_subtree);
+ }
+}
+
+impl<I: Interner> Iterator for TypeWalker<I> {
+ type Item = I::GenericArg;
+
+ fn next(&mut self) -> Option<I::GenericArg> {
+ debug!("next(): stack={:?}", self.stack);
+ loop {
+ let next = self.stack.pop()?;
+ self.last_subtree = self.stack.len();
+ if self.visited.insert(next) {
+ push_inner::<I>(&mut self.stack, next);
+ debug!("next: stack={:?}", self.stack);
+ return Some(next);
+ }
+ }
+ }
+}
+
+/// We push `GenericArg`s on the stack in reverse order so as to
+/// maintain a pre-order traversal. As of the time of this
+/// writing, the fact that the traversal is pre-order is not
+/// known to be significant to any code, but it seems like the
+/// natural order one would expect (basically, the order of the
+/// types as they are written).
+fn push_inner<I: Interner>(stack: &mut TypeWalkerStack<I>, parent: I::GenericArg) {
+ match parent.kind() {
+ ty::GenericArgKind::Type(parent_ty) => match parent_ty.kind() {
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Str
+ | ty::Infer(_)
+ | ty::Param(_)
+ | ty::Never
+ | ty::Error(_)
+ | ty::Placeholder(..)
+ | ty::Bound(..)
+ | ty::Foreign(..) => {}
+
+ ty::Pat(ty, pat) => {
+ match pat.kind() {
+ ty::PatternKind::Range { start, end } => {
+ stack.push(end.into());
+ stack.push(start.into());
+ }
+ }
+ stack.push(ty.into());
+ }
+ ty::Array(ty, len) => {
+ stack.push(len.into());
+ stack.push(ty.into());
+ }
+ ty::Slice(ty) => {
+ stack.push(ty.into());
+ }
+ ty::RawPtr(ty, _) => {
+ stack.push(ty.into());
+ }
+ ty::Ref(lt, ty, _) => {
+ stack.push(ty.into());
+ stack.push(lt.into());
+ }
+ ty::Alias(_, data) => {
+ stack.extend(data.args.iter().rev());
+ }
+ ty::Dynamic(obj, lt, _) => {
+ stack.push(lt.into());
+ stack.extend(
+ obj.iter()
+ .rev()
+ .filter_map(|predicate| {
+ let (args, opt_ty) = match predicate.skip_binder() {
+ ty::ExistentialPredicate::Trait(tr) => (tr.args, None),
+ ty::ExistentialPredicate::Projection(p) => (p.args, Some(p.term)),
+ ty::ExistentialPredicate::AutoTrait(_) => {
+ return None;
+ }
+ };
+
+ Some(args.iter().rev().chain(opt_ty.map(|term| match term.kind() {
+ ty::TermKind::Ty(ty) => ty.into(),
+ ty::TermKind::Const(ct) => ct.into(),
+ })))
+ })
+ .flatten(),
+ );
+ }
+ ty::Adt(_, args)
+ | ty::Closure(_, args)
+ | ty::CoroutineClosure(_, args)
+ | ty::Coroutine(_, args)
+ | ty::CoroutineWitness(_, args)
+ | ty::FnDef(_, args) => {
+ stack.extend(args.iter().rev());
+ }
+ ty::Tuple(ts) => stack.extend(ts.iter().rev().map(|ty| ty.into())),
+ ty::FnPtr(sig_tys, _hdr) => {
+ stack.extend(
+ sig_tys.skip_binder().inputs_and_output.iter().rev().map(|ty| ty.into()),
+ );
+ }
+ ty::UnsafeBinder(bound_ty) => {
+ stack.push(bound_ty.skip_binder().into());
+ }
+ },
+ ty::GenericArgKind::Lifetime(_) => {}
+ ty::GenericArgKind::Const(parent_ct) => match parent_ct.kind() {
+ ty::ConstKind::Infer(_)
+ | ty::ConstKind::Param(_)
+ | ty::ConstKind::Placeholder(_)
+ | ty::ConstKind::Bound(..)
+ | ty::ConstKind::Error(_) => {}
+
+ ty::ConstKind::Value(cv) => stack.push(cv.ty().into()),
+
+ ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
+ ty::ConstKind::Unevaluated(ct) => {
+ stack.extend(ct.args.iter().rev());
+ }
+ },
+ }
+}
diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs
index 8eefecd..3a10d0d 100644
--- a/compiler/rustc_type_ir_macros/src/lib.rs
+++ b/compiler/rustc_type_ir_macros/src/lib.rs
@@ -83,7 +83,7 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke
s.add_where_predicate(parse_quote! { I: Interner });
s.add_bounds(synstructure::AddBounds::Fields);
s.bind_with(|_| synstructure::BindStyle::Move);
- let body_fold = s.each_variant(|vi| {
+ let body_try_fold = s.each_variant(|vi| {
let bindings = vi.bindings();
vi.construct(|_, index| {
let bind = &bindings[index];
@@ -99,6 +99,22 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke
})
});
+ let body_fold = s.each_variant(|vi| {
+ let bindings = vi.bindings();
+ vi.construct(|_, index| {
+ let bind = &bindings[index];
+
+ // retain value of fields with #[type_foldable(identity)]
+ if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") {
+ bind.to_token_stream()
+ } else {
+ quote! {
+ ::rustc_type_ir::TypeFoldable::fold_with(#bind, __folder)
+ }
+ }
+ })
+ });
+
// We filter fields which get ignored and don't require them to implement
// `TypeFoldable`. We do so after generating `body_fold` as we still need
// to generate code for them.
@@ -111,7 +127,14 @@ fn try_fold_with<__F: ::rustc_type_ir::FallibleTypeFolder<I>>(
self,
__folder: &mut __F
) -> Result<Self, __F::Error> {
- Ok(match self { #body_fold })
+ Ok(match self { #body_try_fold })
+ }
+
+ fn fold_with<__F: ::rustc_type_ir::TypeFolder<I>>(
+ self,
+ __folder: &mut __F
+ ) -> Self {
+ match self { #body_fold }
}
},
)
diff --git a/library/Cargo.lock b/library/Cargo.lock
index d035ca6..e4f1c4e 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -67,9 +67,9 @@
[[package]]
name = "compiler_builtins"
-version = "0.1.153"
+version = "0.1.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "926ef6a360c15a911023352fd6969c51605d70495406f735beb1ca0257448e59"
+checksum = "341e0830ca6170a4fcf02e92e57daf4b6f10142d48da32a547023867a6c8b35e"
dependencies = [
"cc",
"rustc-std-workspace-core",
@@ -176,9 +176,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
"compiler_builtins",
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index ee8cb9d..cedbd33 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -16,7 +16,7 @@
[dependencies]
core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.153", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.155", features = ['rustc-dep-of-std'] }
[features]
compiler-builtins-mem = ['compiler_builtins/mem']
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index e40de13..30f4205 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -109,7 +109,7 @@
//! parameters (corresponding to `format_spec` in [the syntax](#syntax)). These
//! parameters affect the string representation of what's being formatted.
//!
-//! The colon `:` in format syntax divides indentifier of the input data and
+//! The colon `:` in format syntax divides identifier of the input data and
//! the formatting options, the colon itself does not change anything, only
//! introduces the options.
//!
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 1edade4..90f76d6 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -1,38 +1,35 @@
//! Defines the `IntoIter` owned iterator for arrays.
use crate::intrinsics::transmute_unchecked;
-use crate::iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce};
+use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce};
use crate::mem::MaybeUninit;
use crate::num::NonZero;
-use crate::ops::{IndexRange, Range};
+use crate::ops::{IndexRange, Range, Try};
use crate::{fmt, ptr};
+mod iter_inner;
+
+type InnerSized<T, const N: usize> = iter_inner::PolymorphicIter<[MaybeUninit<T>; N]>;
+type InnerUnsized<T> = iter_inner::PolymorphicIter<[MaybeUninit<T>]>;
+
/// A by-value [array] iterator.
#[stable(feature = "array_value_iter", since = "1.51.0")]
#[rustc_insignificant_dtor]
#[rustc_diagnostic_item = "ArrayIntoIter"]
+#[derive(Clone)]
pub struct IntoIter<T, const N: usize> {
- /// This is the array we are iterating over.
- ///
- /// Elements with index `i` where `alive.start <= i < alive.end` have not
- /// been yielded yet and are valid array entries. Elements with indices `i
- /// < alive.start` or `i >= alive.end` have been yielded already and must
- /// not be accessed anymore! Those dead elements might even be in a
- /// completely uninitialized state!
- ///
- /// So the invariants are:
- /// - `data[alive]` is alive (i.e. contains valid elements)
- /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
- /// elements were already read and must not be touched anymore!)
- data: [MaybeUninit<T>; N],
+ inner: InnerSized<T, N>,
+}
- /// The elements in `data` that have not been yielded yet.
- ///
- /// Invariants:
- /// - `alive.end <= N`
- ///
- /// (And the `IndexRange` type requires `alive.start <= alive.end`.)
- alive: IndexRange,
+impl<T, const N: usize> IntoIter<T, N> {
+ #[inline]
+ fn unsize(&self) -> &InnerUnsized<T> {
+ &self.inner
+ }
+ #[inline]
+ fn unsize_mut(&mut self) -> &mut InnerUnsized<T> {
+ &mut self.inner
+ }
}
// Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator`
@@ -53,6 +50,7 @@ pub struct IntoIter<T, const N: usize> {
/// 2021 edition -- see the [array] Editions section for more information.
///
/// [array]: prim@array
+ #[inline]
fn into_iter(self) -> Self::IntoIter {
// SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
// promise:
@@ -68,7 +66,10 @@ fn into_iter(self) -> Self::IntoIter {
// FIXME: If normal `transmute` ever gets smart enough to allow this
// directly, use it instead of `transmute_unchecked`.
let data: [MaybeUninit<T>; N] = unsafe { transmute_unchecked(self) };
- IntoIter { data, alive: IndexRange::zero_to(N) }
+ // SAFETY: The original array was entirely initialized and the the alive
+ // range we're passing here represents that fact.
+ let inner = unsafe { InnerSized::new_unchecked(IndexRange::zero_to(N), data) };
+ IntoIter { inner }
}
}
@@ -136,13 +137,16 @@ impl<T, const N: usize> IntoIter<T, N> {
/// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]);
/// ```
#[unstable(feature = "array_into_iter_constructors", issue = "91583")]
+ #[inline]
pub const unsafe fn new_unchecked(
buffer: [MaybeUninit<T>; N],
initialized: Range<usize>,
) -> Self {
// SAFETY: one of our safety conditions is that the range is canonical.
let alive = unsafe { IndexRange::new_unchecked(initialized.start, initialized.end) };
- Self { data: buffer, alive }
+ // SAFETY: one of our safety condition is that these items are initialized.
+ let inner = unsafe { InnerSized::new_unchecked(alive, buffer) };
+ IntoIter { inner }
}
/// Creates an iterator over `T` which returns no elements.
@@ -198,172 +202,134 @@ impl<T, const N: usize> IntoIter<T, N> {
/// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]);
/// ```
#[unstable(feature = "array_into_iter_constructors", issue = "91583")]
+ #[inline]
pub const fn empty() -> Self {
- let buffer = [const { MaybeUninit::uninit() }; N];
- let initialized = 0..0;
-
- // SAFETY: We're telling it that none of the elements are initialized,
- // which is trivially true. And ∀N: usize, 0 <= N.
- unsafe { Self::new_unchecked(buffer, initialized) }
+ let inner = InnerSized::empty();
+ IntoIter { inner }
}
/// Returns an immutable slice of all elements that have not been yielded
/// yet.
#[stable(feature = "array_value_iter", since = "1.51.0")]
+ #[inline]
pub fn as_slice(&self) -> &[T] {
- // SAFETY: We know that all elements within `alive` are properly initialized.
- unsafe {
- let slice = self.data.get_unchecked(self.alive.clone());
- slice.assume_init_ref()
- }
+ self.unsize().as_slice()
}
/// Returns a mutable slice of all elements that have not been yielded yet.
#[stable(feature = "array_value_iter", since = "1.51.0")]
+ #[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
- // SAFETY: We know that all elements within `alive` are properly initialized.
- unsafe {
- let slice = self.data.get_unchecked_mut(self.alive.clone());
- slice.assume_init_mut()
- }
+ self.unsize_mut().as_mut_slice()
}
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
- fn next(&mut self) -> Option<Self::Item> {
- // Get the next index from the front.
- //
- // Increasing `alive.start` by 1 maintains the invariant regarding
- // `alive`. However, due to this change, for a short time, the alive
- // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
- self.alive.next().map(|idx| {
- // Read the element from the array.
- // SAFETY: `idx` is an index into the former "alive" region of the
- // array. Reading this element means that `data[idx]` is regarded as
- // dead now (i.e. do not touch). As `idx` was the start of the
- // alive-zone, the alive zone is now `data[alive]` again, restoring
- // all invariants.
- unsafe { self.data.get_unchecked(idx).assume_init_read() }
- })
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.len();
- (len, Some(len))
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.unsize_mut().next()
}
#[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, mut fold: Fold) -> Acc
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.unsize().size_hint()
+ }
+
+ #[inline]
+ fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
{
- let data = &mut self.data;
- iter::ByRefSized(&mut self.alive).fold(init, |acc, idx| {
- // SAFETY: idx is obtained by folding over the `alive` range, which implies the
- // value is currently considered alive but as the range is being consumed each value
- // we read here will only be read once and then considered dead.
- fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() })
- })
+ self.unsize_mut().fold(init, fold)
}
+ #[inline]
+ fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ self.unsize_mut().try_fold(init, f)
+ }
+
+ #[inline]
fn count(self) -> usize {
self.len()
}
+ #[inline]
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
+ #[inline]
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
- // This also moves the start, which marks them as conceptually "dropped",
- // so if anything goes bad then our drop impl won't double-free them.
- let range_to_drop = self.alive.take_prefix(n);
- let remaining = n - range_to_drop.len();
-
- // SAFETY: These elements are currently initialized, so it's fine to drop them.
- unsafe {
- let slice = self.data.get_unchecked_mut(range_to_drop);
- slice.assume_init_drop();
- }
-
- NonZero::new(remaining).map_or(Ok(()), Err)
+ self.unsize_mut().advance_by(n)
}
#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// SAFETY: The caller must provide an idx that is in bound of the remainder.
- unsafe { self.data.as_ptr().add(self.alive.start()).add(idx).cast::<T>().read() }
+ let elem_ref = unsafe { self.as_mut_slice().get_unchecked_mut(idx) };
+ // SAFETY: We only implement `TrustedRandomAccessNoCoerce` for types
+ // which are actually `Copy`, so cannot have multiple-drop issues.
+ unsafe { ptr::read(elem_ref) }
}
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
+ #[inline]
fn next_back(&mut self) -> Option<Self::Item> {
- // Get the next index from the back.
- //
- // Decreasing `alive.end` by 1 maintains the invariant regarding
- // `alive`. However, due to this change, for a short time, the alive
- // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
- self.alive.next_back().map(|idx| {
- // Read the element from the array.
- // SAFETY: `idx` is an index into the former "alive" region of the
- // array. Reading this element means that `data[idx]` is regarded as
- // dead now (i.e. do not touch). As `idx` was the end of the
- // alive-zone, the alive zone is now `data[alive]` again, restoring
- // all invariants.
- unsafe { self.data.get_unchecked(idx).assume_init_read() }
- })
+ self.unsize_mut().next_back()
}
#[inline]
- fn rfold<Acc, Fold>(mut self, init: Acc, mut rfold: Fold) -> Acc
+ fn rfold<Acc, Fold>(mut self, init: Acc, rfold: Fold) -> Acc
where
Fold: FnMut(Acc, Self::Item) -> Acc,
{
- let data = &mut self.data;
- iter::ByRefSized(&mut self.alive).rfold(init, |acc, idx| {
- // SAFETY: idx is obtained by folding over the `alive` range, which implies the
- // value is currently considered alive but as the range is being consumed each value
- // we read here will only be read once and then considered dead.
- rfold(acc, unsafe { data.get_unchecked(idx).assume_init_read() })
- })
+ self.unsize_mut().rfold(init, rfold)
}
+ #[inline]
+ fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ self.unsize_mut().try_rfold(init, f)
+ }
+
+ #[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
- // This also moves the end, which marks them as conceptually "dropped",
- // so if anything goes bad then our drop impl won't double-free them.
- let range_to_drop = self.alive.take_suffix(n);
- let remaining = n - range_to_drop.len();
-
- // SAFETY: These elements are currently initialized, so it's fine to drop them.
- unsafe {
- let slice = self.data.get_unchecked_mut(range_to_drop);
- slice.assume_init_drop();
- }
-
- NonZero::new(remaining).map_or(Ok(()), Err)
+ self.unsize_mut().advance_back_by(n)
}
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, N> {
+ #[inline]
fn drop(&mut self) {
- // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
- // of elements that have not been moved out yet and that remain
- // to be dropped.
- unsafe { ptr::drop_in_place(self.as_mut_slice()) }
+ // `inner` now handles this, but it'd technically be a breaking change
+ // to remove this `impl`, even though it's useless.
}
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
+ #[inline]
fn len(&self) -> usize {
- self.alive.len()
+ self.inner.len()
}
+ #[inline]
fn is_empty(&self) -> bool {
- self.alive.is_empty()
+ self.inner.len() == 0
}
}
@@ -397,31 +363,8 @@ unsafe impl<T, const N: usize> TrustedRandomAccessNoCoerce for IntoIter<T, N>
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
- fn clone(&self) -> Self {
- // Note, we don't really need to match the exact same alive range, so
- // we can just clone into offset 0 regardless of where `self` is.
- let mut new =
- Self { data: [const { MaybeUninit::uninit() }; N], alive: IndexRange::zero_to(0) };
-
- // Clone all alive elements.
- for (src, dst) in iter::zip(self.as_slice(), &mut new.data) {
- // Write a clone into the new array, then update its alive range.
- // If cloning panics, we'll correctly drop the previous items.
- dst.write(src.clone());
- // This addition cannot overflow as we're iterating a slice
- new.alive = IndexRange::zero_to(new.alive.end() + 1);
- }
-
- new
- }
-}
-
-#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // Only print the elements that were not yielded yet: we cannot
- // access the yielded elements anymore.
- f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
+ self.unsize().fmt(f)
}
}
diff --git a/library/core/src/array/iter/iter_inner.rs b/library/core/src/array/iter/iter_inner.rs
new file mode 100644
index 0000000..3c23435
--- /dev/null
+++ b/library/core/src/array/iter/iter_inner.rs
@@ -0,0 +1,281 @@
+//! Defines the `IntoIter` owned iterator for arrays.
+
+use crate::mem::MaybeUninit;
+use crate::num::NonZero;
+use crate::ops::{IndexRange, NeverShortCircuit, Try};
+use crate::{fmt, iter};
+
+#[allow(private_bounds)]
+trait PartialDrop {
+ /// # Safety
+ /// `self[alive]` are all initialized before the call,
+ /// then are never used (without reinitializing them) after it.
+ unsafe fn partial_drop(&mut self, alive: IndexRange);
+}
+impl<T> PartialDrop for [MaybeUninit<T>] {
+ unsafe fn partial_drop(&mut self, alive: IndexRange) {
+ // SAFETY: We know that all elements within `alive` are properly initialized.
+ unsafe { self.get_unchecked_mut(alive).assume_init_drop() }
+ }
+}
+impl<T, const N: usize> PartialDrop for [MaybeUninit<T>; N] {
+ unsafe fn partial_drop(&mut self, alive: IndexRange) {
+ let slice: &mut [MaybeUninit<T>] = self;
+ // SAFETY: Initialized elements in the array are also initialized in the slice.
+ unsafe { slice.partial_drop(alive) }
+ }
+}
+
+/// The internals of a by-value array iterator.
+///
+/// The real `array::IntoIter<T, N>` stores a `PolymorphicIter<[MaybeUninit<T>, N]>`
+/// which it unsizes to `PolymorphicIter<[MaybeUninit<T>]>` to iterate.
+#[allow(private_bounds)]
+pub(super) struct PolymorphicIter<DATA: ?Sized>
+where
+ DATA: PartialDrop,
+{
+ /// The elements in `data` that have not been yielded yet.
+ ///
+ /// Invariants:
+ /// - `alive.end <= N`
+ ///
+ /// (And the `IndexRange` type requires `alive.start <= alive.end`.)
+ alive: IndexRange,
+
+ /// This is the array we are iterating over.
+ ///
+ /// Elements with index `i` where `alive.start <= i < alive.end` have not
+ /// been yielded yet and are valid array entries. Elements with indices `i
+ /// < alive.start` or `i >= alive.end` have been yielded already and must
+ /// not be accessed anymore! Those dead elements might even be in a
+ /// completely uninitialized state!
+ ///
+ /// So the invariants are:
+ /// - `data[alive]` is alive (i.e. contains valid elements)
+ /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
+ /// elements were already read and must not be touched anymore!)
+ data: DATA,
+}
+
+#[allow(private_bounds)]
+impl<DATA: ?Sized> PolymorphicIter<DATA>
+where
+ DATA: PartialDrop,
+{
+ #[inline]
+ pub(super) const fn len(&self) -> usize {
+ self.alive.len()
+ }
+}
+
+#[allow(private_bounds)]
+impl<DATA: ?Sized> Drop for PolymorphicIter<DATA>
+where
+ DATA: PartialDrop,
+{
+ #[inline]
+ fn drop(&mut self) {
+ // SAFETY: by our type invariant `self.alive` is exactly the initialized
+ // items, and this is drop so nothing can use the items afterwards.
+ unsafe { self.data.partial_drop(self.alive.clone()) }
+ }
+}
+
+impl<T, const N: usize> PolymorphicIter<[MaybeUninit<T>; N]> {
+ #[inline]
+ pub(super) const fn empty() -> Self {
+ Self { alive: IndexRange::zero_to(0), data: [const { MaybeUninit::uninit() }; N] }
+ }
+
+ /// # Safety
+ /// `data[alive]` are all initialized.
+ #[inline]
+ pub(super) const unsafe fn new_unchecked(alive: IndexRange, data: [MaybeUninit<T>; N]) -> Self {
+ Self { alive, data }
+ }
+}
+
+impl<T: Clone, const N: usize> Clone for PolymorphicIter<[MaybeUninit<T>; N]> {
+ #[inline]
+ fn clone(&self) -> Self {
+ // Note, we don't really need to match the exact same alive range, so
+ // we can just clone into offset 0 regardless of where `self` is.
+ let mut new = Self::empty();
+
+ fn clone_into_new<U: Clone>(
+ source: &PolymorphicIter<[MaybeUninit<U>]>,
+ target: &mut PolymorphicIter<[MaybeUninit<U>]>,
+ ) {
+ // Clone all alive elements.
+ for (src, dst) in iter::zip(source.as_slice(), &mut target.data) {
+ // Write a clone into the new array, then update its alive range.
+ // If cloning panics, we'll correctly drop the previous items.
+ dst.write(src.clone());
+ // This addition cannot overflow as we're iterating a slice,
+ // the length of which always fits in usize.
+ target.alive = IndexRange::zero_to(target.alive.end() + 1);
+ }
+ }
+
+ clone_into_new(self, &mut new);
+ new
+ }
+}
+
+impl<T> PolymorphicIter<[MaybeUninit<T>]> {
+ #[inline]
+ pub(super) fn as_slice(&self) -> &[T] {
+ // SAFETY: We know that all elements within `alive` are properly initialized.
+ unsafe {
+ let slice = self.data.get_unchecked(self.alive.clone());
+ slice.assume_init_ref()
+ }
+ }
+
+ #[inline]
+ pub(super) fn as_mut_slice(&mut self) -> &mut [T] {
+ // SAFETY: We know that all elements within `alive` are properly initialized.
+ unsafe {
+ let slice = self.data.get_unchecked_mut(self.alive.clone());
+ slice.assume_init_mut()
+ }
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for PolymorphicIter<[MaybeUninit<T>]> {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Only print the elements that were not yielded yet: we cannot
+ // access the yielded elements anymore.
+ f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
+ }
+}
+
+/// Iterator-equivalent methods.
+///
+/// We don't implement the actual iterator traits because we want to implement
+/// things like `try_fold` that require `Self: Sized` (which we're not).
+impl<T> PolymorphicIter<[MaybeUninit<T>]> {
+ #[inline]
+ pub(super) fn next(&mut self) -> Option<T> {
+ // Get the next index from the front.
+ //
+ // Increasing `alive.start` by 1 maintains the invariant regarding
+ // `alive`. However, due to this change, for a short time, the alive
+ // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
+ self.alive.next().map(|idx| {
+ // Read the element from the array.
+ // SAFETY: `idx` is an index into the former "alive" region of the
+ // array. Reading this element means that `data[idx]` is regarded as
+ // dead now (i.e. do not touch). As `idx` was the start of the
+ // alive-zone, the alive zone is now `data[alive]` again, restoring
+ // all invariants.
+ unsafe { self.data.get_unchecked(idx).assume_init_read() }
+ })
+ }
+
+ #[inline]
+ pub(super) fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.len();
+ (len, Some(len))
+ }
+
+ #[inline]
+ pub(super) fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+ // This also moves the start, which marks them as conceptually "dropped",
+ // so if anything goes bad then our drop impl won't double-free them.
+ let range_to_drop = self.alive.take_prefix(n);
+ let remaining = n - range_to_drop.len();
+
+ // SAFETY: These elements are currently initialized, so it's fine to drop them.
+ unsafe {
+ let slice = self.data.get_unchecked_mut(range_to_drop);
+ slice.assume_init_drop();
+ }
+
+ NonZero::new(remaining).map_or(Ok(()), Err)
+ }
+
+ #[inline]
+ pub(super) fn fold<B>(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B {
+ self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
+ }
+
+ #[inline]
+ pub(super) fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
+ where
+ F: FnMut(B, T) -> R,
+ R: Try<Output = B>,
+ {
+ // `alive` is an `IndexRange`, not an arbitrary iterator, so we can
+ // trust that its `try_fold` isn't going to do something weird like
+ // call the fold-er multiple times for the same index.
+ let data = &mut self.data;
+ self.alive.try_fold(init, move |accum, idx| {
+ // SAFETY: `idx` has been removed from the alive range, so we're not
+ // going to drop it (even if `f` panics) and thus its ok to give
+ // out ownership of that item to `f` to handle.
+ let elem = unsafe { data.get_unchecked(idx).assume_init_read() };
+ f(accum, elem)
+ })
+ }
+
+ #[inline]
+ pub(super) fn next_back(&mut self) -> Option<T> {
+ // Get the next index from the back.
+ //
+ // Decreasing `alive.end` by 1 maintains the invariant regarding
+ // `alive`. However, due to this change, for a short time, the alive
+ // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
+ self.alive.next_back().map(|idx| {
+ // Read the element from the array.
+ // SAFETY: `idx` is an index into the former "alive" region of the
+ // array. Reading this element means that `data[idx]` is regarded as
+ // dead now (i.e. do not touch). As `idx` was the end of the
+ // alive-zone, the alive zone is now `data[alive]` again, restoring
+ // all invariants.
+ unsafe { self.data.get_unchecked(idx).assume_init_read() }
+ })
+ }
+
+ #[inline]
+ pub(super) fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+ // This also moves the end, which marks them as conceptually "dropped",
+ // so if anything goes bad then our drop impl won't double-free them.
+ let range_to_drop = self.alive.take_suffix(n);
+ let remaining = n - range_to_drop.len();
+
+ // SAFETY: These elements are currently initialized, so it's fine to drop them.
+ unsafe {
+ let slice = self.data.get_unchecked_mut(range_to_drop);
+ slice.assume_init_drop();
+ }
+
+ NonZero::new(remaining).map_or(Ok(()), Err)
+ }
+
+ #[inline]
+ pub(super) fn rfold<B>(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B {
+ self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
+ }
+
+ #[inline]
+ pub(super) fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
+ where
+ F: FnMut(B, T) -> R,
+ R: Try<Output = B>,
+ {
+ // `alive` is an `IndexRange`, not an arbitrary iterator, so we can
+ // trust that its `try_rfold` isn't going to do something weird like
+ // call the fold-er multiple times for the same index.
+ let data = &mut self.data;
+ self.alive.try_rfold(init, move |accum, idx| {
+ // SAFETY: `idx` has been removed from the alive range, so we're not
+ // going to drop it (even if `f` panics) and thus its ok to give
+ // out ownership of that item to `f` to handle.
+ let elem = unsafe { data.get_unchecked(idx).assume_init_read() };
+ f(accum, elem)
+ })
+ }
+}
diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs
index d525ab4..2016ece 100644
--- a/library/core/src/bool.rs
+++ b/library/core/src/bool.rs
@@ -61,52 +61,4 @@ pub fn then_some<T>(self, t: T) -> Option<T> {
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self { Some(f()) } else { None }
}
-
- /// Returns either `true_val` or `false_val` depending on the value of
- /// `self`, with a hint to the compiler that `self` is unlikely
- /// to be correctly predicted by a CPU’s branch predictor.
- ///
- /// This method is functionally equivalent to
- /// ```ignore (this is just for illustrative purposes)
- /// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
- /// if b { true_val } else { false_val }
- /// }
- /// ```
- /// but might generate different assembly. In particular, on platforms with
- /// a conditional move or select instruction (like `cmov` on x86 or `csel`
- /// on ARM) the optimizer might use these instructions to avoid branches,
- /// which can benefit performance if the branch predictor is struggling
- /// with predicting `condition`, such as in an implementation of binary
- /// search.
- ///
- /// Note however that this lowering is not guaranteed (on any platform) and
- /// should not be relied upon when trying to write constant-time code. Also
- /// be aware that this lowering might *decrease* performance if `condition`
- /// is well-predictable. It is advisable to perform benchmarks to tell if
- /// this function is useful.
- ///
- /// # Examples
- ///
- /// Distribute values evenly between two buckets:
- /// ```
- /// #![feature(select_unpredictable)]
- ///
- /// use std::hash::BuildHasher;
- ///
- /// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
- /// let hash = hasher.hash_one(&v);
- /// let bucket = (hash % 2 == 0).select_unpredictable(bucket_one, bucket_two);
- /// bucket.push(v);
- /// }
- /// # let hasher = std::collections::hash_map::RandomState::new();
- /// # let mut bucket_one = Vec::new();
- /// # let mut bucket_two = Vec::new();
- /// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
- /// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
- /// ```
- #[inline(always)]
- #[unstable(feature = "select_unpredictable", issue = "133962")]
- pub fn select_unpredictable<T>(self, true_val: T, false_val: T) -> T {
- crate::intrinsics::select_unpredictable(self, true_val, false_val)
- }
}
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 0dc2cc7..c315131 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -2053,6 +2053,22 @@ fn gt(&self, other: &&B) -> bool {
fn ge(&self, other: &&B) -> bool {
PartialOrd::ge(*self, *other)
}
+ #[inline]
+ fn __chaining_lt(&self, other: &&B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_lt(*self, *other)
+ }
+ #[inline]
+ fn __chaining_le(&self, other: &&B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_le(*self, *other)
+ }
+ #[inline]
+ fn __chaining_gt(&self, other: &&B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_gt(*self, *other)
+ }
+ #[inline]
+ fn __chaining_ge(&self, other: &&B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_ge(*self, *other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &A
@@ -2108,6 +2124,22 @@ fn gt(&self, other: &&mut B) -> bool {
fn ge(&self, other: &&mut B) -> bool {
PartialOrd::ge(*self, *other)
}
+ #[inline]
+ fn __chaining_lt(&self, other: &&mut B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_lt(*self, *other)
+ }
+ #[inline]
+ fn __chaining_le(&self, other: &&mut B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_le(*self, *other)
+ }
+ #[inline]
+ fn __chaining_gt(&self, other: &&mut B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_gt(*self, *other)
+ }
+ #[inline]
+ fn __chaining_ge(&self, other: &&mut B) -> ControlFlow<bool> {
+ PartialOrd::__chaining_ge(*self, *other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &mut A
diff --git a/library/core/src/contracts.rs b/library/core/src/contracts.rs
index 8b79a3a..495f84b 100644
--- a/library/core/src/contracts.rs
+++ b/library/core/src/contracts.rs
@@ -2,19 +2,23 @@
pub use crate::macros::builtin::{contracts_ensures as ensures, contracts_requires as requires};
-/// Emitted by rustc as a desugaring of `#[ensures(PRED)] fn foo() -> R { ... [return R;] ... }`
-/// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }`
-/// (including the implicit return of the tail expression, if any).
+/// This is an identity function used as part of the desugaring of the `#[ensures]` attribute.
+///
+/// This is an existing hack to allow users to omit the type of the return value in their ensures
+/// attribute.
+///
+/// Ideally, rustc should be able to generate the type annotation.
+/// The existing lowering logic makes it rather hard to add the explicit type annotation,
+/// while the function call is fairly straight forward.
#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
+// Similar to `contract_check_requires`, we need to use the user-facing
+// `contracts` feature rather than the perma-unstable `contracts_internals`.
+// Const-checking doesn't honor allow_internal_unstable logic used by contract expansion.
+#[rustc_const_unstable(feature = "contracts", issue = "128044")]
#[lang = "contract_build_check_ensures"]
-#[track_caller]
-pub fn build_check_ensures<Ret, C>(cond: C) -> impl (Fn(Ret) -> Ret) + Copy
+pub const fn build_check_ensures<Ret, C>(cond: C) -> C
where
- C: for<'a> Fn(&'a Ret) -> bool + Copy + 'static,
+ C: Fn(&Ret) -> bool + Copy + 'static,
{
- #[track_caller]
- move |ret| {
- crate::intrinsics::contract_check_ensures(&ret, cond);
- ret
- }
+ cond
}
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 7ca3909..580f95e 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -7,7 +7,7 @@
use crate::marker::PhantomData;
use crate::num::fmt as numfmt;
use crate::ops::Deref;
-use crate::{iter, mem, result, str};
+use crate::{iter, result, str};
mod builders;
#[cfg(not(no_fp_fmt_parse))]
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 0459674..adcfdd3 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -65,61 +65,92 @@ pub struct Argument<'a> {
ty: ArgumentType<'a>,
}
-#[rustc_diagnostic_item = "ArgumentMethods"]
-impl Argument<'_> {
- #[inline]
- const fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
+macro_rules! argument_new {
+ ($t:ty, $x:expr, $f:expr) => {
Argument {
// INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
// a `fn(&T, ...)`, so the invariant is maintained.
ty: ArgumentType::Placeholder {
- value: NonNull::from_ref(x).cast(),
- // SAFETY: function pointers always have the same layout.
- formatter: unsafe { mem::transmute(f) },
+ value: NonNull::<$t>::from_ref($x).cast(),
+ // The Rust ABI considers all pointers to be equivalent, so transmuting a fn(&T) to
+ // fn(NonNull<()>) and calling it with a NonNull<()> that points at a T is allowed.
+ // However, the CFI sanitizer does not allow this, and triggers a crash when it
+ // happens.
+ //
+ // To avoid this crash, we use a helper function when CFI is enabled. To avoid the
+ // cost of this helper function (mainly code-size) when it is not needed, we
+ // transmute the function pointer otherwise.
+ //
+ // This is similar to what the Rust compiler does internally with vtables when KCFI
+ // is enabled, where it generates trampoline functions that only serve to adjust the
+ // expected type of the argument. `ArgumentType::Placeholder` is a bit like a
+ // manually constructed trait object, so it is not surprising that the same approach
+ // has to be applied here as well.
+ //
+ // It is still considered problematic (from the Rust side) that CFI rejects entirely
+ // legal Rust programs, so we do not consider anything done here a stable guarantee,
+ // but meanwhile we carry this work-around to keep Rust compatible with CFI and
+ // KCFI.
+ #[cfg(not(any(sanitize = "cfi", sanitize = "kcfi")))]
+ formatter: {
+ let f: fn(&$t, &mut Formatter<'_>) -> Result = $f;
+ // SAFETY: This is only called with `value`, which has the right type.
+ unsafe { core::mem::transmute(f) }
+ },
+ #[cfg(any(sanitize = "cfi", sanitize = "kcfi"))]
+ formatter: |ptr: NonNull<()>, fmt: &mut Formatter<'_>| {
+ let func = $f;
+ // SAFETY: This is the same type as the `value` field.
+ let r = unsafe { ptr.cast::<$t>().as_ref() };
+ (func)(r, fmt)
+ },
_lifetime: PhantomData,
},
}
- }
+ };
+}
+#[rustc_diagnostic_item = "ArgumentMethods"]
+impl Argument<'_> {
#[inline]
pub fn new_display<T: Display>(x: &T) -> Argument<'_> {
- Self::new(x, Display::fmt)
+ argument_new!(T, x, <T as Display>::fmt)
}
#[inline]
pub fn new_debug<T: Debug>(x: &T) -> Argument<'_> {
- Self::new(x, Debug::fmt)
+ argument_new!(T, x, <T as Debug>::fmt)
}
#[inline]
pub fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> {
- Self::new(x, |_, _| Ok(()))
+ argument_new!(T, x, |_: &T, _| Ok(()))
}
#[inline]
pub fn new_octal<T: Octal>(x: &T) -> Argument<'_> {
- Self::new(x, Octal::fmt)
+ argument_new!(T, x, <T as Octal>::fmt)
}
#[inline]
pub fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> {
- Self::new(x, LowerHex::fmt)
+ argument_new!(T, x, <T as LowerHex>::fmt)
}
#[inline]
pub fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> {
- Self::new(x, UpperHex::fmt)
+ argument_new!(T, x, <T as UpperHex>::fmt)
}
#[inline]
pub fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> {
- Self::new(x, Pointer::fmt)
+ argument_new!(T, x, <T as Pointer>::fmt)
}
#[inline]
pub fn new_binary<T: Binary>(x: &T) -> Argument<'_> {
- Self::new(x, Binary::fmt)
+ argument_new!(T, x, <T as Binary>::fmt)
}
#[inline]
pub fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> {
- Self::new(x, LowerExp::fmt)
+ argument_new!(T, x, <T as LowerExp>::fmt)
}
#[inline]
pub fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> {
- Self::new(x, UpperExp::fmt)
+ argument_new!(T, x, <T as UpperExp>::fmt)
}
#[inline]
#[track_caller]
@@ -135,11 +166,6 @@ pub const fn from_usize(x: &usize) -> Argument<'_> {
/// # Safety
///
/// This argument must actually be a placeholder argument.
- ///
- // FIXME: Transmuting formatter in new and indirectly branching to/calling
- // it here is an explicit CFI violation.
- #[allow(inline_no_sanitize)]
- #[no_sanitize(cfi, kcfi)]
#[inline]
pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self.ty {
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 5ce282b..1ca23ab 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -4,6 +4,7 @@
//!
//! Hints may be compile time or runtime.
+use crate::mem::MaybeUninit;
use crate::{intrinsics, ub_checks};
/// Informs the compiler that the site which is calling this function is not
@@ -734,3 +735,63 @@ pub const fn unlikely(b: bool) -> bool {
pub const fn cold_path() {
crate::intrinsics::cold_path()
}
+
+/// Returns either `true_val` or `false_val` depending on the value of
+/// `condition`, with a hint to the compiler that `condition` is unlikely to be
+/// correctly predicted by a CPU’s branch predictor.
+///
+/// This method is functionally equivalent to
+/// ```ignore (this is just for illustrative purposes)
+/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
+/// if b { true_val } else { false_val }
+/// }
+/// ```
+/// but might generate different assembly. In particular, on platforms with
+/// a conditional move or select instruction (like `cmov` on x86 or `csel`
+/// on ARM) the optimizer might use these instructions to avoid branches,
+/// which can benefit performance if the branch predictor is struggling
+/// with predicting `condition`, such as in an implementation of binary
+/// search.
+///
+/// Note however that this lowering is not guaranteed (on any platform) and
+/// should not be relied upon when trying to write cryptographic constant-time
+/// code. Also be aware that this lowering might *decrease* performance if
+/// `condition` is well-predictable. It is advisable to perform benchmarks to
+/// tell if this function is useful.
+///
+/// # Examples
+///
+/// Distribute values evenly between two buckets:
+/// ```
+/// #![feature(select_unpredictable)]
+///
+/// use std::hash::BuildHasher;
+/// use std::hint;
+///
+/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
+/// let hash = hasher.hash_one(&v);
+/// let bucket = hint::select_unpredictable(hash % 2 == 0, bucket_one, bucket_two);
+/// bucket.push(v);
+/// }
+/// # let hasher = std::collections::hash_map::RandomState::new();
+/// # let mut bucket_one = Vec::new();
+/// # let mut bucket_two = Vec::new();
+/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
+/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
+/// ```
+#[inline(always)]
+#[unstable(feature = "select_unpredictable", issue = "133962")]
+pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T {
+ // FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/245):
+ // Change this to use ManuallyDrop instead.
+ let mut true_val = MaybeUninit::new(true_val);
+ let mut false_val = MaybeUninit::new(false_val);
+ // SAFETY: The value that is not selected is dropped, and the selected one
+ // is returned. This is necessary because the intrinsic doesn't drop the
+ // value that is not selected.
+ unsafe {
+ crate::intrinsics::select_unpredictable(!condition, &mut true_val, &mut false_val)
+ .assume_init_drop();
+ crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init()
+ }
+}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index ad33e2e..a01efb2 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1326,7 +1326,9 @@ pub const fn unlikely(b: bool) -> bool {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
-/// The public form of this instrinsic is [`bool::select_unpredictable`].
+/// The public form of this instrinsic is [`core::hint::select_unpredictable`].
+/// However unlike the public form, the intrinsic will not drop the value that
+/// is not selected.
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_nounwind]
@@ -2628,13 +2630,15 @@ pub unsafe fn rintf64(x: f64) -> f64 {
#[rustc_intrinsic]
pub const fn bitreverse<T: Copy>(x: T) -> T;
-/// Does a three-way comparison between the two integer arguments.
+/// Does a three-way comparison between the two arguments,
+/// which must be of character or integer (signed or unsigned) type.
///
-/// This is included as an intrinsic as it's useful to let it be one thing
-/// in MIR, rather than the multiple checks and switches that make its IR
-/// large and difficult to optimize.
+/// This was originally added because it greatly simplified the MIR in `cmp`
+/// implementations, and then LLVM 20 added a backend intrinsic for it too.
///
/// The stabilized version of this intrinsic is [`Ord::cmp`].
+#[rustc_intrinsic_const_stable_indirect]
+#[rustc_nounwind]
#[rustc_intrinsic]
pub const fn three_way_compare<T: Copy>(lhs: T, rhss: T) -> crate::cmp::Ordering;
@@ -2735,6 +2739,7 @@ pub const fn carrying_mul_add<T: ~const fallback::CarryingMulAdd<Unsigned = U>,
/// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`
///
/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic_const_stable_indirect]
#[rustc_nounwind]
#[rustc_intrinsic]
pub const unsafe fn exact_div<T: Copy>(x: T, y: T) -> T;
@@ -3399,20 +3404,62 @@ pub const fn contract_checks() -> bool {
///
/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
/// returns false.
-#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
+///
+/// Note that this function is a no-op during constant evaluation.
+#[unstable(feature = "contracts_internals", issue = "128044")]
+// Calls to this function get inserted by an AST expansion pass, which uses the equivalent of
+// `#[allow_internal_unstable]` to allow using `contracts_internals` functions. Const-checking
+// doesn't honor `#[allow_internal_unstable]`, so for the const feature gate we use the user-facing
+// `contracts` feature rather than the perma-unstable `contracts_internals`
+#[rustc_const_unstable(feature = "contracts", issue = "128044")]
#[lang = "contract_check_requires"]
#[rustc_intrinsic]
-pub fn contract_check_requires<C: Fn() -> bool>(cond: C) {
- if contract_checks() && !cond() {
- // Emit no unwind panic in case this was a safety requirement.
- crate::panicking::panic_nounwind("failed requires check");
- }
+pub const fn contract_check_requires<C: Fn() -> bool + Copy>(cond: C) {
+ const_eval_select!(
+ @capture[C: Fn() -> bool + Copy] { cond: C } :
+ if const {
+ // Do nothing
+ } else {
+ if contract_checks() && !cond() {
+ // Emit no unwind panic in case this was a safety requirement.
+ crate::panicking::panic_nounwind("failed requires check");
+ }
+ }
+ )
}
/// Check if the post-condition `cond` has been met.
///
/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
/// returns false.
+///
+/// Note that this function is a no-op during constant evaluation.
+#[cfg(not(bootstrap))]
+#[unstable(feature = "contracts_internals", issue = "128044")]
+// Similar to `contract_check_requires`, we need to use the user-facing
+// `contracts` feature rather than the perma-unstable `contracts_internals`.
+// Const-checking doesn't honor allow_internal_unstable logic used by contract expansion.
+#[rustc_const_unstable(feature = "contracts", issue = "128044")]
+#[lang = "contract_check_ensures"]
+#[rustc_intrinsic]
+pub const fn contract_check_ensures<C: Fn(&Ret) -> bool + Copy, Ret>(cond: C, ret: Ret) -> Ret {
+ const_eval_select!(
+ @capture[C: Fn(&Ret) -> bool + Copy, Ret] { cond: C, ret: Ret } -> Ret :
+ if const {
+ // Do nothing
+ ret
+ } else {
+ if contract_checks() && !cond(&ret) {
+ // Emit no unwind panic in case this was a safety requirement.
+ crate::panicking::panic_nounwind("failed ensures check");
+ }
+ ret
+ }
+ )
+}
+
+/// This is the old version of contract_check_ensures kept here for bootstrap only.
+#[cfg(bootstrap)]
#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
#[rustc_intrinsic]
pub fn contract_check_ensures<'a, Ret, C: Fn(&'a Ret) -> bool>(ret: &'a Ret, cond: C) {
diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs
index aea6d64..72d7462 100644
--- a/library/core/src/iter/adapters/cloned.rs
+++ b/library/core/src/iter/adapters/cloned.rs
@@ -1,5 +1,6 @@
use core::num::NonZero;
+use crate::cmp::Ordering;
use crate::iter::adapters::zip::try_get_unchecked;
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
@@ -41,13 +42,31 @@ fn next(&mut self) -> Option<T> {
self.it.next().cloned()
}
+ #[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
+ #[inline]
+ fn count(self) -> usize {
+ self.it.count()
+ }
+
+ fn last(self) -> Option<T> {
+ self.it.last().cloned()
+ }
+
+ #[inline]
+ fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+ self.it.advance_by(n)
+ }
+
+ fn nth(&mut self, n: usize) -> Option<T> {
+ self.it.nth(n).cloned()
+ }
+
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
- Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
@@ -61,6 +80,58 @@ fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
self.it.map(T::clone).fold(init, f)
}
+ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
+ where
+ P: FnMut(&Self::Item) -> bool,
+ {
+ self.it.find(move |x| predicate(&x)).cloned()
+ }
+
+ fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
+ where
+ F: FnMut(&Self::Item, &Self::Item) -> Ordering,
+ {
+ self.it.max_by(move |&x, &y| compare(x, y)).cloned()
+ }
+
+ fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
+ where
+ F: FnMut(&Self::Item, &Self::Item) -> Ordering,
+ {
+ self.it.min_by(move |&x, &y| compare(x, y)).cloned()
+ }
+
+ fn cmp<O>(self, other: O) -> Ordering
+ where
+ O: IntoIterator<Item = Self::Item>,
+ Self::Item: Ord,
+ {
+ self.it.cmp_by(other, |x, y| x.cmp(&y))
+ }
+
+ fn partial_cmp<O>(self, other: O) -> Option<Ordering>
+ where
+ O: IntoIterator,
+ Self::Item: PartialOrd<O::Item>,
+ {
+ self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
+ }
+
+ fn eq<O>(self, other: O) -> bool
+ where
+ O: IntoIterator,
+ Self::Item: PartialEq<O::Item>,
+ {
+ self.it.eq_by(other, |x, y| x == &y)
+ }
+
+ fn is_sorted_by<F>(self, mut compare: F) -> bool
+ where
+ F: FnMut(&Self::Item, &Self::Item) -> bool,
+ {
+ self.it.is_sorted_by(move |&x, &y| compare(x, y))
+ }
+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
where
Self: TrustedRandomAccessNoCoerce,
@@ -81,9 +152,13 @@ fn next_back(&mut self) -> Option<T> {
self.it.next_back().cloned()
}
+ #[inline]
+ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+ self.it.advance_back_by(n)
+ }
+
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
where
- Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
@@ -96,6 +171,13 @@ fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
{
self.it.map(T::clone).rfold(init, f)
}
+
+ fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
+ where
+ P: FnMut(&Self::Item) -> bool,
+ {
+ self.it.rfind(move |x| predicate(&x)).cloned()
+ }
}
#[stable(feature = "iter_cloned", since = "1.1.0")]
@@ -104,10 +186,12 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
I: ExactSizeIterator<Item = &'a T>,
T: Clone,
{
+ #[inline]
fn len(&self) -> usize {
self.it.len()
}
+ #[inline]
fn is_empty(&self) -> bool {
self.it.is_empty()
}
diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs
index 23e4e25..73913aa 100644
--- a/library/core/src/iter/adapters/copied.rs
+++ b/library/core/src/iter/adapters/copied.rs
@@ -1,3 +1,4 @@
+use crate::cmp::Ordering;
use crate::iter::adapters::zip::try_get_unchecked;
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
@@ -48,20 +49,35 @@ fn next(&mut self) -> Option<T> {
fn next_chunk<const N: usize>(
&mut self,
- ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
- where
- Self: Sized,
- {
+ ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
<I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
}
+ #[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
+ #[inline]
+ fn count(self) -> usize {
+ self.it.count()
+ }
+
+ fn last(self) -> Option<T> {
+ self.it.last().copied()
+ }
+
+ #[inline]
+ fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+ self.it.advance_by(n)
+ }
+
+ fn nth(&mut self, n: usize) -> Option<T> {
+ self.it.nth(n).copied()
+ }
+
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
- Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
@@ -75,21 +91,56 @@ fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
self.it.fold(init, copy_fold(f))
}
- fn nth(&mut self, n: usize) -> Option<T> {
- self.it.nth(n).copied()
+ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
+ where
+ P: FnMut(&Self::Item) -> bool,
+ {
+ self.it.find(move |x| predicate(&x)).copied()
}
- fn last(self) -> Option<T> {
- self.it.last().copied()
+ fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
+ where
+ F: FnMut(&Self::Item, &Self::Item) -> Ordering,
+ {
+ self.it.max_by(move |&x, &y| compare(x, y)).copied()
}
- fn count(self) -> usize {
- self.it.count()
+ fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
+ where
+ F: FnMut(&Self::Item, &Self::Item) -> Ordering,
+ {
+ self.it.min_by(move |&x, &y| compare(x, y)).copied()
}
- #[inline]
- fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
- self.it.advance_by(n)
+ fn cmp<O>(self, other: O) -> Ordering
+ where
+ O: IntoIterator<Item = Self::Item>,
+ Self::Item: Ord,
+ {
+ self.it.cmp_by(other, |x, y| x.cmp(&y))
+ }
+
+ fn partial_cmp<O>(self, other: O) -> Option<Ordering>
+ where
+ O: IntoIterator,
+ Self::Item: PartialOrd<O::Item>,
+ {
+ self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
+ }
+
+ fn eq<O>(self, other: O) -> bool
+ where
+ O: IntoIterator,
+ Self::Item: PartialEq<O::Item>,
+ {
+ self.it.eq_by(other, |x, y| x == &y)
+ }
+
+ fn is_sorted_by<F>(self, mut compare: F) -> bool
+ where
+ F: FnMut(&Self::Item, &Self::Item) -> bool,
+ {
+ self.it.is_sorted_by(move |&x, &y| compare(x, y))
}
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
@@ -112,9 +163,13 @@ fn next_back(&mut self) -> Option<T> {
self.it.next_back().copied()
}
+ #[inline]
+ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+ self.it.advance_back_by(n)
+ }
+
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
where
- Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
@@ -128,9 +183,11 @@ fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
self.it.rfold(init, copy_fold(f))
}
- #[inline]
- fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
- self.it.advance_back_by(n)
+ fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
+ where
+ P: FnMut(&Self::Item) -> bool,
+ {
+ self.it.rfind(move |x| predicate(&x)).copied()
}
}
@@ -140,10 +197,12 @@ impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
I: ExactSizeIterator<Item = &'a T>,
T: Copy,
{
+ #[inline]
fn len(&self) -> usize {
self.it.len()
}
+ #[inline]
fn is_empty(&self) -> bool {
self.it.is_empty()
}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index dc06aa4..9625475 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -101,7 +101,6 @@
#![feature(bstr)]
#![feature(bstr_internals)]
#![feature(cfg_match)]
-#![feature(closure_track_caller)]
#![feature(const_carrying_mul_add)]
#![feature(const_eval_select)]
#![feature(core_intrinsics)]
@@ -127,6 +126,7 @@
#![feature(ub_checks)]
#![feature(unchecked_neg)]
#![feature(unchecked_shifts)]
+#![feature(unsafe_pinned)]
#![feature(utf16_extra)]
#![feature(variant_count)]
// tidy-alphabetical-end
@@ -169,7 +169,6 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(no_core)]
-#![feature(no_sanitize)]
#![feature(optimize_attribute)]
#![feature(prelude_import)]
#![feature(repr_simd)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 6801131..9dc20be 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -17,6 +17,7 @@
use crate::cmp;
use crate::fmt::Debug;
use crate::hash::{Hash, Hasher};
+use crate::pin::UnsafePinned;
/// Implements a given marker trait for multiple types at the same time.
///
@@ -878,6 +879,23 @@ impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
{T: ?Sized} &mut T,
}
+/// Used to determine whether a type contains any `UnsafePinned` (or `PhantomPinned`) internally,
+/// but not through an indirection. This affects, for example, whether we emit `noalias` metadata
+/// for `&mut T` or not.
+///
+/// This is part of [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html), and is
+/// tracked by [#125735](https://github.com/rust-lang/rust/issues/125735).
+#[cfg_attr(not(bootstrap), lang = "unsafe_unpin")]
+#[cfg_attr(bootstrap, allow(dead_code))]
+pub(crate) unsafe auto trait UnsafeUnpin {}
+
+impl<T: ?Sized> !UnsafeUnpin for UnsafePinned<T> {}
+unsafe impl<T: ?Sized> UnsafeUnpin for PhantomData<T> {}
+unsafe impl<T: ?Sized> UnsafeUnpin for *const T {}
+unsafe impl<T: ?Sized> UnsafeUnpin for *mut T {}
+unsafe impl<T: ?Sized> UnsafeUnpin for &T {}
+unsafe impl<T: ?Sized> UnsafeUnpin for &mut T {}
+
/// Types that do not require any pinning guarantees.
///
/// For information on what "pinning" is, see the [`pin` module] documentation.
@@ -953,6 +971,11 @@ impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
/// A marker type which does not implement `Unpin`.
///
/// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default.
+//
+// FIXME(unsafe_pinned): This is *not* a stable guarantee we want to make, at least not yet.
+// Note that for backwards compatibility with the new [`UnsafePinned`] wrapper type, placing this
+// marker in your struct acts as if you wrapped the entire struct in an `UnsafePinned`. This type
+// will likely eventually be deprecated, and all new code should be using `UnsafePinned` instead.
#[stable(feature = "pin", since = "1.33.0")]
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct PhantomPinned;
@@ -960,6 +983,12 @@ impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
#[stable(feature = "pin", since = "1.33.0")]
impl !Unpin for PhantomPinned {}
+// This is a small hack to allow existing code which uses PhantomPinned to opt-out of noalias to
+// continue working. Ideally PhantomPinned could just wrap an `UnsafePinned<()>` to get the same
+// effect, but we can't add a new field to an already stable unit struct -- that would be a breaking
+// change.
+impl !UnsafeUnpin for PhantomPinned {}
+
marker_impls! {
#[stable(feature = "pin", since = "1.33.0")]
Unpin for
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 08c34e8..d3d1eeb 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -224,14 +224,16 @@ impl f128 {
/// Not a Number (NaN).
///
- /// Note that IEEE 754 doesn't define just a single NaN value;
- /// a plethora of bit patterns are considered to be NaN.
- /// Furthermore, the standard makes a difference
- /// between a "signaling" and a "quiet" NaN,
- /// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
- /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
- /// and the stability of its representation over Rust versions
- /// and target platforms isn't guaranteed.
+ /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are
+ /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and
+ /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern)
+ /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions
+ /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is
+ /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary.
+ /// The concrete bit pattern may change across Rust versions and target platforms.
#[allow(clippy::eq_op)]
#[rustc_diagnostic_item = "f128_nan"]
#[unstable(feature = "f128", issue = "116909")]
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index a33e5f5..dceb301 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -219,14 +219,16 @@ impl f16 {
/// Not a Number (NaN).
///
- /// Note that IEEE 754 doesn't define just a single NaN value;
- /// a plethora of bit patterns are considered to be NaN.
- /// Furthermore, the standard makes a difference
- /// between a "signaling" and a "quiet" NaN,
- /// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
- /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
- /// and the stability of its representation over Rust versions
- /// and target platforms isn't guaranteed.
+ /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are
+ /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and
+ /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern)
+ /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions
+ /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is
+ /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary.
+ /// The concrete bit pattern may change across Rust versions and target platforms.
#[allow(clippy::eq_op)]
#[rustc_diagnostic_item = "f16_nan"]
#[unstable(feature = "f16", issue = "116909")]
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index e473fac0..c97dbfb 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -470,14 +470,16 @@ impl f32 {
/// Not a Number (NaN).
///
- /// Note that IEEE 754 doesn't define just a single NaN value;
- /// a plethora of bit patterns are considered to be NaN.
- /// Furthermore, the standard makes a difference
- /// between a "signaling" and a "quiet" NaN,
- /// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
- /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
- /// and the stability of its representation over Rust versions
- /// and target platforms isn't guaranteed.
+ /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are
+ /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and
+ /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern)
+ /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions
+ /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is
+ /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary.
+ /// The concrete bit pattern may change across Rust versions and target platforms.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
#[rustc_diagnostic_item = "f32_nan"]
#[allow(clippy::eq_op)]
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 6522a80..91affdb 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -469,14 +469,16 @@ impl f64 {
/// Not a Number (NaN).
///
- /// Note that IEEE 754 doesn't define just a single NaN value;
- /// a plethora of bit patterns are considered to be NaN.
- /// Furthermore, the standard makes a difference
- /// between a "signaling" and a "quiet" NaN,
- /// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
- /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
- /// and the stability of its representation over Rust versions
- /// and target platforms isn't guaranteed.
+ /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are
+ /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and
+ /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern)
+ /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions
+ /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is
+ /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary.
+ /// The concrete bit pattern may change across Rust versions and target platforms.
#[rustc_diagnostic_item = "f64_nan"]
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
#[allow(clippy::eq_op)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index de0d55e..05d8216 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -3571,10 +3571,7 @@ pub const fn signum(self) -> Self {
// so delegate it to `Ord` which is already producing -1/0/+1
// exactly like we need and can be the place to deal with the complexity.
- // FIXME(const-hack): replace with cmp
- if self < 0 { -1 }
- else if self == 0 { 0 }
- else { 1 }
+ crate::intrinsics::three_way_compare(self, 0) as Self
}
/// Returns `true` if `self` is positive and `false` if the number is zero or
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 1b2acdc..3678bb0 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -3343,7 +3343,7 @@ pub const fn is_multiple_of(self, rhs: Self) -> bool {
}
}
- /// Returns `true` if and only if `self == 2^k` for some `k`.
+ /// Returns `true` if and only if `self == 2^k` for some unsigned integer `k`.
///
/// # Examples
///
diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs
index b82184b..c645c99 100644
--- a/library/core/src/ops/index_range.rs
+++ b/library/core/src/ops/index_range.rs
@@ -1,5 +1,6 @@
use crate::iter::{FusedIterator, TrustedLen};
use crate::num::NonZero;
+use crate::ops::{NeverShortCircuit, Try};
use crate::ub_checks;
/// Like a `Range<usize>`, but with a safety invariant that `start <= end`.
@@ -112,6 +113,12 @@ pub(crate) fn take_suffix(&mut self, n: usize) -> Self {
self.end = mid;
suffix
}
+
+ #[inline]
+ fn assume_range(&self) {
+ // SAFETY: This is the type invariant
+ unsafe { crate::hint::assert_unchecked(self.start <= self.end) }
+ }
}
impl Iterator for IndexRange {
@@ -138,6 +145,30 @@ fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
let taken = self.take_prefix(n);
NonZero::new(n - taken.len()).map_or(Ok(()), Err)
}
+
+ #[inline]
+ fn fold<B, F: FnMut(B, usize) -> B>(mut self, init: B, f: F) -> B {
+ self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
+ }
+
+ #[inline]
+ fn try_fold<B, F, R>(&mut self, mut accum: B, mut f: F) -> R
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ // `Range` needs to check `start < end`, but thanks to our type invariant
+ // we can loop on the stricter `start != end`.
+
+ self.assume_range();
+ while self.start != self.end {
+ // SAFETY: We just checked that the range is non-empty
+ let i = unsafe { self.next_unchecked() };
+ accum = f(accum, i)?;
+ }
+ try { accum }
+ }
}
impl DoubleEndedIterator for IndexRange {
@@ -156,6 +187,30 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
let taken = self.take_suffix(n);
NonZero::new(n - taken.len()).map_or(Ok(()), Err)
}
+
+ #[inline]
+ fn rfold<B, F: FnMut(B, usize) -> B>(mut self, init: B, f: F) -> B {
+ self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
+ }
+
+ #[inline]
+ fn try_rfold<B, F, R>(&mut self, mut accum: B, mut f: F) -> R
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ // `Range` needs to check `start < end`, but thanks to our type invariant
+ // we can loop on the stricter `start != end`.
+
+ self.assume_range();
+ while self.start != self.end {
+ // SAFETY: We just checked that the range is non-empty
+ let i = unsafe { self.next_back_unchecked() };
+ accum = f(accum, i)?;
+ }
+ try { accum }
+ }
}
impl ExactSizeIterator for IndexRange {
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 2ef1bbf..9e6acf0 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -931,6 +931,11 @@
};
use crate::{cmp, fmt};
+mod unsafe_pinned;
+
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+pub use self::unsafe_pinned::UnsafePinned;
+
/// A pointer which pins its pointee in place.
///
/// [`Pin`] is a wrapper around some kind of pointer `Ptr` which makes that pointer "pin" its
@@ -1087,24 +1092,15 @@
#[rustc_pub_transparent]
#[derive(Copy, Clone)]
pub struct Pin<Ptr> {
- // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
- // - deter downstream users from accessing it (which would be unsound!),
- // - let the `pin!` macro access it (such a macro requires using struct
- // literal syntax in order to benefit from lifetime extension).
- //
- // However, if the `Deref` impl exposes a field with the same name as this
- // field, then the two will collide, resulting in a confusing error when the
- // user attempts to access the field through a `Pin<Ptr>`. Therefore, the
- // name `__pointer` is designed to be unlikely to collide with any other
- // field. Long-term, macro hygiene is expected to offer a more robust
- // alternative, alongside `unsafe` fields.
- #[unstable(feature = "unsafe_pin_internals", issue = "none")]
- #[doc(hidden)]
- pub __pointer: Ptr,
+ /// Only public for bootstrap.
+ #[cfg(bootstrap)]
+ pub pointer: Ptr,
+ #[cfg(not(bootstrap))]
+ pointer: Ptr,
}
// The following implementations aren't derived in order to avoid soundness
-// issues. `&self.__pointer` should not be accessible to untrusted trait
+// issues. `&self.pointer` should not be accessible to untrusted trait
// implementations.
//
// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73> for more details.
@@ -1218,7 +1214,7 @@ pub const fn new(pointer: Ptr) -> Pin<Ptr> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin_into_inner", since = "1.39.0")]
pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
- pin.__pointer
+ pin.pointer
}
}
@@ -1355,7 +1351,7 @@ impl<Ptr: Deref> Pin<Ptr> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin", since = "1.33.0")]
pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> {
- Pin { __pointer: pointer }
+ Pin { pointer }
}
/// Gets a shared reference to the pinned value this [`Pin`] points to.
@@ -1369,7 +1365,7 @@ impl<Ptr: Deref> Pin<Ptr> {
#[inline(always)]
pub fn as_ref(&self) -> Pin<&Ptr::Target> {
// SAFETY: see documentation on this function
- unsafe { Pin::new_unchecked(&*self.__pointer) }
+ unsafe { Pin::new_unchecked(&*self.pointer) }
}
}
@@ -1413,7 +1409,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
#[inline(always)]
pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
// SAFETY: see documentation on this function
- unsafe { Pin::new_unchecked(&mut *self.__pointer) }
+ unsafe { Pin::new_unchecked(&mut *self.pointer) }
}
/// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer.
@@ -1480,7 +1476,7 @@ pub fn set(&mut self, value: Ptr::Target)
where
Ptr::Target: Sized,
{
- *(self.__pointer) = value;
+ *(self.pointer) = value;
}
}
@@ -1508,7 +1504,7 @@ impl<Ptr: Deref> Pin<Ptr> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin_into_inner", since = "1.39.0")]
pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr {
- pin.__pointer
+ pin.pointer
}
}
@@ -1534,7 +1530,7 @@ pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U>
U: ?Sized,
F: FnOnce(&T) -> &U,
{
- let pointer = &*self.__pointer;
+ let pointer = &*self.pointer;
let new_pointer = func(pointer);
// SAFETY: the safety contract for `new_unchecked` must be
@@ -1564,7 +1560,7 @@ pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U>
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin", since = "1.33.0")]
pub const fn get_ref(self) -> &'a T {
- self.__pointer
+ self.pointer
}
}
@@ -1575,7 +1571,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
#[stable(feature = "pin", since = "1.33.0")]
pub const fn into_ref(self) -> Pin<&'a T> {
- Pin { __pointer: self.__pointer }
+ Pin { pointer: self.pointer }
}
/// Gets a mutable reference to the data inside of this `Pin`.
@@ -1595,7 +1591,7 @@ pub const fn get_mut(self) -> &'a mut T
where
T: Unpin,
{
- self.__pointer
+ self.pointer
}
/// Gets a mutable reference to the data inside of this `Pin`.
@@ -1613,7 +1609,7 @@ pub const fn get_mut(self) -> &'a mut T
#[stable(feature = "pin", since = "1.33.0")]
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
- self.__pointer
+ self.pointer
}
/// Constructs a new pin by mapping the interior value.
@@ -1700,21 +1696,21 @@ impl<Ptr: LegacyReceiver> LegacyReceiver for Pin<Ptr> {}
#[stable(feature = "pin", since = "1.33.0")]
impl<Ptr: fmt::Debug> fmt::Debug for Pin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Debug::fmt(&self.__pointer, f)
+ fmt::Debug::fmt(&self.pointer, f)
}
}
#[stable(feature = "pin", since = "1.33.0")]
impl<Ptr: fmt::Display> fmt::Display for Pin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(&self.__pointer, f)
+ fmt::Display::fmt(&self.pointer, f)
}
}
#[stable(feature = "pin", since = "1.33.0")]
impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Pointer::fmt(&self.__pointer, f)
+ fmt::Pointer::fmt(&self.pointer, f)
}
}
@@ -1940,80 +1936,22 @@ unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
/// constructor.
///
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
+#[cfg(not(bootstrap))]
#[stable(feature = "pin_macro", since = "1.68.0")]
#[rustc_macro_transparency = "semitransparent"]
-#[allow_internal_unstable(unsafe_pin_internals)]
-#[rustc_macro_edition_2021]
+#[allow_internal_unstable(super_let)]
pub macro pin($value:expr $(,)?) {
- // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's
- // review such a hypothetical macro (that any user-code could define):
- //
- // ```rust
- // macro_rules! pin {( $value:expr ) => (
- // match &mut { $value } { at_value => unsafe { // Do not wrap `$value` in an `unsafe` block.
- // $crate::pin::Pin::<&mut _>::new_unchecked(at_value)
- // }}
- // )}
- // ```
- //
- // Safety:
- // - `type P = &mut _`. There are thus no pathological `Deref{,Mut}` impls
- // that would break `Pin`'s invariants.
- // - `{ $value }` is braced, making it a _block expression_, thus **moving**
- // the given `$value`, and making it _become an **anonymous** temporary_.
- // By virtue of being anonymous, it can no longer be accessed, thus
- // preventing any attempts to `mem::replace` it or `mem::forget` it, _etc._
- //
- // This gives us a `pin!` definition that is sound, and which works, but only
- // in certain scenarios:
- // - If the `pin!(value)` expression is _directly_ fed to a function call:
- // `let poll = pin!(fut).poll(cx);`
- // - If the `pin!(value)` expression is part of a scrutinee:
- // ```rust
- // match pin!(fut) { pinned_fut => {
- // pinned_fut.as_mut().poll(...);
- // pinned_fut.as_mut().poll(...);
- // }} // <- `fut` is dropped here.
- // ```
- // Alas, it doesn't work for the more straight-forward use-case: `let` bindings.
- // ```rust
- // let pinned_fut = pin!(fut); // <- temporary value is freed at the end of this statement
- // pinned_fut.poll(...) // error[E0716]: temporary value dropped while borrowed
- // // note: consider using a `let` binding to create a longer lived value
- // ```
- // - Issues such as this one are the ones motivating https://github.com/rust-lang/rfcs/pull/66
- //
- // This makes such a macro incredibly unergonomic in practice, and the reason most macros
- // out there had to take the path of being a statement/binding macro (_e.g._, `pin!(future);`)
- // instead of featuring the more intuitive ergonomics of an expression macro.
- //
- // Luckily, there is a way to avoid the problem. Indeed, the problem stems from the fact that a
- // temporary is dropped at the end of its enclosing statement when it is part of the parameters
- // given to function call, which has precisely been the case with our `Pin::new_unchecked()`!
- // For instance,
- // ```rust
- // let p = Pin::new_unchecked(&mut <temporary>);
- // ```
- // becomes:
- // ```rust
- // let p = { let mut anon = <temporary>; &mut anon };
- // ```
- //
- // However, when using a literal braced struct to construct the value, references to temporaries
- // can then be taken. This makes Rust change the lifespan of such temporaries so that they are,
- // instead, dropped _at the end of the enscoping block_.
- // For instance,
- // ```rust
- // let p = Pin { __pointer: &mut <temporary> };
- // ```
- // becomes:
- // ```rust
- // let mut anon = <temporary>;
- // let p = Pin { __pointer: &mut anon };
- // ```
- // which is *exactly* what we want.
- //
- // See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension
- // for more info.
- $crate::pin::Pin::<&mut _> { __pointer: &mut { $value } }
+ {
+ super let mut pinned = $value;
+ // SAFETY: The value is pinned: it is the local above which cannot be named outside this macro.
+ unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) }
+ }
+}
+
+/// Only for bootstrap.
+#[cfg(bootstrap)]
+#[stable(feature = "pin_macro", since = "1.68.0")]
+#[rustc_macro_transparency = "semitransparent"]
+pub macro pin($value:expr $(,)?) {
+ $crate::pin::Pin::<&mut _> { pointer: &mut { $value } }
}
diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs
new file mode 100644
index 0000000..5fb628c
--- /dev/null
+++ b/library/core/src/pin/unsafe_pinned.rs
@@ -0,0 +1,197 @@
+use crate::marker::{PointerLike, Unpin};
+use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::pin::Pin;
+use crate::{fmt, ptr};
+
+/// This type provides a way to opt-out of typical aliasing rules;
+/// specifically, `&mut UnsafePinned<T>` is not guaranteed to be a unique pointer.
+///
+/// However, even if you define your type like `pub struct Wrapper(UnsafePinned<...>)`, it is still
+/// very risky to have an `&mut Wrapper` that aliases anything else. Many functions that work
+/// generically on `&mut T` assume that the memory that stores `T` is uniquely owned (such as
+/// `mem::swap`). In other words, while having aliasing with `&mut Wrapper` is not immediate
+/// Undefined Behavior, it is still unsound to expose such a mutable reference to code you do not
+/// control! Techniques such as pinning via [`Pin`] are needed to ensure soundness.
+///
+/// Similar to [`UnsafeCell`](crate::cell::UnsafeCell), `UnsafePinned` will not usually show up in
+/// the public API of a library. It is an internal implementation detail of libraries that need to
+/// support aliasing mutable references.
+///
+/// Further note that this does *not* lift the requirement that shared references must be read-only!
+/// Use `UnsafeCell` for that.
+///
+/// This type blocks niches the same way `UnsafeCell` does.
+#[cfg_attr(not(bootstrap), lang = "unsafe_pinned")]
+#[repr(transparent)]
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+pub struct UnsafePinned<T: ?Sized> {
+ value: T,
+}
+
+/// When this type is used, that almost certainly means safe APIs need to use pinning to avoid the
+/// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt
+/// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned.
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: ?Sized> !Unpin for UnsafePinned<T> {}
+
+/// The type is `Copy` when `T` is to avoid people assuming that `Copy` implies there is no
+/// `UnsafePinned` anywhere. (This is an issue with `UnsafeCell`: people use `Copy` bounds to mean
+/// `Freeze`.) Given that there is no `unsafe impl Copy for ...`, this is also the option that
+/// leaves the user more choices (as they can always wrap this in a `!Copy` type).
+// FIXME(unsafe_pinned): this may be unsound or a footgun?
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: Copy> Copy for UnsafePinned<T> {}
+
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: Copy> Clone for UnsafePinned<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+// `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since
+// we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes
+// unergonomic. A type that needs to be `!Send`/`!Sync` should really have an explicit
+// opt-out itself, e.g. via an `PhantomData<*mut T>` or (one day) via `impl !Send`/`impl !Sync`.
+
+impl<T> UnsafePinned<T> {
+ /// Constructs a new instance of `UnsafePinned` which will wrap the specified value.
+ ///
+ /// All access to the inner value through `&UnsafePinned<T>` or `&mut UnsafePinned<T>` or
+ /// `Pin<&mut UnsafePinned<T>>` requires `unsafe` code.
+ #[inline(always)]
+ #[must_use]
+ #[unstable(feature = "unsafe_pinned", issue = "125735")]
+ pub const fn new(value: T) -> Self {
+ UnsafePinned { value }
+ }
+
+ /// Unwraps the value, consuming this `UnsafePinned`.
+ #[inline(always)]
+ #[must_use]
+ #[unstable(feature = "unsafe_pinned", issue = "125735")]
+ #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
+ pub const fn into_inner(self) -> T {
+ self.value
+ }
+}
+
+impl<T: ?Sized> UnsafePinned<T> {
+ /// Get read-write access to the contents of a pinned `UnsafePinned`.
+ #[inline(always)]
+ #[must_use]
+ #[unstable(feature = "unsafe_pinned", issue = "125735")]
+ pub const fn get_mut_pinned(self: Pin<&mut Self>) -> *mut T {
+ // SAFETY: we're not using `get_unchecked_mut` to unpin anything
+ unsafe { self.get_unchecked_mut() }.get_mut_unchecked()
+ }
+
+ /// Get read-write access to the contents of an `UnsafePinned`.
+ ///
+ /// You should usually be using `get_mut_pinned` instead to explicitly track the fact that this
+ /// memory is "pinned" due to there being aliases.
+ #[inline(always)]
+ #[must_use]
+ #[unstable(feature = "unsafe_pinned", issue = "125735")]
+ pub const fn get_mut_unchecked(&mut self) -> *mut T {
+ ptr::from_mut(self) as *mut T
+ }
+
+ /// Get read-only access to the contents of a shared `UnsafePinned`.
+ ///
+ /// Note that `&UnsafePinned<T>` is read-only if `&T` is read-only. This means that if there is
+ /// mutation of the `T`, future reads from the `*const T` returned here are UB! Use
+ /// [`UnsafeCell`] if you also need interior mutability.
+ ///
+ /// [`UnsafeCell`]: crate::cell::UnsafeCell
+ ///
+ /// ```rust,no_run
+ /// #![feature(unsafe_pinned)]
+ /// use std::pin::UnsafePinned;
+ ///
+ /// unsafe {
+ /// let mut x = UnsafePinned::new(0);
+ /// let ptr = x.get(); // read-only pointer, assumes immutability
+ /// x.get_mut_unchecked().write(1);
+ /// ptr.read(); // UB!
+ /// }
+ /// ```
+ #[inline(always)]
+ #[must_use]
+ #[unstable(feature = "unsafe_pinned", issue = "125735")]
+ pub const fn get(&self) -> *const T {
+ ptr::from_ref(self) as *const T
+ }
+
+ /// Gets an immutable pointer to the wrapped value.
+ ///
+ /// The difference from [`get`] is that this function accepts a raw pointer, which is useful to
+ /// avoid the creation of temporary references.
+ ///
+ /// [`get`]: UnsafePinned::get
+ #[inline(always)]
+ #[must_use]
+ #[unstable(feature = "unsafe_pinned", issue = "125735")]
+ pub const fn raw_get(this: *const Self) -> *const T {
+ this as *const T
+ }
+
+ /// Gets a mutable pointer to the wrapped value.
+ ///
+ /// The difference from [`get_mut_pinned`] and [`get_mut_unchecked`] is that this function
+ /// accepts a raw pointer, which is useful to avoid the creation of temporary references.
+ ///
+ /// [`get_mut_pinned`]: UnsafePinned::get_mut_pinned
+ /// [`get_mut_unchecked`]: UnsafePinned::get_mut_unchecked
+ #[inline(always)]
+ #[must_use]
+ #[unstable(feature = "unsafe_pinned", issue = "125735")]
+ pub const fn raw_get_mut(this: *mut Self) -> *mut T {
+ this as *mut T
+ }
+}
+
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: Default> Default for UnsafePinned<T> {
+ /// Creates an `UnsafePinned`, with the `Default` value for T.
+ fn default() -> Self {
+ UnsafePinned::new(T::default())
+ }
+}
+
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T> From<T> for UnsafePinned<T> {
+ /// Creates a new `UnsafePinned<T>` containing the given value.
+ fn from(value: T) -> Self {
+ UnsafePinned::new(value)
+ }
+}
+
+#[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: ?Sized> fmt::Debug for UnsafePinned<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("UnsafePinned").finish_non_exhaustive()
+ }
+}
+
+#[unstable(feature = "coerce_unsized", issue = "18598")]
+// #[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafePinned<U>> for UnsafePinned<T> {}
+
+// Allow types that wrap `UnsafePinned` to also implement `DispatchFromDyn`
+// and become dyn-compatible method receivers.
+// Note that currently `UnsafePinned` itself cannot be a method receiver
+// because it does not implement Deref.
+// In other words:
+// `self: UnsafePinned<&Self>` won't work
+// `self: UnsafePinned<Self>` becomes possible
+// FIXME(unsafe_pinned) this logic is copied from UnsafeCell, is it still sound?
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+// #[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafePinned<U>> for UnsafePinned<T> {}
+
+#[unstable(feature = "pointer_like_trait", issue = "none")]
+// #[unstable(feature = "unsafe_pinned", issue = "125735")]
+impl<T: PointerLike> PointerLike for UnsafePinned<T> {}
+
+// FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned<T>?
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 2357ba2..445c789 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -278,7 +278,7 @@
//! ### Using Strict Provenance
//!
//! Most code needs no changes to conform to strict provenance, as the only really concerning
-//! operation is casts from usize to a pointer. For code which *does* cast a `usize` to a pointer,
+//! operation is casts from `usize` to a pointer. For code which *does* cast a `usize` to a pointer,
//! the scope of the change depends on exactly what you're doing.
//!
//! In general, you just need to make sure that if you want to convert a `usize` address to a
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index da85f42..5ce72b4 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -5,6 +5,7 @@
use crate::cmp::{self, BytewiseEq, Ordering};
use crate::intrinsics::compare_bytes;
use crate::num::NonZero;
+use crate::ops::ControlFlow;
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> PartialEq<[U]> for [T]
@@ -31,12 +32,64 @@ fn cmp(&self, other: &[T]) -> Ordering {
}
}
+#[inline]
+fn as_underlying(x: ControlFlow<bool>) -> u8 {
+ // SAFETY: This will only compile if `bool` and `ControlFlow<bool>` have the same
+ // size (which isn't guaranteed but this is libcore). Because they have the same
+ // size, it's a niched implementation, which in one byte means there can't be
+ // any uninitialized memory. The callers then only check for `0` or `1` from this,
+ // which must necessarily match the `Break` variant, and we're fine no matter
+ // what ends up getting picked as the value representing `Continue(())`.
+ unsafe { crate::mem::transmute(x) }
+}
+
/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd> PartialOrd for [T] {
+ #[inline]
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
SlicePartialOrd::partial_compare(self, other)
}
+ #[inline]
+ fn lt(&self, other: &Self) -> bool {
+ // This is certainly not the obvious way to implement these methods.
+ // Unfortunately, using anything that looks at the discriminant means that
+ // LLVM sees a check for `2` (aka `ControlFlow<bool>::Continue(())`) and
+ // gets very distracted by that, ending up generating extraneous code.
+ // This should be changed to something simpler once either LLVM is smarter,
+ // see <https://github.com/llvm/llvm-project/issues/132678>, or we generate
+ // niche discriminant checks in a way that doesn't trigger it.
+
+ as_underlying(self.__chaining_lt(other)) == 1
+ }
+ #[inline]
+ fn le(&self, other: &Self) -> bool {
+ as_underlying(self.__chaining_le(other)) != 0
+ }
+ #[inline]
+ fn gt(&self, other: &Self) -> bool {
+ as_underlying(self.__chaining_gt(other)) == 1
+ }
+ #[inline]
+ fn ge(&self, other: &Self) -> bool {
+ as_underlying(self.__chaining_ge(other)) != 0
+ }
+ #[inline]
+ fn __chaining_lt(&self, other: &Self) -> ControlFlow<bool> {
+ SliceChain::chaining_lt(self, other)
+ }
+ #[inline]
+ fn __chaining_le(&self, other: &Self) -> ControlFlow<bool> {
+ SliceChain::chaining_le(self, other)
+ }
+ #[inline]
+ fn __chaining_gt(&self, other: &Self) -> ControlFlow<bool> {
+ SliceChain::chaining_gt(self, other)
+ }
+ #[inline]
+ fn __chaining_ge(&self, other: &Self) -> ControlFlow<bool> {
+ SliceChain::chaining_ge(self, other)
+ }
}
#[doc(hidden)]
@@ -99,26 +152,65 @@ trait SlicePartialOrd: Sized {
fn partial_compare(left: &[Self], right: &[Self]) -> Option<Ordering>;
}
+#[doc(hidden)]
+// intermediate trait for specialization of slice's PartialOrd chaining methods
+trait SliceChain: Sized {
+ fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
+ fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
+ fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
+ fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
+}
+
+type AlwaysBreak<B> = ControlFlow<B, crate::convert::Infallible>;
+
impl<A: PartialOrd> SlicePartialOrd for A {
default fn partial_compare(left: &[A], right: &[A]) -> Option<Ordering> {
- let l = cmp::min(left.len(), right.len());
-
- // Slice to the loop iteration range to enable bound check
- // elimination in the compiler
- let lhs = &left[..l];
- let rhs = &right[..l];
-
- for i in 0..l {
- match lhs[i].partial_cmp(&rhs[i]) {
- Some(Ordering::Equal) => (),
- non_eq => return non_eq,
- }
- }
-
- left.len().partial_cmp(&right.len())
+ let elem_chain = |a, b| match PartialOrd::partial_cmp(a, b) {
+ Some(Ordering::Equal) => ControlFlow::Continue(()),
+ non_eq => ControlFlow::Break(non_eq),
+ };
+ let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b));
+ let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
+ b
}
}
+impl<A: PartialOrd> SliceChain for A {
+ default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt)
+ }
+ default fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ chaining_impl(left, right, PartialOrd::__chaining_le, usize::__chaining_le)
+ }
+ default fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ chaining_impl(left, right, PartialOrd::__chaining_gt, usize::__chaining_gt)
+ }
+ default fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ chaining_impl(left, right, PartialOrd::__chaining_ge, usize::__chaining_ge)
+ }
+}
+
+#[inline]
+fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
+ left: &'l [A],
+ right: &'r [A],
+ elem_chain: impl Fn(&'l A, &'r A) -> ControlFlow<B>,
+ len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow<B, C>,
+) -> ControlFlow<B, C> {
+ let l = cmp::min(left.len(), right.len());
+
+ // Slice to the loop iteration range to enable bound check
+ // elimination in the compiler
+ let lhs = &left[..l];
+ let rhs = &right[..l];
+
+ for i in 0..l {
+ elem_chain(&lhs[i], &rhs[i])?;
+ }
+
+ len_chain(&left.len(), &right.len())
+}
+
// This is the impl that we would like to have. Unfortunately it's not sound.
// See `partial_ord_slice.rs`.
/*
@@ -165,21 +257,13 @@ trait SliceOrd: Sized {
impl<A: Ord> SliceOrd for A {
default fn compare(left: &[Self], right: &[Self]) -> Ordering {
- let l = cmp::min(left.len(), right.len());
-
- // Slice to the loop iteration range to enable bound check
- // elimination in the compiler
- let lhs = &left[..l];
- let rhs = &right[..l];
-
- for i in 0..l {
- match lhs[i].cmp(&rhs[i]) {
- Ordering::Equal => (),
- non_eq => return non_eq,
- }
- }
-
- left.len().cmp(&right.len())
+ let elem_chain = |a, b| match Ord::cmp(a, b) {
+ Ordering::Equal => ControlFlow::Continue(()),
+ non_eq => ControlFlow::Break(non_eq),
+ };
+ let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b));
+ let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain);
+ b
}
}
@@ -191,7 +275,7 @@ impl<A: Ord> SliceOrd for A {
/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same
/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`.
#[rustc_specialization_trait]
-unsafe trait UnsignedBytewiseOrd {}
+unsafe trait UnsignedBytewiseOrd: Ord {}
unsafe impl UnsignedBytewiseOrd for bool {}
unsafe impl UnsignedBytewiseOrd for u8 {}
@@ -225,6 +309,38 @@ fn compare(left: &[Self], right: &[Self]) -> Ordering {
}
}
+// Don't generate our own chaining loops for `memcmp`-able things either.
+impl<A: PartialOrd + UnsignedBytewiseOrd> SliceChain for A {
+ #[inline]
+ fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ match SliceOrd::compare(left, right) {
+ Ordering::Equal => ControlFlow::Continue(()),
+ ne => ControlFlow::Break(ne.is_lt()),
+ }
+ }
+ #[inline]
+ fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ match SliceOrd::compare(left, right) {
+ Ordering::Equal => ControlFlow::Continue(()),
+ ne => ControlFlow::Break(ne.is_le()),
+ }
+ }
+ #[inline]
+ fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ match SliceOrd::compare(left, right) {
+ Ordering::Equal => ControlFlow::Continue(()),
+ ne => ControlFlow::Break(ne.is_gt()),
+ }
+ }
+ #[inline]
+ fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow<bool> {
+ match SliceOrd::compare(left, right) {
+ Ordering::Equal => ControlFlow::Continue(()),
+ ne => ControlFlow::Break(ne.is_ge()),
+ }
+ }
+}
+
pub(super) trait SliceContains: Sized {
fn slice_contains(&self, x: &[Self]) -> bool;
}
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index b906899..7b2a3fa 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1287,7 +1287,6 @@ pub const fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
- #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
#[must_use]
pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
@@ -1333,7 +1332,6 @@ pub const fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_
/// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
- #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
#[track_caller]
#[must_use]
@@ -1368,7 +1366,6 @@ pub const fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_
/// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
- #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
#[track_caller]
#[must_use]
@@ -1448,7 +1445,6 @@ pub const fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
- #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
#[must_use]
pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
@@ -1489,7 +1485,6 @@ pub const fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
/// assert_eq!(v, &[1, 1, 2, 2, 9]);
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
- #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
#[track_caller]
#[must_use]
@@ -1530,7 +1525,6 @@ pub const fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
/// assert_eq!(v, &[9, 1, 1, 2, 2]);
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
- #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
#[track_caller]
#[must_use]
@@ -2828,7 +2822,7 @@ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
// Binary search interacts poorly with branch prediction, so force
// the compiler to use conditional moves if supported by the target
// architecture.
- base = (cmp == Greater).select_unpredictable(base, mid);
+ base = hint::select_unpredictable(cmp == Greater, base, mid);
// This is imprecise in the case where `size` is odd and the
// comparison returns Greater: the mid element still gets included
diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs
index 95f196a..4280f75 100644
--- a/library/core/src/slice/sort/shared/smallsort.rs
+++ b/library/core/src/slice/sort/shared/smallsort.rs
@@ -2,7 +2,7 @@
use crate::mem::{self, ManuallyDrop, MaybeUninit};
use crate::slice::sort::shared::FreezeMarker;
-use crate::{intrinsics, ptr, slice};
+use crate::{hint, intrinsics, ptr, slice};
// It's important to differentiate between SMALL_SORT_THRESHOLD performance for
// small slices and small-sort performance sorting small sub-slices as part of
@@ -408,8 +408,8 @@ unsafe fn swap_if_less<T, F>(v_base: *mut T, a_pos: usize, b_pos: usize, is_less
// }
// The goal is to generate cmov instructions here.
- let v_a_swap = should_swap.select_unpredictable(v_b, v_a);
- let v_b_swap = should_swap.select_unpredictable(v_a, v_b);
+ let v_a_swap = hint::select_unpredictable(should_swap, v_b, v_a);
+ let v_b_swap = hint::select_unpredictable(should_swap, v_a, v_b);
let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap));
ptr::copy(v_a_swap, v_a, 1);
@@ -640,15 +640,15 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
// 1, 1 | c b a d
let c3 = is_less(&*c, &*a);
let c4 = is_less(&*d, &*b);
- let min = c3.select_unpredictable(c, a);
- let max = c4.select_unpredictable(b, d);
- let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b));
- let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c));
+ let min = hint::select_unpredictable(c3, c, a);
+ let max = hint::select_unpredictable(c4, b, d);
+ let unknown_left = hint::select_unpredictable(c3, a, hint::select_unpredictable(c4, c, b));
+ let unknown_right = hint::select_unpredictable(c4, d, hint::select_unpredictable(c3, b, c));
// Sort the last two unknown elements.
let c5 = is_less(&*unknown_right, &*unknown_left);
- let lo = c5.select_unpredictable(unknown_right, unknown_left);
- let hi = c5.select_unpredictable(unknown_left, unknown_right);
+ let lo = hint::select_unpredictable(c5, unknown_right, unknown_left);
+ let hi = hint::select_unpredictable(c5, unknown_left, unknown_right);
ptr::copy_nonoverlapping(min, dst, 1);
ptr::copy_nonoverlapping(lo, dst.add(1), 1);
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index d754bb9..02eb805 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -2,7 +2,7 @@
use crate::cmp::Ordering::{self, *};
use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
-use crate::ops::ControlFlow::{Break, Continue};
+use crate::ops::ControlFlow::{self, Break, Continue};
// Recursive macro for implementing n-ary tuple functions and operations
//
@@ -95,6 +95,22 @@ fn ge(&self, other: &($($T,)+)) -> bool {
fn gt(&self, other: &($($T,)+)) -> bool {
lexical_ord!(gt, __chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
}
+ #[inline]
+ fn __chaining_lt(&self, other: &($($T,)+)) -> ControlFlow<bool> {
+ lexical_chain!(__chaining_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+ }
+ #[inline]
+ fn __chaining_le(&self, other: &($($T,)+)) -> ControlFlow<bool> {
+ lexical_chain!(__chaining_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+ }
+ #[inline]
+ fn __chaining_gt(&self, other: &($($T,)+)) -> ControlFlow<bool> {
+ lexical_chain!(__chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+ }
+ #[inline]
+ fn __chaining_ge(&self, other: &($($T,)+)) -> ControlFlow<bool> {
+ lexical_chain!(__chaining_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
+ }
}
}
@@ -187,6 +203,17 @@ macro_rules! lexical_ord {
};
}
+// Same parameter interleaving as `lexical_ord` above
+macro_rules! lexical_chain {
+ ($chain_rel: ident, $a:expr, $b:expr $(,$rest_a:expr, $rest_b:expr)*) => {{
+ PartialOrd::$chain_rel(&$a, &$b)?;
+ lexical_chain!($chain_rel $(,$rest_a, $rest_b)*)
+ }};
+ ($chain_rel: ident) => {
+ Continue(())
+ };
+}
+
macro_rules! lexical_partial_cmp {
($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
match ($a).partial_cmp(&$b) {
diff --git a/library/coretests/tests/hint.rs b/library/coretests/tests/hint.rs
new file mode 100644
index 0000000..032bbc1
--- /dev/null
+++ b/library/coretests/tests/hint.rs
@@ -0,0 +1,23 @@
+#[test]
+fn select_unpredictable_drop() {
+ use core::cell::Cell;
+ struct X<'a>(&'a Cell<bool>);
+ impl Drop for X<'_> {
+ fn drop(&mut self) {
+ self.0.set(true);
+ }
+ }
+
+ let a_dropped = Cell::new(false);
+ let b_dropped = Cell::new(false);
+ let a = X(&a_dropped);
+ let b = X(&b_dropped);
+ assert!(!a_dropped.get());
+ assert!(!b_dropped.get());
+ let selected = core::hint::select_unpredictable(core::hint::black_box(true), a, b);
+ assert!(!a_dropped.get());
+ assert!(b_dropped.get());
+ drop(selected);
+ assert!(a_dropped.get());
+ assert!(b_dropped.get());
+}
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 7ad1547..1c43bfe 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -68,6 +68,7 @@
#![feature(pointer_is_aligned_to)]
#![feature(portable_simd)]
#![feature(ptr_metadata)]
+#![feature(select_unpredictable)]
#![feature(slice_from_ptr_range)]
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
@@ -147,6 +148,7 @@ fn $test() $block
mod fmt;
mod future;
mod hash;
+mod hint;
mod intrinsics;
mod io;
mod iter;
diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs
index bfbfa8d..3174c91 100644
--- a/library/coretests/tests/pin_macro.rs
+++ b/library/coretests/tests/pin_macro.rs
@@ -38,6 +38,7 @@ fn rust_2024_expr() {
}
#[test]
+#[cfg(not(bootstrap))]
fn temp_lifetime() {
// Check that temporary lifetimes work as in Rust 2021.
// Regression test for https://github.com/rust-lang/rust/issues/138596
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index f6d4825..e7d5479 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -111,12 +111,6 @@ fn clone(&self) -> Self {
}
}
-impl Clone for SourceFile {
- fn clone(&self) -> Self {
- self.clone()
- }
-}
-
impl Span {
pub(crate) fn def_site() -> Span {
Bridge::with(|bridge| bridge.globals.def_site)
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 1b5c221..75d82d7 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -81,16 +81,8 @@ fn into_trees(
$self: $S::TokenStream
) -> Vec<TokenTree<$S::TokenStream, $S::Span, $S::Symbol>>;
},
- SourceFile {
- fn drop($self: $S::SourceFile);
- fn clone($self: &$S::SourceFile) -> $S::SourceFile;
- fn eq($self: &$S::SourceFile, other: &$S::SourceFile) -> bool;
- fn path($self: &$S::SourceFile) -> String;
- fn is_real($self: &$S::SourceFile) -> bool;
- },
Span {
fn debug($self: $S::Span) -> String;
- fn source_file($self: $S::Span) -> $S::SourceFile;
fn parent($self: $S::Span) -> Option<$S::Span>;
fn source($self: $S::Span) -> $S::Span;
fn byte_range($self: $S::Span) -> Range<usize>;
@@ -98,6 +90,8 @@ fn into_trees(
fn end($self: $S::Span) -> $S::Span;
fn line($self: $S::Span) -> usize;
fn column($self: $S::Span) -> usize;
+ fn file($self: $S::Span) -> String;
+ fn local_file($self: $S::Span) -> Option<String>;
fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>;
fn subspan($self: $S::Span, start: Bound<usize>, end: Bound<usize>) -> Option<$S::Span>;
fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span;
@@ -120,7 +114,6 @@ macro_rules! with_api_handle_types {
'owned:
FreeFunctions,
TokenStream,
- SourceFile,
'interned:
Span,
diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs
index 97e5a60..5beda7c 100644
--- a/library/proc_macro/src/bridge/server.rs
+++ b/library/proc_macro/src/bridge/server.rs
@@ -82,7 +82,6 @@ fn decode(r: &mut Reader<'_>, s: &mut HandleStore<MarkedTypes<S>>) -> Self {
pub trait Types {
type FreeFunctions: 'static;
type TokenStream: 'static + Clone;
- type SourceFile: 'static + Clone;
type Span: 'static + Copy + Eq + Hash;
type Symbol: 'static;
}
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index f1cf0c5..c46dceb 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -491,12 +491,6 @@ pub fn mixed_site() -> Span {
Span(bridge::client::Span::mixed_site())
}
- /// The original source file into which this span points.
- #[unstable(feature = "proc_macro_span", issue = "54725")]
- pub fn source_file(&self) -> SourceFile {
- SourceFile(self.0.source_file())
- }
-
/// The `Span` for the tokens in the previous macro expansion from which
/// `self` was generated from, if any.
#[unstable(feature = "proc_macro_span", issue = "54725")]
@@ -546,6 +540,25 @@ pub fn column(&self) -> usize {
self.0.column()
}
+ /// The path to the source file in which this span occurs, for display purposes.
+ ///
+ /// This might not correspond to a valid file system path.
+ /// It might be remapped, or might be an artificial path such as `"<macro expansion>"`.
+ #[unstable(feature = "proc_macro_span", issue = "54725")]
+ pub fn file(&self) -> String {
+ self.0.file()
+ }
+
+ /// The path to the source file in which this span occurs on disk.
+ ///
+ /// This is the actual path on disk. It is unaffected by path remapping.
+ ///
+ /// This path should not be embedded in the output of the macro; prefer `file()` instead.
+ #[unstable(feature = "proc_macro_span", issue = "54725")]
+ pub fn local_file(&self) -> Option<PathBuf> {
+ self.0.local_file().map(|s| PathBuf::from(s))
+ }
+
/// Creates a new span encompassing `self` and `other`.
///
/// Returns `None` if `self` and `other` are from different files.
@@ -614,58 +627,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-/// The source file of a given `Span`.
-#[unstable(feature = "proc_macro_span", issue = "54725")]
-#[derive(Clone)]
-pub struct SourceFile(bridge::client::SourceFile);
-
-impl SourceFile {
- /// Gets the path to this source file.
- ///
- /// ### Note
- /// If the code span associated with this `SourceFile` was generated by an external macro, this
- /// macro, this might not be an actual path on the filesystem. Use [`is_real`] to check.
- ///
- /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on
- /// the command line, the path as given might not actually be valid.
- ///
- /// [`is_real`]: Self::is_real
- #[unstable(feature = "proc_macro_span", issue = "54725")]
- pub fn path(&self) -> PathBuf {
- PathBuf::from(self.0.path())
- }
-
- /// Returns `true` if this source file is a real source file, and not generated by an external
- /// macro's expansion.
- #[unstable(feature = "proc_macro_span", issue = "54725")]
- pub fn is_real(&self) -> bool {
- // This is a hack until intercrate spans are implemented and we can have real source files
- // for spans generated in external macros.
- // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368
- self.0.is_real()
- }
-}
-
-#[unstable(feature = "proc_macro_span", issue = "54725")]
-impl fmt::Debug for SourceFile {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("SourceFile")
- .field("path", &self.path())
- .field("is_real", &self.is_real())
- .finish()
- }
-}
-
-#[unstable(feature = "proc_macro_span", issue = "54725")]
-impl PartialEq for SourceFile {
- fn eq(&self, other: &Self) -> bool {
- self.0.eq(&other.0)
- }
-}
-
-#[unstable(feature = "proc_macro_span", issue = "54725")]
-impl Eq for SourceFile {}
-
/// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`).
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
#[derive(Clone)]
diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs
index dd85239..fc1a9ec 100644
--- a/library/profiler_builtins/build.rs
+++ b/library/profiler_builtins/build.rs
@@ -9,8 +9,14 @@
fn main() {
if let Ok(rt) = tracked_env_var("LLVM_PROFILER_RT_LIB") {
- println!("cargo::rustc-link-lib=static:+verbatim={rt}");
- return;
+ let rt = PathBuf::from(rt);
+ if let Some(lib) = rt.file_name() {
+ if let Some(dir) = rt.parent() {
+ println!("cargo::rustc-link-search=native={}", dir.display());
+ }
+ println!("cargo::rustc-link-lib=static:+verbatim={}", lib.to_str().unwrap());
+ return;
+ }
}
let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set");
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 6b70ff7..917a470 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,7 @@
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.153" }
+compiler_builtins = { version = "=0.1.155" }
unwind = { path = "../unwind" }
hashbrown = { version = "0.15", default-features = false, features = [
'rustc-dep-of-std',
diff --git a/library/std/build.rs b/library/std/build.rs
index d76d07a..40a56d4 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -12,11 +12,6 @@ fn main() {
.expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set")
.parse()
.unwrap();
- let target_features: Vec<_> = env::var("CARGO_CFG_TARGET_FEATURE")
- .unwrap_or_default()
- .split(",")
- .map(ToOwned::to_owned)
- .collect();
let is_miri = env::var_os("CARGO_CFG_MIRI").is_some();
println!("cargo:rustc-check-cfg=cfg(netbsd10)");
@@ -108,8 +103,6 @@ fn main() {
("s390x", _) => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
- // LLVM crash <https://github.com/llvm/llvm-project/issues/129394>
- ("aarch64", _) if !target_features.iter().any(|f| f == "neon") => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index ede2196..217528f 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -666,7 +666,7 @@ pub fn log10(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn cbrt(self) -> f128 {
- unsafe { cmath::cbrtf128(self) }
+ cmath::cbrtf128(self)
}
/// Compute the distance between the origin and a point (`x`, `y`) on the
@@ -703,7 +703,7 @@ pub fn cbrt(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn hypot(self, other: f128) -> f128 {
- unsafe { cmath::hypotf128(self, other) }
+ cmath::hypotf128(self, other)
}
/// Computes the sine of a number (in radians).
@@ -789,7 +789,7 @@ pub fn cos(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn tan(self) -> f128 {
- unsafe { cmath::tanf128(self) }
+ cmath::tanf128(self)
}
/// Computes the arcsine of a number. Return value is in radians in
@@ -824,7 +824,7 @@ pub fn tan(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn asin(self) -> f128 {
- unsafe { cmath::asinf128(self) }
+ cmath::asinf128(self)
}
/// Computes the arccosine of a number. Return value is in radians in
@@ -859,7 +859,7 @@ pub fn asin(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn acos(self) -> f128 {
- unsafe { cmath::acosf128(self) }
+ cmath::acosf128(self)
}
/// Computes the arctangent of a number. Return value is in radians in the
@@ -893,7 +893,7 @@ pub fn acos(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn atan(self) -> f128 {
- unsafe { cmath::atanf128(self) }
+ cmath::atanf128(self)
}
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
@@ -939,7 +939,7 @@ pub fn atan(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn atan2(self, other: f128) -> f128 {
- unsafe { cmath::atan2f128(self, other) }
+ cmath::atan2f128(self, other)
}
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
@@ -1008,7 +1008,7 @@ pub fn sin_cos(self) -> (f128, f128) {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn exp_m1(self) -> f128 {
- unsafe { cmath::expm1f128(self) }
+ cmath::expm1f128(self)
}
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
@@ -1055,7 +1055,7 @@ pub fn exp_m1(self) -> f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
pub fn ln_1p(self) -> f128 {
- unsafe { cmath::log1pf128(self) }
+ cmath::log1pf128(self)
}
/// Hyperbolic sine function.
@@ -1090,7 +1090,7 @@ pub fn ln_1p(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn sinh(self) -> f128 {
- unsafe { cmath::sinhf128(self) }
+ cmath::sinhf128(self)
}
/// Hyperbolic cosine function.
@@ -1125,7 +1125,7 @@ pub fn sinh(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn cosh(self) -> f128 {
- unsafe { cmath::coshf128(self) }
+ cmath::coshf128(self)
}
/// Hyperbolic tangent function.
@@ -1160,7 +1160,7 @@ pub fn cosh(self) -> f128 {
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn tanh(self) -> f128 {
- unsafe { cmath::tanhf128(self) }
+ cmath::tanhf128(self)
}
/// Inverse hyperbolic sine function.
@@ -1289,7 +1289,7 @@ pub fn atanh(self) -> f128 {
// #[unstable(feature = "float_gamma", issue = "99842")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn gamma(self) -> f128 {
- unsafe { cmath::tgammaf128(self) }
+ cmath::tgammaf128(self)
}
/// Natural logarithm of the absolute value of the gamma function
@@ -1325,7 +1325,7 @@ pub fn gamma(self) -> f128 {
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn ln_gamma(self) -> (f128, i32) {
let mut signgamp: i32 = 0;
- let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) };
+ let x = cmath::lgammaf128_r(self, &mut signgamp);
(x, signgamp)
}
@@ -1365,7 +1365,7 @@ pub fn ln_gamma(self) -> (f128, i32) {
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f128 {
- unsafe { cmath::erff128(self) }
+ cmath::erff128(self)
}
/// Complementary error function.
@@ -1398,6 +1398,6 @@ pub fn erf(self) -> f128 {
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f128 {
- unsafe { cmath::erfcf128(self) }
+ cmath::erfcf128(self)
}
}
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index 286993d..4dadcbb 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -665,7 +665,7 @@ pub fn log10(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn cbrt(self) -> f16 {
- (unsafe { cmath::cbrtf(self as f32) }) as f16
+ cmath::cbrtf(self as f32) as f16
}
/// Compute the distance between the origin and a point (`x`, `y`) on the
@@ -701,7 +701,7 @@ pub fn cbrt(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn hypot(self, other: f16) -> f16 {
- (unsafe { cmath::hypotf(self as f32, other as f32) }) as f16
+ cmath::hypotf(self as f32, other as f32) as f16
}
/// Computes the sine of a number (in radians).
@@ -787,7 +787,7 @@ pub fn cos(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn tan(self) -> f16 {
- (unsafe { cmath::tanf(self as f32) }) as f16
+ cmath::tanf(self as f32) as f16
}
/// Computes the arcsine of a number. Return value is in radians in
@@ -822,7 +822,7 @@ pub fn tan(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn asin(self) -> f16 {
- (unsafe { cmath::asinf(self as f32) }) as f16
+ cmath::asinf(self as f32) as f16
}
/// Computes the arccosine of a number. Return value is in radians in
@@ -857,7 +857,7 @@ pub fn asin(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn acos(self) -> f16 {
- (unsafe { cmath::acosf(self as f32) }) as f16
+ cmath::acosf(self as f32) as f16
}
/// Computes the arctangent of a number. Return value is in radians in the
@@ -891,7 +891,7 @@ pub fn acos(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn atan(self) -> f16 {
- (unsafe { cmath::atanf(self as f32) }) as f16
+ cmath::atanf(self as f32) as f16
}
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
@@ -937,7 +937,7 @@ pub fn atan(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn atan2(self, other: f16) -> f16 {
- (unsafe { cmath::atan2f(self as f32, other as f32) }) as f16
+ cmath::atan2f(self as f32, other as f32) as f16
}
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
@@ -1006,7 +1006,7 @@ pub fn sin_cos(self) -> (f16, f16) {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn exp_m1(self) -> f16 {
- (unsafe { cmath::expm1f(self as f32) }) as f16
+ cmath::expm1f(self as f32) as f16
}
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
@@ -1053,7 +1053,7 @@ pub fn exp_m1(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn ln_1p(self) -> f16 {
- (unsafe { cmath::log1pf(self as f32) }) as f16
+ cmath::log1pf(self as f32) as f16
}
/// Hyperbolic sine function.
@@ -1088,7 +1088,7 @@ pub fn ln_1p(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn sinh(self) -> f16 {
- (unsafe { cmath::sinhf(self as f32) }) as f16
+ cmath::sinhf(self as f32) as f16
}
/// Hyperbolic cosine function.
@@ -1123,7 +1123,7 @@ pub fn sinh(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn cosh(self) -> f16 {
- (unsafe { cmath::coshf(self as f32) }) as f16
+ cmath::coshf(self as f32) as f16
}
/// Hyperbolic tangent function.
@@ -1158,7 +1158,7 @@ pub fn cosh(self) -> f16 {
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn tanh(self) -> f16 {
- (unsafe { cmath::tanhf(self as f32) }) as f16
+ cmath::tanhf(self as f32) as f16
}
/// Inverse hyperbolic sine function.
@@ -1287,7 +1287,7 @@ pub fn atanh(self) -> f16 {
// #[unstable(feature = "float_gamma", issue = "99842")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn gamma(self) -> f16 {
- (unsafe { cmath::tgammaf(self as f32) }) as f16
+ cmath::tgammaf(self as f32) as f16
}
/// Natural logarithm of the absolute value of the gamma function
@@ -1323,7 +1323,7 @@ pub fn gamma(self) -> f16 {
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn ln_gamma(self) -> (f16, i32) {
let mut signgamp: i32 = 0;
- let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16;
+ let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16;
(x, signgamp)
}
@@ -1363,7 +1363,7 @@ pub fn ln_gamma(self) -> (f16, i32) {
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f16 {
- (unsafe { cmath::erff(self as f32) }) as f16
+ cmath::erff(self as f32) as f16
}
/// Complementary error function.
@@ -1396,6 +1396,6 @@ pub fn erf(self) -> f16 {
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f16 {
- (unsafe { cmath::erfcf(self as f32) }) as f16
+ cmath::erfcf(self as f32) as f16
}
}
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 980e7f7..baf7002 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -599,7 +599,7 @@ pub fn log10(self) -> f32 {
filing an issue describing your use-case too)."
)]
pub fn abs_sub(self, other: f32) -> f32 {
- unsafe { cmath::fdimf(self, other) }
+ cmath::fdimf(self, other)
}
/// Returns the cube root of a number.
@@ -626,7 +626,7 @@ pub fn abs_sub(self, other: f32) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cbrt(self) -> f32 {
- unsafe { cmath::cbrtf(self) }
+ cmath::cbrtf(self)
}
/// Compute the distance between the origin and a point (`x`, `y`) on the
@@ -657,7 +657,7 @@ pub fn cbrt(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn hypot(self, other: f32) -> f32 {
- unsafe { cmath::hypotf(self, other) }
+ cmath::hypotf(self, other)
}
/// Computes the sine of a number (in radians).
@@ -730,7 +730,7 @@ pub fn cos(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tan(self) -> f32 {
- unsafe { cmath::tanf(self) }
+ cmath::tanf(self)
}
/// Computes the arcsine of a number. Return value is in radians in
@@ -760,7 +760,7 @@ pub fn tan(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asin(self) -> f32 {
- unsafe { cmath::asinf(self) }
+ cmath::asinf(self)
}
/// Computes the arccosine of a number. Return value is in radians in
@@ -790,7 +790,7 @@ pub fn asin(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acos(self) -> f32 {
- unsafe { cmath::acosf(self) }
+ cmath::acosf(self)
}
/// Computes the arctangent of a number. Return value is in radians in the
@@ -819,7 +819,7 @@ pub fn acos(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan(self) -> f32 {
- unsafe { cmath::atanf(self) }
+ cmath::atanf(self)
}
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
@@ -860,7 +860,7 @@ pub fn atan(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan2(self, other: f32) -> f32 {
- unsafe { cmath::atan2f(self, other) }
+ cmath::atan2f(self, other)
}
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
@@ -919,7 +919,7 @@ pub fn sin_cos(self) -> (f32, f32) {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp_m1(self) -> f32 {
- unsafe { cmath::expm1f(self) }
+ cmath::expm1f(self)
}
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
@@ -957,7 +957,7 @@ pub fn exp_m1(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ln_1p(self) -> f32 {
- unsafe { cmath::log1pf(self) }
+ cmath::log1pf(self)
}
/// Hyperbolic sine function.
@@ -987,7 +987,7 @@ pub fn ln_1p(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sinh(self) -> f32 {
- unsafe { cmath::sinhf(self) }
+ cmath::sinhf(self)
}
/// Hyperbolic cosine function.
@@ -1017,7 +1017,7 @@ pub fn sinh(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cosh(self) -> f32 {
- unsafe { cmath::coshf(self) }
+ cmath::coshf(self)
}
/// Hyperbolic tangent function.
@@ -1047,7 +1047,7 @@ pub fn cosh(self) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tanh(self) -> f32 {
- unsafe { cmath::tanhf(self) }
+ cmath::tanhf(self)
}
/// Inverse hyperbolic sine function.
@@ -1158,7 +1158,7 @@ pub fn atanh(self) -> f32 {
#[unstable(feature = "float_gamma", issue = "99842")]
#[inline]
pub fn gamma(self) -> f32 {
- unsafe { cmath::tgammaf(self) }
+ cmath::tgammaf(self)
}
/// Natural logarithm of the absolute value of the gamma function
@@ -1188,7 +1188,7 @@ pub fn gamma(self) -> f32 {
#[inline]
pub fn ln_gamma(self) -> (f32, i32) {
let mut signgamp: i32 = 0;
- let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) };
+ let x = cmath::lgammaf_r(self, &mut signgamp);
(x, signgamp)
}
@@ -1224,7 +1224,7 @@ pub fn ln_gamma(self) -> (f32, i32) {
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f32 {
- unsafe { cmath::erff(self) }
+ cmath::erff(self)
}
/// Complementary error function.
@@ -1253,6 +1253,6 @@ pub fn erf(self) -> f32 {
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f32 {
- unsafe { cmath::erfcf(self) }
+ cmath::erfcf(self)
}
}
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 2aaab3f..84fd9bf 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -599,7 +599,7 @@ pub fn log10(self) -> f64 {
filing an issue describing your use-case too)."
)]
pub fn abs_sub(self, other: f64) -> f64 {
- unsafe { cmath::fdim(self, other) }
+ cmath::fdim(self, other)
}
/// Returns the cube root of a number.
@@ -626,7 +626,7 @@ pub fn abs_sub(self, other: f64) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cbrt(self) -> f64 {
- unsafe { cmath::cbrt(self) }
+ cmath::cbrt(self)
}
/// Compute the distance between the origin and a point (`x`, `y`) on the
@@ -657,7 +657,7 @@ pub fn cbrt(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn hypot(self, other: f64) -> f64 {
- unsafe { cmath::hypot(self, other) }
+ cmath::hypot(self, other)
}
/// Computes the sine of a number (in radians).
@@ -730,7 +730,7 @@ pub fn cos(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tan(self) -> f64 {
- unsafe { cmath::tan(self) }
+ cmath::tan(self)
}
/// Computes the arcsine of a number. Return value is in radians in
@@ -760,7 +760,7 @@ pub fn tan(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asin(self) -> f64 {
- unsafe { cmath::asin(self) }
+ cmath::asin(self)
}
/// Computes the arccosine of a number. Return value is in radians in
@@ -790,7 +790,7 @@ pub fn asin(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acos(self) -> f64 {
- unsafe { cmath::acos(self) }
+ cmath::acos(self)
}
/// Computes the arctangent of a number. Return value is in radians in the
@@ -819,7 +819,7 @@ pub fn acos(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan(self) -> f64 {
- unsafe { cmath::atan(self) }
+ cmath::atan(self)
}
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
@@ -860,7 +860,7 @@ pub fn atan(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan2(self, other: f64) -> f64 {
- unsafe { cmath::atan2(self, other) }
+ cmath::atan2(self, other)
}
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
@@ -919,7 +919,7 @@ pub fn sin_cos(self) -> (f64, f64) {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp_m1(self) -> f64 {
- unsafe { cmath::expm1(self) }
+ cmath::expm1(self)
}
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
@@ -957,7 +957,7 @@ pub fn exp_m1(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ln_1p(self) -> f64 {
- unsafe { cmath::log1p(self) }
+ cmath::log1p(self)
}
/// Hyperbolic sine function.
@@ -987,7 +987,7 @@ pub fn ln_1p(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sinh(self) -> f64 {
- unsafe { cmath::sinh(self) }
+ cmath::sinh(self)
}
/// Hyperbolic cosine function.
@@ -1017,7 +1017,7 @@ pub fn sinh(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cosh(self) -> f64 {
- unsafe { cmath::cosh(self) }
+ cmath::cosh(self)
}
/// Hyperbolic tangent function.
@@ -1047,7 +1047,7 @@ pub fn cosh(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tanh(self) -> f64 {
- unsafe { cmath::tanh(self) }
+ cmath::tanh(self)
}
/// Inverse hyperbolic sine function.
@@ -1158,7 +1158,7 @@ pub fn atanh(self) -> f64 {
#[unstable(feature = "float_gamma", issue = "99842")]
#[inline]
pub fn gamma(self) -> f64 {
- unsafe { cmath::tgamma(self) }
+ cmath::tgamma(self)
}
/// Natural logarithm of the absolute value of the gamma function
@@ -1188,7 +1188,7 @@ pub fn gamma(self) -> f64 {
#[inline]
pub fn ln_gamma(self) -> (f64, i32) {
let mut signgamp: i32 = 0;
- let x = unsafe { cmath::lgamma_r(self, &mut signgamp) };
+ let x = cmath::lgamma_r(self, &mut signgamp);
(x, signgamp)
}
@@ -1224,7 +1224,7 @@ pub fn ln_gamma(self) -> (f64, i32) {
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f64 {
- unsafe { cmath::erf(self) }
+ cmath::erf(self)
}
/// Complementary error function.
@@ -1253,6 +1253,6 @@ pub fn erf(self) -> f64 {
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f64 {
- unsafe { cmath::erfc(self) }
+ cmath::erfc(self)
}
}
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 2498fb8..cf3778b 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -48,6 +48,7 @@
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), doc(search_unbox))]
pub type Result<T> = result::Result<T, Error>;
/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index b6545ea..5242261 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2658,6 +2658,10 @@ pub fn into_inner(self) -> (T, U) {
/// Gets references to the underlying readers in this `Chain`.
///
+ /// Care should be taken to avoid modifying the internal I/O state of the
+ /// underlying readers as doing so may corrupt the internal state of this
+ /// `Chain`.
+ ///
/// # Examples
///
/// ```no_run
@@ -2915,6 +2919,10 @@ pub fn into_inner(self) -> T {
/// Gets a reference to the underlying reader.
///
+ /// Care should be taken to avoid modifying the internal I/O state of the
+ /// underlying reader as doing so may corrupt the internal limit of this
+ /// `Take`.
+ ///
/// # Examples
///
/// ```no_run
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5c38118..3a52b77 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -312,7 +312,6 @@
#![feature(needs_panic_runtime)]
#![feature(negative_impls)]
#![feature(never_type)]
-#![feature(no_sanitize)]
#![feature(optimize_attribute)]
#![feature(prelude_import)]
#![feature(rustc_attrs)]
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index da51801..76ce7bc 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1286,6 +1286,40 @@ pub struct Output {
pub stderr: Vec<u8>,
}
+impl Output {
+ /// Returns an error if a nonzero exit status was received.
+ ///
+ /// If the [`Command`] exited successfully,
+ /// `self` is returned.
+ ///
+ /// This is equivalent to calling [`exit_ok`](ExitStatus::exit_ok)
+ /// on [`Output.status`](Output::status).
+ ///
+ /// Note that this will throw away the [`Output::stderr`] field in the error case.
+ /// If the child process outputs useful informantion to stderr, you can:
+ /// * Use `cmd.stderr(Stdio::inherit())` to forward the
+ /// stderr child process to the parent's stderr,
+ /// usually printing it to console where the user can see it.
+ /// This is usually correct for command-line applications.
+ /// * Capture `stderr` using a custom error type.
+ /// This is usually correct for libraries.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(exit_status_error)]
+ /// # #[cfg(unix)] {
+ /// use std::process::Command;
+ /// assert!(Command::new("false").output().unwrap().exit_ok().is_err());
+ /// # }
+ /// ```
+ #[unstable(feature = "exit_status_error", issue = "84908")]
+ pub fn exit_ok(self) -> Result<Self, ExitStatusError> {
+ self.status.exit_ok()?;
+ Ok(self)
+ }
+}
+
// If either stderr or stdout are valid utf8 strings it prints the valid
// strings, otherwise it prints the byte sequence instead
#[stable(feature = "process_output_debug", since = "1.7.0")]
diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs
index d88914f..1c6acb2 100644
--- a/library/std/src/sync/mpmc/list.rs
+++ b/library/std/src/sync/mpmc/list.rs
@@ -213,6 +213,11 @@ fn start_send(&self, token: &mut Token) -> bool {
.compare_exchange(block, new, Ordering::Release, Ordering::Relaxed)
.is_ok()
{
+ // This yield point leaves the channel in a half-initialized state where the
+ // tail.block pointer is set but the head.block is not. This is used to
+ // facilitate the test in src/tools/miri/tests/pass/issues/issue-139553.rs
+ #[cfg(miri)]
+ crate::thread::yield_now();
self.head.block.store(new, Ordering::Release);
block = new;
} else {
@@ -564,9 +569,15 @@ fn discard_all_messages(&self) {
// In that case, just wait until it gets initialized.
while block.is_null() {
backoff.spin_heavy();
- block = self.head.block.load(Ordering::Acquire);
+ block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel);
}
}
+ // After this point `head.block` is not modified again and it will be deallocated if it's
+ // non-null. The `Drop` code of the channel, which runs after this function, also attempts
+ // to deallocate `head.block` if it's non-null. Therefore this function must maintain the
+ // invariant that if a deallocation of head.block is attemped then it must also be set to
+ // NULL. Failing to do so will lead to the Drop code attempting a double free. For this
+ // reason both reads above do an atomic swap instead of a simple atomic load.
unsafe {
// Drop all messages between head and tail and deallocate the heap-allocated blocks.
diff --git a/library/std/src/sys/args/common.rs b/library/std/src/sys/args/common.rs
new file mode 100644
index 0000000..43ac5e9
--- /dev/null
+++ b/library/std/src/sys/args/common.rs
@@ -0,0 +1,43 @@
+use crate::ffi::OsString;
+use crate::{fmt, vec};
+
+pub struct Args {
+ iter: vec::IntoIter<OsString>,
+}
+
+impl !Send for Args {}
+impl !Sync for Args {}
+
+impl Args {
+ pub(super) fn new(args: Vec<OsString>) -> Self {
+ Args { iter: args.into_iter() }
+ }
+}
+
+impl fmt::Debug for Args {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.iter.as_slice().fmt(f)
+ }
+}
+
+impl Iterator for Args {
+ type Item = OsString;
+ fn next(&mut self) -> Option<OsString> {
+ self.iter.next()
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl ExactSizeIterator for Args {
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl DoubleEndedIterator for Args {
+ fn next_back(&mut self) -> Option<OsString> {
+ self.iter.next_back()
+ }
+}
diff --git a/library/std/src/sys/args/hermit.rs b/library/std/src/sys/args/hermit.rs
new file mode 100644
index 0000000..ddd644a
--- /dev/null
+++ b/library/std/src/sys/args/hermit.rs
@@ -0,0 +1,35 @@
+use crate::ffi::{CStr, OsString, c_char};
+use crate::os::hermit::ffi::OsStringExt;
+use crate::ptr;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{AtomicIsize, AtomicPtr};
+
+#[path = "common.rs"]
+mod common;
+pub use common::Args;
+
+static ARGC: AtomicIsize = AtomicIsize::new(0);
+static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
+
+/// One-time global initialization.
+pub unsafe fn init(argc: isize, argv: *const *const u8) {
+ ARGC.store(argc, Relaxed);
+ // Use release ordering here to broadcast writes by the OS.
+ ARGV.store(argv as *mut *const u8, Release);
+}
+
+/// Returns the command line arguments
+pub fn args() -> Args {
+ // Synchronize with the store above.
+ let argv = ARGV.load(Acquire);
+ // If argv has not been initialized yet, do not return any arguments.
+ let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) };
+ let args: Vec<OsString> = (0..argc)
+ .map(|i| unsafe {
+ let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char);
+ OsStringExt::from_vec(cstr.to_bytes().to_vec())
+ })
+ .collect();
+
+ Args::new(args)
+}
diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs
new file mode 100644
index 0000000..f24d6eb
--- /dev/null
+++ b/library/std/src/sys/args/mod.rs
@@ -0,0 +1,34 @@
+//! Platform-dependent command line arguments abstraction.
+
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+cfg_if::cfg_if! {
+ if #[cfg(all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))))] {
+ mod unix;
+ pub use unix::*;
+ } else if #[cfg(target_family = "windows")] {
+ mod windows;
+ pub use windows::*;
+ } else if #[cfg(target_os = "hermit")] {
+ mod hermit;
+ pub use hermit::*;
+ } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
+ mod sgx;
+ pub use sgx::*;
+ } else if #[cfg(target_os = "uefi")] {
+ mod uefi;
+ pub use uefi::*;
+ } else if #[cfg(target_os = "wasi")] {
+ mod wasi;
+ pub use wasi::*;
+ } else if #[cfg(target_os = "xous")] {
+ mod xous;
+ pub use xous::*;
+ } else if #[cfg(target_os = "zkvm")] {
+ mod zkvm;
+ pub use zkvm::*;
+ } else {
+ mod unsupported;
+ pub use unsupported::*;
+ }
+}
diff --git a/library/std/src/sys/pal/sgx/args.rs b/library/std/src/sys/args/sgx.rs
similarity index 88%
rename from library/std/src/sys/pal/sgx/args.rs
rename to library/std/src/sys/args/sgx.rs
index e62bf38..efc4b79 100644
--- a/library/std/src/sys/pal/sgx/args.rs
+++ b/library/std/src/sys/args/sgx.rs
@@ -1,8 +1,10 @@
-use super::abi::usercalls::alloc;
-use super::abi::usercalls::raw::ByteBuffer;
+#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers
+
use crate::ffi::OsString;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::os_str::Buf;
+use crate::sys::pal::abi::usercalls::alloc;
+use crate::sys::pal::abi::usercalls::raw::ByteBuffer;
use crate::sys_common::FromInner;
use crate::{fmt, slice};
diff --git a/library/std/src/sys/pal/uefi/args.rs b/library/std/src/sys/args/uefi.rs
similarity index 79%
rename from library/std/src/sys/pal/uefi/args.rs
rename to library/std/src/sys/args/uefi.rs
index 0c29caf..84406c7 100644
--- a/library/std/src/sys/pal/uefi/args.rs
+++ b/library/std/src/sys/args/uefi.rs
@@ -1,14 +1,13 @@
use r_efi::protocols::loaded_image;
-use super::helpers;
use crate::env::current_exe;
use crate::ffi::OsString;
use crate::iter::Iterator;
-use crate::{fmt, vec};
+use crate::sys::pal::helpers;
-pub struct Args {
- parsed_args_list: vec::IntoIter<OsString>,
-}
+#[path = "common.rs"]
+mod common;
+pub use common::Args;
pub fn args() -> Args {
let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]);
@@ -22,51 +21,17 @@ pub fn args() -> Args {
let lp_size = unsafe { (*protocol.as_ptr()).load_options_size } as usize;
// Break if we are sure that it cannot be UTF-16
if lp_size < size_of::<u16>() || lp_size % size_of::<u16>() != 0 {
- return Args { parsed_args_list: lazy_current_exe().into_iter() };
+ return Args::new(lazy_current_exe());
}
let lp_size = lp_size / size_of::<u16>();
let lp_cmd_line = unsafe { (*protocol.as_ptr()).load_options as *const u16 };
if !lp_cmd_line.is_aligned() {
- return Args { parsed_args_list: lazy_current_exe().into_iter() };
+ return Args::new(lazy_current_exe());
}
let lp_cmd_line = unsafe { crate::slice::from_raw_parts(lp_cmd_line, lp_size) };
- Args {
- parsed_args_list: parse_lp_cmd_line(lp_cmd_line)
- .unwrap_or_else(lazy_current_exe)
- .into_iter(),
- }
-}
-
-impl fmt::Debug for Args {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.parsed_args_list.as_slice().fmt(f)
- }
-}
-
-impl Iterator for Args {
- type Item = OsString;
-
- fn next(&mut self) -> Option<OsString> {
- self.parsed_args_list.next()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.parsed_args_list.size_hint()
- }
-}
-
-impl ExactSizeIterator for Args {
- fn len(&self) -> usize {
- self.parsed_args_list.len()
- }
-}
-
-impl DoubleEndedIterator for Args {
- fn next_back(&mut self) -> Option<OsString> {
- self.parsed_args_list.next_back()
- }
+ Args::new(parse_lp_cmd_line(lp_cmd_line).unwrap_or_else(lazy_current_exe))
}
/// Implements the UEFI command-line argument parsing algorithm.
diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/args/unix.rs
similarity index 85%
rename from library/std/src/sys/pal/unix/args.rs
rename to library/std/src/sys/args/unix.rs
index 0bb7b64..7d7815c 100644
--- a/library/std/src/sys/pal/unix/args.rs
+++ b/library/std/src/sys/args/unix.rs
@@ -5,13 +5,16 @@
#![allow(dead_code)] // runtime init functions not used during testing
-use crate::ffi::{CStr, OsString};
+use crate::ffi::CStr;
use crate::os::unix::ffi::OsStringExt;
-use crate::{fmt, vec};
+
+#[path = "common.rs"]
+mod common;
+pub use common::Args;
/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
- imp::init(argc, argv)
+ unsafe { imp::init(argc, argv) }
}
/// Returns the command line arguments
@@ -55,42 +58,7 @@ pub fn args() -> Args {
vec.push(OsStringExt::from_vec(cstr.to_bytes().to_vec()));
}
- Args { iter: vec.into_iter() }
-}
-
-pub struct Args {
- iter: vec::IntoIter<OsString>,
-}
-
-impl !Send for Args {}
-impl !Sync for Args {}
-
-impl fmt::Debug for Args {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.iter.as_slice().fmt(f)
- }
-}
-
-impl Iterator for Args {
- type Item = OsString;
- fn next(&mut self) -> Option<OsString> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl ExactSizeIterator for Args {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl DoubleEndedIterator for Args {
- fn next_back(&mut self) -> Option<OsString> {
- self.iter.next_back()
- }
+ Args::new(vec)
}
#[cfg(any(
@@ -141,7 +109,7 @@ unsafe fn really_init(argc: isize, argv: *const *const u8) {
pub unsafe fn init(argc: isize, argv: *const *const u8) {
// on GNU/Linux if we are main then we will init argv and argc twice, it "duplicates work"
// BUT edge-cases are real: only using .init_array can break most emulators, dlopen, etc.
- really_init(argc, argv);
+ unsafe { really_init(argc, argv) };
}
/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
@@ -159,9 +127,7 @@ extern "C" fn init_wrapper(
argv: *const *const u8,
_envp: *const *const u8,
) {
- unsafe {
- really_init(argc as isize, argv);
- }
+ unsafe { really_init(argc as isize, argv) };
}
init_wrapper
};
@@ -228,16 +194,3 @@ pub fn argc_argv() -> (isize, *const *const c_char) {
(argc as isize, argv.cast())
}
}
-
-#[cfg(any(target_os = "espidf", target_os = "vita"))]
-mod imp {
- use crate::ffi::c_char;
- use crate::ptr;
-
- #[inline(always)]
- pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
-
- pub fn argc_argv() -> (isize, *const *const c_char) {
- (0, ptr::null())
- }
-}
diff --git a/library/std/src/sys/pal/unsupported/args.rs b/library/std/src/sys/args/unsupported.rs
similarity index 100%
rename from library/std/src/sys/pal/unsupported/args.rs
rename to library/std/src/sys/args/unsupported.rs
diff --git a/library/std/src/sys/args/wasi.rs b/library/std/src/sys/args/wasi.rs
new file mode 100644
index 0000000..4795789
--- /dev/null
+++ b/library/std/src/sys/args/wasi.rs
@@ -0,0 +1,29 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use crate::ffi::{CStr, OsStr, OsString};
+use crate::os::wasi::ffi::OsStrExt;
+
+#[path = "common.rs"]
+mod common;
+pub use common::Args;
+
+/// Returns the command line arguments
+pub fn args() -> Args {
+ Args::new(maybe_args().unwrap_or(Vec::new()))
+}
+
+fn maybe_args() -> Option<Vec<OsString>> {
+ unsafe {
+ let (argc, buf_size) = wasi::args_sizes_get().ok()?;
+ let mut argv = Vec::with_capacity(argc);
+ let mut buf = Vec::with_capacity(buf_size);
+ wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
+ argv.set_len(argc);
+ let mut ret = Vec::with_capacity(argc);
+ for ptr in argv {
+ let s = CStr::from_ptr(ptr.cast());
+ ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
+ }
+ Some(ret)
+ }
+}
diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/args/windows.rs
similarity index 94%
rename from library/std/src/sys/pal/windows/args.rs
rename to library/std/src/sys/args/windows.rs
index d973743..47f0e5f 100644
--- a/library/std/src/sys/pal/windows/args.rs
+++ b/library/std/src/sys/args/windows.rs
@@ -6,17 +6,21 @@
#[cfg(test)]
mod tests;
-use super::ensure_no_nuls;
-use super::os::current_exe;
use crate::ffi::{OsStr, OsString};
use crate::num::NonZero;
use crate::os::windows::prelude::*;
use crate::path::{Path, PathBuf};
+use crate::sys::pal::os::current_exe;
+use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf};
use crate::sys::path::get_long_path;
use crate::sys::{c, to_u16s};
use crate::sys_common::AsInner;
use crate::sys_common::wstr::WStrUnits;
-use crate::{fmt, io, iter, vec};
+use crate::{io, iter, ptr};
+
+#[path = "common.rs"]
+mod common;
+pub use common::Args;
pub fn args() -> Args {
// SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16
@@ -27,7 +31,7 @@ pub fn args() -> Args {
current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new())
});
- Args { parsed_args_list: parsed_args_list.into_iter() }
+ Args::new(parsed_args_list)
}
}
@@ -153,38 +157,6 @@ fn parse_lp_cmd_line<'a, F: Fn() -> OsString>(
ret_val
}
-pub struct Args {
- parsed_args_list: vec::IntoIter<OsString>,
-}
-
-impl fmt::Debug for Args {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.parsed_args_list.as_slice().fmt(f)
- }
-}
-
-impl Iterator for Args {
- type Item = OsString;
- fn next(&mut self) -> Option<OsString> {
- self.parsed_args_list.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.parsed_args_list.size_hint()
- }
-}
-
-impl DoubleEndedIterator for Args {
- fn next_back(&mut self) -> Option<OsString> {
- self.parsed_args_list.next_back()
- }
-}
-
-impl ExactSizeIterator for Args {
- fn len(&self) -> usize {
- self.parsed_args_list.len()
- }
-}
-
#[derive(Debug)]
pub(crate) enum Arg {
/// Add quotes (if needed)
@@ -384,9 +356,6 @@ pub(crate) fn to_user_path(path: &Path) -> io::Result<Vec<u16>> {
from_wide_to_user_path(to_u16s(path)?)
}
pub(crate) fn from_wide_to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> {
- use super::fill_utf16_buf;
- use crate::ptr;
-
// UTF-16 encoded code points, used in parsing and building UTF-16 paths.
// All of these are in the ASCII range so they can be cast directly to `u16`.
const SEP: u16 = b'\\' as _;
diff --git a/library/std/src/sys/pal/windows/args/tests.rs b/library/std/src/sys/args/windows/tests.rs
similarity index 100%
rename from library/std/src/sys/pal/windows/args/tests.rs
rename to library/std/src/sys/args/windows/tests.rs
diff --git a/library/std/src/sys/args/xous.rs b/library/std/src/sys/args/xous.rs
new file mode 100644
index 0000000..09a4728
--- /dev/null
+++ b/library/std/src/sys/args/xous.rs
@@ -0,0 +1,23 @@
+use crate::sys::pal::os::get_application_parameters;
+use crate::sys::pal::os::params::ArgumentList;
+
+#[path = "common.rs"]
+mod common;
+pub use common::Args;
+
+pub fn args() -> Args {
+ let Some(params) = get_application_parameters() else {
+ return Args::new(vec![]);
+ };
+
+ for param in params {
+ if let Ok(args) = ArgumentList::try_from(¶m) {
+ let mut parsed_args = vec![];
+ for arg in args {
+ parsed_args.push(arg.into());
+ }
+ return Args::new(parsed_args);
+ }
+ }
+ Args::new(vec![])
+}
diff --git a/library/std/src/sys/pal/zkvm/args.rs b/library/std/src/sys/args/zkvm.rs
similarity index 97%
rename from library/std/src/sys/pal/zkvm/args.rs
rename to library/std/src/sys/args/zkvm.rs
index 47857f6..194ba71 100644
--- a/library/std/src/sys/pal/zkvm/args.rs
+++ b/library/std/src/sys/args/zkvm.rs
@@ -1,7 +1,7 @@
-use super::{WORD_SIZE, abi};
use crate::ffi::OsString;
use crate::fmt;
use crate::sys::os_str;
+use crate::sys::pal::{WORD_SIZE, abi};
use crate::sys_common::FromInner;
pub struct Args {
diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs
index c9969b4..668fd92 100644
--- a/library/std/src/sys/cmath.rs
+++ b/library/std/src/sys/cmath.rs
@@ -3,70 +3,70 @@
// These symbols are all defined by `libm`,
// or by `compiler-builtins` on unsupported platforms.
unsafe extern "C" {
- pub fn acos(n: f64) -> f64;
- pub fn asin(n: f64) -> f64;
- pub fn atan(n: f64) -> f64;
- pub fn atan2(a: f64, b: f64) -> f64;
- pub fn cbrt(n: f64) -> f64;
- pub fn cbrtf(n: f32) -> f32;
- pub fn cosh(n: f64) -> f64;
- pub fn expm1(n: f64) -> f64;
- pub fn expm1f(n: f32) -> f32;
- pub fn fdim(a: f64, b: f64) -> f64;
- pub fn fdimf(a: f32, b: f32) -> f32;
+ pub safe fn acos(n: f64) -> f64;
+ pub safe fn asin(n: f64) -> f64;
+ pub safe fn atan(n: f64) -> f64;
+ pub safe fn atan2(a: f64, b: f64) -> f64;
+ pub safe fn cbrt(n: f64) -> f64;
+ pub safe fn cbrtf(n: f32) -> f32;
+ pub safe fn cosh(n: f64) -> f64;
+ pub safe fn expm1(n: f64) -> f64;
+ pub safe fn expm1f(n: f32) -> f32;
+ pub safe fn fdim(a: f64, b: f64) -> f64;
+ pub safe fn fdimf(a: f32, b: f32) -> f32;
#[cfg_attr(target_env = "msvc", link_name = "_hypot")]
- pub fn hypot(x: f64, y: f64) -> f64;
+ pub safe fn hypot(x: f64, y: f64) -> f64;
#[cfg_attr(target_env = "msvc", link_name = "_hypotf")]
- pub fn hypotf(x: f32, y: f32) -> f32;
- pub fn log1p(n: f64) -> f64;
- pub fn log1pf(n: f32) -> f32;
- pub fn sinh(n: f64) -> f64;
- pub fn tan(n: f64) -> f64;
- pub fn tanh(n: f64) -> f64;
- pub fn tgamma(n: f64) -> f64;
- pub fn tgammaf(n: f32) -> f32;
- pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
+ pub safe fn hypotf(x: f32, y: f32) -> f32;
+ pub safe fn log1p(n: f64) -> f64;
+ pub safe fn log1pf(n: f32) -> f32;
+ pub safe fn sinh(n: f64) -> f64;
+ pub safe fn tan(n: f64) -> f64;
+ pub safe fn tanh(n: f64) -> f64;
+ pub safe fn tgamma(n: f64) -> f64;
+ pub safe fn tgammaf(n: f32) -> f32;
+ pub safe fn lgamma_r(n: f64, s: &mut i32) -> f64;
#[cfg(not(target_os = "aix"))]
- pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
- pub fn erf(n: f64) -> f64;
- pub fn erff(n: f32) -> f32;
- pub fn erfc(n: f64) -> f64;
- pub fn erfcf(n: f32) -> f32;
+ pub safe fn lgammaf_r(n: f32, s: &mut i32) -> f32;
+ pub safe fn erf(n: f64) -> f64;
+ pub safe fn erff(n: f32) -> f32;
+ pub safe fn erfc(n: f64) -> f64;
+ pub safe fn erfcf(n: f32) -> f32;
- pub fn acosf128(n: f128) -> f128;
- pub fn asinf128(n: f128) -> f128;
- pub fn atanf128(n: f128) -> f128;
- pub fn atan2f128(a: f128, b: f128) -> f128;
- pub fn cbrtf128(n: f128) -> f128;
- pub fn coshf128(n: f128) -> f128;
- pub fn expm1f128(n: f128) -> f128;
- pub fn hypotf128(x: f128, y: f128) -> f128;
- pub fn log1pf128(n: f128) -> f128;
- pub fn sinhf128(n: f128) -> f128;
- pub fn tanf128(n: f128) -> f128;
- pub fn tanhf128(n: f128) -> f128;
- pub fn tgammaf128(n: f128) -> f128;
- pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
- pub fn erff128(n: f128) -> f128;
- pub fn erfcf128(n: f128) -> f128;
+ pub safe fn acosf128(n: f128) -> f128;
+ pub safe fn asinf128(n: f128) -> f128;
+ pub safe fn atanf128(n: f128) -> f128;
+ pub safe fn atan2f128(a: f128, b: f128) -> f128;
+ pub safe fn cbrtf128(n: f128) -> f128;
+ pub safe fn coshf128(n: f128) -> f128;
+ pub safe fn expm1f128(n: f128) -> f128;
+ pub safe fn hypotf128(x: f128, y: f128) -> f128;
+ pub safe fn log1pf128(n: f128) -> f128;
+ pub safe fn sinhf128(n: f128) -> f128;
+ pub safe fn tanf128(n: f128) -> f128;
+ pub safe fn tanhf128(n: f128) -> f128;
+ pub safe fn tgammaf128(n: f128) -> f128;
+ pub safe fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
+ pub safe fn erff128(n: f128) -> f128;
+ pub safe fn erfcf128(n: f128) -> f128;
cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] {
- pub fn acosf(n: f32) -> f32;
- pub fn asinf(n: f32) -> f32;
- pub fn atan2f(a: f32, b: f32) -> f32;
- pub fn atanf(n: f32) -> f32;
- pub fn coshf(n: f32) -> f32;
- pub fn sinhf(n: f32) -> f32;
- pub fn tanf(n: f32) -> f32;
- pub fn tanhf(n: f32) -> f32;
+ pub safe fn acosf(n: f32) -> f32;
+ pub safe fn asinf(n: f32) -> f32;
+ pub safe fn atan2f(a: f32, b: f32) -> f32;
+ pub safe fn atanf(n: f32) -> f32;
+ pub safe fn coshf(n: f32) -> f32;
+ pub safe fn sinhf(n: f32) -> f32;
+ pub safe fn tanf(n: f32) -> f32;
+ pub safe fn tanhf(n: f32) -> f32;
}}
}
// On AIX, we don't have lgammaf_r only the f64 version, so we can
// use the f64 version lgamma_r
#[cfg(target_os = "aix")]
-pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 {
+pub fn lgammaf_r(n: f32, s: &mut i32) -> f32 {
lgamma_r(n.into(), s) as f32
}
@@ -76,42 +76,42 @@ pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 {
cfg_if::cfg_if! {
if #[cfg(all(target_os = "windows", target_env = "msvc", target_arch = "x86"))] {
#[inline]
- pub unsafe fn acosf(n: f32) -> f32 {
+ pub fn acosf(n: f32) -> f32 {
f64::acos(n as f64) as f32
}
#[inline]
- pub unsafe fn asinf(n: f32) -> f32 {
+ pub fn asinf(n: f32) -> f32 {
f64::asin(n as f64) as f32
}
#[inline]
- pub unsafe fn atan2f(n: f32, b: f32) -> f32 {
+ pub fn atan2f(n: f32, b: f32) -> f32 {
f64::atan2(n as f64, b as f64) as f32
}
#[inline]
- pub unsafe fn atanf(n: f32) -> f32 {
+ pub fn atanf(n: f32) -> f32 {
f64::atan(n as f64) as f32
}
#[inline]
- pub unsafe fn coshf(n: f32) -> f32 {
+ pub fn coshf(n: f32) -> f32 {
f64::cosh(n as f64) as f32
}
#[inline]
- pub unsafe fn sinhf(n: f32) -> f32 {
+ pub fn sinhf(n: f32) -> f32 {
f64::sinh(n as f64) as f32
}
#[inline]
- pub unsafe fn tanf(n: f32) -> f32 {
+ pub fn tanf(n: f32) -> f32 {
f64::tan(n as f64) as f32
}
#[inline]
- pub unsafe fn tanhf(n: f32) -> f32 {
+ pub fn tanhf(n: f32) -> f32 {
f64::tanh(n as f64) as f32
}
}}
diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs
index 2042ea2..cdca73c 100644
--- a/library/std/src/sys/fd/unix.rs
+++ b/library/std/src/sys/fd/unix.rs
@@ -71,9 +71,11 @@ const fn max_iov() -> usize {
target_os = "android",
target_os = "dragonfly",
target_os = "emscripten",
+ target_os = "espidf",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
+ target_os = "nuttx",
target_os = "nto",
target_os = "openbsd",
target_os = "horizon",
@@ -257,9 +259,6 @@ fn preadv(
}
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
- // FIXME(#115199): Rust currently omits weak function definitions
- // and its metadata from LLVM IR.
- #[no_sanitize(cfi)]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
weak!(
fn preadv64(
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index 3b176d0..4c5e36c 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -20,6 +20,7 @@
mod windows;
use windows as imp;
pub use windows::{symlink_inner, junction_point};
+ use crate::sys::path::with_native_path;
} else if #[cfg(target_os = "hermit")] {
mod hermit;
use hermit as imp;
@@ -39,7 +40,7 @@
}
// FIXME: Replace this with platform-specific path conversion functions.
-#[cfg(not(target_family = "unix"))]
+#[cfg(not(any(target_family = "unix", target_os = "windows")))]
#[inline]
pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
f(path)
@@ -51,7 +52,7 @@ pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> i
};
pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
- // FIXME: use with_native_path
+ // FIXME: use with_native_path on all platforms
imp::readdir(path)
}
@@ -68,8 +69,11 @@ pub fn remove_dir(path: &Path) -> io::Result<()> {
}
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
- // FIXME: use with_native_path
- imp::remove_dir_all(path)
+ // FIXME: use with_native_path on all platforms
+ #[cfg(not(windows))]
+ return imp::remove_dir_all(path);
+ #[cfg(windows)]
+ with_native_path(path, &imp::remove_dir_all)
}
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
@@ -77,6 +81,10 @@ pub fn read_link(path: &Path) -> io::Result<PathBuf> {
}
pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+ // FIXME: use with_native_path on all platforms
+ #[cfg(windows)]
+ return imp::symlink(original, link);
+ #[cfg(not(windows))]
with_native_path(original, &|original| {
with_native_path(link, &|link| imp::symlink(original, link))
})
@@ -105,11 +113,17 @@ pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
}
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
- // FIXME: use with_native_path
- imp::copy(from, to)
+ // FIXME: use with_native_path on all platforms
+ #[cfg(not(windows))]
+ return imp::copy(from, to);
+ #[cfg(windows)]
+ with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to)))
}
pub fn exists(path: &Path) -> io::Result<bool> {
- // FIXME: use with_native_path
- imp::exists(path)
+ // FIXME: use with_native_path on all platforms
+ #[cfg(not(windows))]
+ return imp::exists(path);
+ #[cfg(windows)]
+ with_native_path(path, &imp::exists)
}
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index 87865be..687fc32 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -1463,20 +1463,6 @@ pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
Ok(())
}
- // FIXME(#115199): Rust currently omits weak function definitions
- // and its metadata from LLVM IR.
- #[cfg_attr(
- any(
- target_os = "android",
- all(
- target_os = "linux",
- target_env = "gnu",
- target_pointer_width = "32",
- not(target_arch = "riscv32")
- )
- ),
- no_sanitize(cfi)
- )]
pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
#[cfg(not(any(
target_os = "redox",
diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs
index 15727c9..9215f93 100644
--- a/library/std/src/sys/fs/windows.rs
+++ b/library/std/src/sys/fs/windows.rs
@@ -12,7 +12,7 @@
use crate::sys::handle::Handle;
use crate::sys::pal::api::{self, WinError, set_file_information_by_handle};
use crate::sys::pal::{IoResult, fill_utf16_buf, to_u16s, truncate_utf16_at_nul};
-use crate::sys::path::maybe_verbatim;
+use crate::sys::path::{WCStr, maybe_verbatim};
use crate::sys::time::SystemTime;
use crate::sys::{Align8, c, cvt};
use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -298,10 +298,12 @@ fn get_flags_and_attributes(&self) -> u32 {
impl File {
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
let path = maybe_verbatim(path)?;
+ // SAFETY: maybe_verbatim returns null-terminated strings
+ let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) };
Self::open_native(&path, opts)
}
- fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result<File> {
+ fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result<File> {
let creation = opts.get_creation_mode()?;
let handle = unsafe {
c::CreateFileW(
@@ -1212,9 +1214,8 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
}
}
-pub fn unlink(p: &Path) -> io::Result<()> {
- let p_u16s = maybe_verbatim(p)?;
- if unsafe { c::DeleteFileW(p_u16s.as_ptr()) } == 0 {
+pub fn unlink(path: &WCStr) -> io::Result<()> {
+ if unsafe { c::DeleteFileW(path.as_ptr()) } == 0 {
let err = api::get_last_error();
// if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove
// the file while ignoring the readonly attribute.
@@ -1223,7 +1224,7 @@ pub fn unlink(p: &Path) -> io::Result<()> {
let mut opts = OpenOptions::new();
opts.access_mode(c::DELETE);
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT);
- if let Ok(f) = File::open_native(&p_u16s, &opts) {
+ if let Ok(f) = File::open_native(&path, &opts) {
if f.posix_delete().is_ok() {
return Ok(());
}
@@ -1236,10 +1237,7 @@ pub fn unlink(p: &Path) -> io::Result<()> {
}
}
-pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
- let old = maybe_verbatim(old)?;
- let new = maybe_verbatim(new)?;
-
+pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> {
if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) } == 0 {
let err = api::get_last_error();
// if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move
@@ -1253,7 +1251,8 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
// Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
// This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
- let Ok(new_len_without_nul_in_bytes): Result<u32, _> = ((new.len() - 1) * 2).try_into()
+ let Ok(new_len_without_nul_in_bytes): Result<u32, _> =
+ ((new.count_bytes() - 1) * 2).try_into()
else {
return Err(err).io_result();
};
@@ -1282,7 +1281,7 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
new.as_ptr().copy_to_nonoverlapping(
(&raw mut (*file_rename_info).FileName).cast::<u16>(),
- new.len(),
+ new.count_bytes(),
);
}
@@ -1309,20 +1308,19 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
Ok(())
}
-pub fn rmdir(p: &Path) -> io::Result<()> {
- let p = maybe_verbatim(p)?;
+pub fn rmdir(p: &WCStr) -> io::Result<()> {
cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) })?;
Ok(())
}
-pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+pub fn remove_dir_all(path: &WCStr) -> io::Result<()> {
// Open a file or directory without following symlinks.
let mut opts = OpenOptions::new();
opts.access_mode(c::FILE_LIST_DIRECTORY);
// `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories.
// `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target.
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT);
- let file = File::open(path, &opts)?;
+ let file = File::open_native(path, &opts)?;
// Test if the file is not a directory or a symlink to a directory.
if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 {
@@ -1333,14 +1331,14 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> {
remove_dir_all_iterative(file).io_result()
}
-pub fn readlink(path: &Path) -> io::Result<PathBuf> {
+pub fn readlink(path: &WCStr) -> io::Result<PathBuf> {
// Open the link with no access mode, instead of generic read.
// By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so
// this is needed for a common case.
let mut opts = OpenOptions::new();
opts.access_mode(0);
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
- let file = File::open(path, &opts)?;
+ let file = File::open_native(&path, &opts)?;
file.readlink()
}
@@ -1378,19 +1376,17 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()>
}
#[cfg(not(target_vendor = "uwp"))]
-pub fn link(original: &Path, link: &Path) -> io::Result<()> {
- let original = maybe_verbatim(original)?;
- let link = maybe_verbatim(link)?;
+pub fn link(original: &WCStr, link: &WCStr) -> io::Result<()> {
cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?;
Ok(())
}
#[cfg(target_vendor = "uwp")]
-pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
+pub fn link(_original: &WCStr, _link: &WCStr) -> io::Result<()> {
return Err(io::const_error!(io::ErrorKind::Unsupported, "hard link are not supported on UWP"));
}
-pub fn stat(path: &Path) -> io::Result<FileAttr> {
+pub fn stat(path: &WCStr) -> io::Result<FileAttr> {
match metadata(path, ReparsePoint::Follow) {
Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => {
if let Ok(attrs) = lstat(path) {
@@ -1404,7 +1400,7 @@ pub fn stat(path: &Path) -> io::Result<FileAttr> {
}
}
-pub fn lstat(path: &Path) -> io::Result<FileAttr> {
+pub fn lstat(path: &WCStr) -> io::Result<FileAttr> {
metadata(path, ReparsePoint::Open)
}
@@ -1420,7 +1416,7 @@ fn as_flag(self) -> u32 {
}
}
-fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
+fn metadata(path: &WCStr, reparse: ReparsePoint) -> io::Result<FileAttr> {
let mut opts = OpenOptions::new();
// No read or write permissions are necessary
opts.access_mode(0);
@@ -1429,7 +1425,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
// Attempt to open the file normally.
// If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileExW`.
// If the fallback fails for any reason we return the original error.
- match File::open(path, &opts) {
+ match File::open_native(&path, &opts) {
Ok(file) => file.file_attr(),
Err(e)
if [Some(c::ERROR_SHARING_VIOLATION as _), Some(c::ERROR_ACCESS_DENIED as _)]
@@ -1442,8 +1438,6 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
// However, there are special system files, such as
// `C:\hiberfil.sys`, that are locked in a way that denies even that.
unsafe {
- let path = maybe_verbatim(path)?;
-
// `FindFirstFileExW` accepts wildcard file names.
// Fortunately wildcards are not valid file names and
// `ERROR_SHARING_VIOLATION` means the file exists (but is locked)
@@ -1482,8 +1476,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
}
}
-pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
- let p = maybe_verbatim(p)?;
+pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> {
unsafe {
cvt(c::SetFileAttributesW(p.as_ptr(), perm.attrs))?;
Ok(())
@@ -1499,17 +1492,17 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
)
}
-pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
+pub fn canonicalize(p: &WCStr) -> io::Result<PathBuf> {
let mut opts = OpenOptions::new();
// No read or write permissions are necessary
opts.access_mode(0);
// This flag is so we can open directories too
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
- let f = File::open(p, &opts)?;
+ let f = File::open_native(p, &opts)?;
get_path(&f)
}
-pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+pub fn copy(from: &WCStr, to: &WCStr) -> io::Result<u64> {
unsafe extern "system" fn callback(
_TotalFileSize: i64,
_TotalBytesTransferred: i64,
@@ -1528,13 +1521,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
c::PROGRESS_CONTINUE
}
}
- let pfrom = maybe_verbatim(from)?;
- let pto = maybe_verbatim(to)?;
let mut size = 0i64;
cvt(unsafe {
c::CopyFileExW(
- pfrom.as_ptr(),
- pto.as_ptr(),
+ from.as_ptr(),
+ to.as_ptr(),
Some(callback),
(&raw mut size) as *mut _,
ptr::null_mut(),
@@ -1624,14 +1615,14 @@ pub struct MountPointBuffer {
}
// Try to see if a file exists but, unlike `exists`, report I/O errors.
-pub fn exists(path: &Path) -> io::Result<bool> {
+pub fn exists(path: &WCStr) -> io::Result<bool> {
// Open the file to ensure any symlinks are followed to their target.
let mut opts = OpenOptions::new();
// No read, write, etc access rights are needed.
opts.access_mode(0);
// Backup semantics enables opening directories as well as files.
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
- match File::open(path, &opts) {
+ match File::open_native(path, &opts) {
Err(e) => match e.kind() {
// The file definitely does not exist
io::ErrorKind::NotFound => Ok(false),
diff --git a/library/std/src/sys/fs/windows/remove_dir_all.rs b/library/std/src/sys/fs/windows/remove_dir_all.rs
index f51eced..b213c49 100644
--- a/library/std/src/sys/fs/windows/remove_dir_all.rs
+++ b/library/std/src/sys/fs/windows/remove_dir_all.rs
@@ -95,7 +95,7 @@ fn open_link_no_reparse(
ObjectName: &mut path_str,
RootDirectory: parent.as_raw_handle(),
Attributes: ATTRIBUTES.load(Ordering::Relaxed),
- ..c::OBJECT_ATTRIBUTES::default()
+ ..c::OBJECT_ATTRIBUTES::with_length()
};
let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE;
let options = c::FILE_OPEN_REPARSE_POINT | options;
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index f8f220f..bc4bf11 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -9,6 +9,7 @@
mod personality;
pub mod anonymous_pipe;
+pub mod args;
pub mod backtrace;
pub mod cmath;
pub mod exit_guard;
diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs
index bbe1e03..b35d5d2 100644
--- a/library/std/src/sys/net/connection/socket/unix.rs
+++ b/library/std/src/sys/net/connection/socket/unix.rs
@@ -1,5 +1,6 @@
use libc::{MSG_PEEK, c_int, c_void, size_t, sockaddr, socklen_t};
+#[cfg(not(any(target_os = "espidf", target_os = "nuttx")))]
use crate::ffi::CStr;
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Shutdown, SocketAddr};
diff --git a/library/std/src/sys/pal/hermit/args.rs b/library/std/src/sys/pal/hermit/args.rs
deleted file mode 100644
index 4402426..0000000
--- a/library/std/src/sys/pal/hermit/args.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-use crate::ffi::{CStr, OsString, c_char};
-use crate::os::hermit::ffi::OsStringExt;
-use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicIsize, AtomicPtr};
-use crate::{fmt, ptr, vec};
-
-static ARGC: AtomicIsize = AtomicIsize::new(0);
-static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
-
-/// One-time global initialization.
-pub unsafe fn init(argc: isize, argv: *const *const u8) {
- ARGC.store(argc, Relaxed);
- // Use release ordering here to broadcast writes by the OS.
- ARGV.store(argv as *mut *const u8, Release);
-}
-
-/// Returns the command line arguments
-pub fn args() -> Args {
- // Synchronize with the store above.
- let argv = ARGV.load(Acquire);
- // If argv has not been initialized yet, do not return any arguments.
- let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) };
- let args: Vec<OsString> = (0..argc)
- .map(|i| unsafe {
- let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char);
- OsStringExt::from_vec(cstr.to_bytes().to_vec())
- })
- .collect();
-
- Args { iter: args.into_iter() }
-}
-
-pub struct Args {
- iter: vec::IntoIter<OsString>,
-}
-
-impl fmt::Debug for Args {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.iter.as_slice().fmt(f)
- }
-}
-
-impl !Send for Args {}
-impl !Sync for Args {}
-
-impl Iterator for Args {
- type Item = OsString;
- fn next(&mut self) -> Option<OsString> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl ExactSizeIterator for Args {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl DoubleEndedIterator for Args {
- fn next_back(&mut self) -> Option<OsString> {
- self.iter.next_back()
- }
-}
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index 26211bc..8218368 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -18,7 +18,6 @@
use crate::os::raw::c_char;
-pub mod args;
pub mod env;
pub mod futex;
pub mod os;
@@ -58,7 +57,7 @@ pub extern "C" fn __rust_abort() {
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
unsafe {
- args::init(argc, argv);
+ crate::sys::args::init(argc, argv);
}
}
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 52684e1..8a87e7a 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -9,7 +9,6 @@
use crate::sync::atomic::{AtomicBool, Ordering};
pub mod abi;
-pub mod args;
pub mod env;
mod libunwind_integration;
pub mod os;
@@ -24,7 +23,7 @@
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
unsafe {
- args::init(argc, argv);
+ crate::sys::args::init(argc, argv);
}
}
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index 22052a1..c41dc84 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -16,8 +16,6 @@ pub mod itron {
use super::unsupported;
}
-#[path = "../unsupported/args.rs"]
-pub mod args;
pub mod env;
// `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as
// `crate::sys::error`
diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs
index c1921a2..b8095ce 100644
--- a/library/std/src/sys/pal/teeos/mod.rs
+++ b/library/std/src/sys/pal/teeos/mod.rs
@@ -6,8 +6,6 @@
#![allow(unused_variables)]
#![allow(dead_code)]
-#[path = "../unsupported/args.rs"]
-pub mod args;
#[path = "../unsupported/env.rs"]
pub mod env;
//pub mod fd;
diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs
index 5295d3f..04e6b4c 100644
--- a/library/std/src/sys/pal/trusty/mod.rs
+++ b/library/std/src/sys/pal/trusty/mod.rs
@@ -1,7 +1,5 @@
//! System bindings for the Trusty OS.
-#[path = "../unsupported/args.rs"]
-pub mod args;
#[path = "../unsupported/common.rs"]
#[deny(unsafe_op_in_unsafe_fn)]
mod common;
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index 9760a23..cd901f4 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -13,7 +13,6 @@
//! [`OsString`]: crate::ffi::OsString
#![forbid(unsafe_op_in_unsafe_fn)]
-pub mod args;
pub mod env;
pub mod helpers;
pub mod os;
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index d7106c3..3a790d9 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -6,7 +6,6 @@
#[macro_use]
pub mod weak;
-pub mod args;
pub mod env;
#[cfg(target_os = "fuchsia")]
pub mod fuchsia;
@@ -27,6 +26,7 @@
pub fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
#[cfg(not(target_os = "espidf"))]
+#[cfg_attr(target_os = "vita", allow(unused_variables))]
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
// See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`.
@@ -47,7 +47,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
reset_sigpipe(sigpipe);
stack_overflow::init();
- args::init(argc, argv);
+ #[cfg(not(target_os = "vita"))]
+ crate::sys::args::init(argc, argv);
// Normally, `thread::spawn` will call `Thread::set_name` but since this thread
// already exists, we have to call it ourselves. We only do this on Apple targets
@@ -273,6 +274,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
libc::ETXTBSY => ExecutableFileBusy,
libc::EXDEV => CrossesDevices,
libc::EINPROGRESS => InProgress,
+ libc::EOPNOTSUPP => Unsupported,
libc::EACCES | libc::EPERM => PermissionDenied,
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 9078dd1..4cdc2ea 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -8,14 +8,19 @@
use crate::sys::{os, stack_overflow};
use crate::time::Duration;
use crate::{cmp, io, ptr};
-#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
+#[cfg(not(any(
+ target_os = "l4re",
+ target_os = "vxworks",
+ target_os = "espidf",
+ target_os = "nuttx"
+)))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
#[cfg(target_os = "l4re")]
pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024;
#[cfg(target_os = "vxworks")]
pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024;
-#[cfg(target_os = "espidf")]
-pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF menuconfig system should be used
+#[cfg(any(target_os = "espidf", target_os = "nuttx"))]
+pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF/NuttX menuconfig system should be used
#[cfg(target_os = "fuchsia")]
mod zircon {
@@ -52,10 +57,10 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
let mut attr: mem::MaybeUninit<libc::pthread_attr_t> = mem::MaybeUninit::uninit();
assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0);
- #[cfg(target_os = "espidf")]
+ #[cfg(any(target_os = "espidf", target_os = "nuttx"))]
if stack > 0 {
// Only set the stack if a non-zero value is passed
- // 0 is used as an indication that the default stack size configured in the ESP-IDF menuconfig system should be used
+ // 0 is used as an indication that the default stack size configured in the ESP-IDF/NuttX menuconfig system should be used
assert_eq!(
libc::pthread_attr_setstacksize(
attr.as_mut_ptr(),
@@ -65,7 +70,7 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
);
}
- #[cfg(not(target_os = "espidf"))]
+ #[cfg(not(any(target_os = "espidf", target_os = "nuttx")))]
{
let stack_size = cmp::max(stack, min_stack_size(attr.as_ptr()));
@@ -189,9 +194,6 @@ pub fn set_name(name: &CStr) {
}
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
- // FIXME(#115199): Rust currently omits weak function definitions
- // and its metadata from LLVM IR.
- #[no_sanitize(cfi)]
pub fn set_name(name: &CStr) {
weak!(
fn pthread_setname_np(
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index b8469b1..0074d76 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -96,17 +96,6 @@ const fn new(tv_sec: i64, tv_nsec: i64) -> Result<Timespec, io::Error> {
}
}
- // FIXME(#115199): Rust currently omits weak function definitions
- // and its metadata from LLVM IR.
- #[cfg_attr(
- all(
- target_os = "linux",
- target_env = "gnu",
- target_pointer_width = "32",
- not(target_arch = "riscv32")
- ),
- no_sanitize(cfi)
- )]
pub fn now(clock: libc::clockid_t) -> Timespec {
use crate::mem::MaybeUninit;
use crate::sys::cvt;
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index e4c814f..a034995 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -155,9 +155,6 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void {
#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub(crate) macro syscall {
(fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
- // FIXME(#115199): Rust currently omits weak function definitions
- // and its metadata from LLVM IR.
- #[no_sanitize(cfi)]
unsafe fn $name($($param: $t),*) -> $ret {
weak!(fn $name($($param: $t),*) -> $ret;);
diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs
index 38838b9..dea42a9 100644
--- a/library/std/src/sys/pal/unsupported/mod.rs
+++ b/library/std/src/sys/pal/unsupported/mod.rs
@@ -1,6 +1,5 @@
#![deny(unsafe_op_in_unsafe_fn)]
-pub mod args;
pub mod env;
pub mod os;
pub mod pipe;
diff --git a/library/std/src/sys/pal/wasi/args.rs b/library/std/src/sys/pal/wasi/args.rs
deleted file mode 100644
index 52cfa20..0000000
--- a/library/std/src/sys/pal/wasi/args.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-#![forbid(unsafe_op_in_unsafe_fn)]
-
-use crate::ffi::{CStr, OsStr, OsString};
-use crate::os::wasi::ffi::OsStrExt;
-use crate::{fmt, vec};
-
-pub struct Args {
- iter: vec::IntoIter<OsString>,
-}
-
-impl !Send for Args {}
-impl !Sync for Args {}
-
-/// Returns the command line arguments
-pub fn args() -> Args {
- Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() }
-}
-
-fn maybe_args() -> Option<Vec<OsString>> {
- unsafe {
- let (argc, buf_size) = wasi::args_sizes_get().ok()?;
- let mut argv = Vec::with_capacity(argc);
- let mut buf = Vec::with_capacity(buf_size);
- wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
- argv.set_len(argc);
- let mut ret = Vec::with_capacity(argc);
- for ptr in argv {
- let s = CStr::from_ptr(ptr.cast());
- ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
- }
- Some(ret)
- }
-}
-
-impl fmt::Debug for Args {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.iter.as_slice().fmt(f)
- }
-}
-
-impl Iterator for Args {
- type Item = OsString;
- fn next(&mut self) -> Option<OsString> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl ExactSizeIterator for Args {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl DoubleEndedIterator for Args {
- fn next_back(&mut self) -> Option<OsString> {
- self.iter.next_back()
- }
-}
diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs
index 80853e7..4ea42b1 100644
--- a/library/std/src/sys/pal/wasi/mod.rs
+++ b/library/std/src/sys/pal/wasi/mod.rs
@@ -13,7 +13,6 @@
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!
-pub mod args;
pub mod env;
#[allow(unused)]
#[path = "../wasm/atomics/futex.rs"]
diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs
index 504b947..6445bf2 100644
--- a/library/std/src/sys/pal/wasip2/mod.rs
+++ b/library/std/src/sys/pal/wasip2/mod.rs
@@ -6,8 +6,6 @@
//! To begin with, this target mirrors the wasi target 1 to 1, but over
//! time this will change significantly.
-#[path = "../wasi/args.rs"]
-pub mod args;
#[path = "../wasi/env.rs"]
pub mod env;
#[allow(unused)]
diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs
index 8d39b70..af37002 100644
--- a/library/std/src/sys/pal/wasm/mod.rs
+++ b/library/std/src/sys/pal/wasm/mod.rs
@@ -16,8 +16,6 @@
#![deny(unsafe_op_in_unsafe_fn)]
-#[path = "../unsupported/args.rs"]
-pub mod args;
pub mod env;
#[path = "../unsupported/os.rs"]
pub mod os;
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index 004cbee..ac1c5e9 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -44,8 +44,8 @@ pub fn from_ref(slice: &[u16]) -> Self {
}
}
-impl Default for OBJECT_ATTRIBUTES {
- fn default() -> Self {
+impl OBJECT_ATTRIBUTES {
+ pub fn with_length() -> Self {
Self {
Length: size_of::<Self>() as _,
RootDirectory: ptr::null_mut(),
diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt
index e2c2163..d5fbb45 100644
--- a/library/std/src/sys/pal/windows/c/bindings.txt
+++ b/library/std/src/sys/pal/windows/c/bindings.txt
@@ -1,7 +1,8 @@
--out windows_sys.rs
--flat
--sys
---no-core
+--no-deps
+--link windows_targets
--filter
!INVALID_HANDLE_VALUE
ABOVE_NORMAL_PRIORITY_CLASS
@@ -19,7 +20,6 @@
ARM64_NT_NEON128
BELOW_NORMAL_PRIORITY_CLASS
bind
-BOOL
BY_HANDLE_FILE_INFORMATION
CALLBACK_CHUNK_FINISHED
CALLBACK_STREAM_SWITCH
diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs
index 1d0e89f..eb2914b 100644
--- a/library/std/src/sys/pal/windows/c/windows_sys.rs
+++ b/library/std/src/sys/pal/windows/c/windows_sys.rs
@@ -1,4 +1,4 @@
-// Bindings generated by `windows-bindgen` 0.59.0
+// Bindings generated by `windows-bindgen` 0.61.0
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
@@ -141,7 +141,7 @@
windows_targets::link!("ws2_32.dll" "system" fn shutdown(s : SOCKET, how : WINSOCK_SHUTDOWN_HOW) -> i32);
pub const ABOVE_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32768u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct ACL {
pub AclRevision: u8,
pub Sbz1: u8,
@@ -162,6 +162,11 @@ pub struct ADDRINFOA {
pub ai_addr: *mut SOCKADDR,
pub ai_next: *mut ADDRINFOA,
}
+impl Default for ADDRINFOA {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const AF_INET: ADDRESS_FAMILY = 2u16;
pub const AF_INET6: ADDRESS_FAMILY = 23u16;
pub const AF_UNIX: u16 = 1u16;
@@ -176,8 +181,13 @@ pub union ARM64_NT_NEON128 {
pub H: [u16; 8],
pub B: [u8; 16],
}
+impl Default for ARM64_NT_NEON128 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct ARM64_NT_NEON128_0 {
pub Low: u64,
pub High: i64,
@@ -185,7 +195,7 @@ pub struct ARM64_NT_NEON128_0 {
pub const BELOW_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 16384u32;
pub type BOOL = i32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct BY_HANDLE_FILE_INFORMATION {
pub dwFileAttributes: u32,
pub ftCreationTime: FILETIME,
@@ -206,9 +216,14 @@ pub struct BY_HANDLE_FILE_INFORMATION {
pub struct CONDITION_VARIABLE {
pub Ptr: *mut core::ffi::c_void,
}
+impl Default for CONDITION_VARIABLE {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type CONSOLE_MODE = u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct CONSOLE_READCONSOLE_CONTROL {
pub nLength: u32,
pub nInitialChars: u32,
@@ -245,6 +260,12 @@ pub struct CONTEXT {
pub SegSs: u32,
pub ExtendedRegisters: [u8; 512],
}
+#[cfg(target_arch = "x86")]
+impl Default for CONTEXT {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
@@ -296,6 +317,12 @@ pub struct CONTEXT {
pub LastExceptionToRip: u64,
pub LastExceptionFromRip: u64,
}
+#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
+impl Default for CONTEXT {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
@@ -303,6 +330,12 @@ pub union CONTEXT_0 {
pub FltSave: XSAVE_FORMAT,
pub Anonymous: CONTEXT_0_0,
}
+#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
+impl Default for CONTEXT_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
@@ -326,6 +359,12 @@ pub struct CONTEXT_0_0 {
pub Xmm14: M128A,
pub Xmm15: M128A,
}
+#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
+impl Default for CONTEXT_0_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
@@ -343,6 +382,12 @@ pub struct CONTEXT {
pub Wcr: [u32; 2],
pub Wvr: [u64; 2],
}
+#[cfg(target_arch = "aarch64")]
+impl Default for CONTEXT {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
@@ -350,9 +395,15 @@ pub union CONTEXT_0 {
pub Anonymous: CONTEXT_0_0,
pub X: [u64; 31],
}
+#[cfg(target_arch = "aarch64")]
+impl Default for CONTEXT_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct CONTEXT_0_0 {
pub X0: u64,
pub X1: u64,
@@ -2305,6 +2356,11 @@ pub struct EXCEPTION_POINTERS {
pub ExceptionRecord: *mut EXCEPTION_RECORD,
pub ContextRecord: *mut CONTEXT,
}
+impl Default for EXCEPTION_POINTERS {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct EXCEPTION_RECORD {
@@ -2315,6 +2371,11 @@ pub struct EXCEPTION_RECORD {
pub NumberParameters: u32,
pub ExceptionInformation: [usize; 15],
}
+impl Default for EXCEPTION_RECORD {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _;
pub const EXTENDED_STARTUPINFO_PRESENT: PROCESS_CREATION_FLAGS = 524288u32;
pub const E_NOTIMPL: HRESULT = 0x80004001_u32 as _;
@@ -2333,8 +2394,13 @@ pub struct FD_SET {
pub fd_count: u32,
pub fd_array: [SOCKET; 64],
}
+impl Default for FD_SET {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILETIME {
pub dwLowDateTime: u32,
pub dwHighDateTime: u32,
@@ -2343,7 +2409,7 @@ pub struct FILETIME {
pub const FILE_ADD_FILE: FILE_ACCESS_RIGHTS = 2u32;
pub const FILE_ADD_SUBDIRECTORY: FILE_ACCESS_RIGHTS = 4u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_ALLOCATION_INFO {
pub AllocationSize: i64,
}
@@ -2369,7 +2435,7 @@ pub struct FILE_ALLOCATION_INFO {
pub const FILE_ATTRIBUTE_SPARSE_FILE: FILE_FLAGS_AND_ATTRIBUTES = 512u32;
pub const FILE_ATTRIBUTE_SYSTEM: FILE_FLAGS_AND_ATTRIBUTES = 4u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_ATTRIBUTE_TAG_INFO {
pub FileAttributes: u32,
pub ReparseTag: u32,
@@ -2378,7 +2444,7 @@ pub struct FILE_ATTRIBUTE_TAG_INFO {
pub const FILE_ATTRIBUTE_UNPINNED: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32;
pub const FILE_ATTRIBUTE_VIRTUAL: FILE_FLAGS_AND_ATTRIBUTES = 65536u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_BASIC_INFO {
pub CreationTime: i64,
pub LastAccessTime: i64,
@@ -2405,19 +2471,19 @@ pub struct FILE_BASIC_INFO {
pub const FILE_DISPOSITION_FLAG_ON_CLOSE: FILE_DISPOSITION_INFO_EX_FLAGS = 8u32;
pub const FILE_DISPOSITION_FLAG_POSIX_SEMANTICS: FILE_DISPOSITION_INFO_EX_FLAGS = 2u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_DISPOSITION_INFO {
pub DeleteFile: bool,
}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_DISPOSITION_INFO_EX {
pub Flags: FILE_DISPOSITION_INFO_EX_FLAGS,
}
pub type FILE_DISPOSITION_INFO_EX_FLAGS = u32;
pub const FILE_END: SET_FILE_POINTER_MOVE_METHOD = 2u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_END_OF_FILE_INFO {
pub EndOfFile: i64,
}
@@ -2457,9 +2523,14 @@ pub struct FILE_ID_BOTH_DIR_INFO {
pub FileId: i64,
pub FileName: [u16; 1],
}
+impl Default for FILE_ID_BOTH_DIR_INFO {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type FILE_INFO_BY_HANDLE_CLASS = i32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_IO_PRIORITY_HINT_INFO {
pub PriorityHint: PRIORITY_HINT,
}
@@ -2494,12 +2565,22 @@ pub struct FILE_RENAME_INFO {
pub FileNameLength: u32,
pub FileName: [u16; 1],
}
+impl Default for FILE_RENAME_INFO {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub union FILE_RENAME_INFO_0 {
pub ReplaceIfExists: bool,
pub Flags: u32,
}
+impl Default for FILE_RENAME_INFO_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32;
pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32;
pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32;
@@ -2509,7 +2590,7 @@ pub union FILE_RENAME_INFO_0 {
pub const FILE_SHARE_READ: FILE_SHARE_MODE = 1u32;
pub const FILE_SHARE_WRITE: FILE_SHARE_MODE = 2u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct FILE_STANDARD_INFO {
pub AllocationSize: i64,
pub EndOfFile: i64,
@@ -2549,6 +2630,12 @@ pub struct FLOATING_SAVE_AREA {
pub RegisterArea: [u8; 80],
pub Spare0: u32,
}
+#[cfg(target_arch = "x86")]
+impl Default for FLOATING_SAVE_AREA {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
@@ -2563,6 +2650,12 @@ pub struct FLOATING_SAVE_AREA {
pub RegisterArea: [u8; 80],
pub Cr0NpxState: u32,
}
+#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
+impl Default for FLOATING_SAVE_AREA {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const FORMAT_MESSAGE_ALLOCATE_BUFFER: FORMAT_MESSAGE_OPTIONS = 256u32;
pub const FORMAT_MESSAGE_ARGUMENT_ARRAY: FORMAT_MESSAGE_OPTIONS = 8192u32;
pub const FORMAT_MESSAGE_FROM_HMODULE: FORMAT_MESSAGE_OPTIONS = 2048u32;
@@ -2639,12 +2732,22 @@ pub const fn from_u128(uuid: u128) -> Self {
pub struct IN6_ADDR {
pub u: IN6_ADDR_0,
}
+impl Default for IN6_ADDR {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub union IN6_ADDR_0 {
pub Byte: [u8; 16],
pub Word: [u16; 8],
}
+impl Default for IN6_ADDR_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const INFINITE: u32 = 4294967295u32;
pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32;
pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32;
@@ -2653,6 +2756,11 @@ pub union IN6_ADDR_0 {
pub union INIT_ONCE {
pub Ptr: *mut core::ffi::c_void,
}
+impl Default for INIT_ONCE {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const INIT_ONCE_INIT_FAILED: u32 = 4u32;
pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32;
pub const INVALID_SOCKET: SOCKET = -1i32 as _;
@@ -2661,6 +2769,11 @@ pub union INIT_ONCE {
pub struct IN_ADDR {
pub S_un: IN_ADDR_0,
}
+impl Default for IN_ADDR {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub union IN_ADDR_0 {
@@ -2668,8 +2781,13 @@ pub union IN_ADDR_0 {
pub S_un_w: IN_ADDR_0_1,
pub S_addr: u32,
}
+impl Default for IN_ADDR_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct IN_ADDR_0_0 {
pub s_b1: u8,
pub s_b2: u8,
@@ -2677,7 +2795,7 @@ pub struct IN_ADDR_0_0 {
pub s_b4: u8,
}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct IN_ADDR_0_1 {
pub s_w1: u16,
pub s_w2: u16,
@@ -2690,12 +2808,22 @@ pub struct IO_STATUS_BLOCK {
pub Anonymous: IO_STATUS_BLOCK_0,
pub Information: usize,
}
+impl Default for IO_STATUS_BLOCK {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub union IO_STATUS_BLOCK_0 {
pub Status: NTSTATUS,
pub Pointer: *mut core::ffi::c_void,
}
+impl Default for IO_STATUS_BLOCK_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type IPPROTO = i32;
pub const IPPROTO_AH: IPPROTO = 51i32;
pub const IPPROTO_CBT: IPPROTO = 7i32;
@@ -2742,6 +2870,11 @@ pub struct IPV6_MREQ {
pub ipv6mr_multiaddr: IN6_ADDR,
pub ipv6mr_interface: u32,
}
+impl Default for IPV6_MREQ {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const IPV6_MULTICAST_LOOP: i32 = 11i32;
pub const IPV6_V6ONLY: i32 = 27i32;
pub const IP_ADD_MEMBERSHIP: i32 = 12i32;
@@ -2752,11 +2885,16 @@ pub struct IP_MREQ {
pub imr_multiaddr: IN_ADDR,
pub imr_interface: IN_ADDR,
}
+impl Default for IP_MREQ {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const IP_MULTICAST_LOOP: i32 = 11i32;
pub const IP_MULTICAST_TTL: i32 = 10i32;
pub const IP_TTL: i32 = 4i32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct LINGER {
pub l_onoff: u16,
pub l_linger: u16,
@@ -2797,7 +2935,7 @@ pub struct LINGER {
),
>;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct M128A {
pub Low: u64,
pub High: i64,
@@ -2838,6 +2976,11 @@ pub struct OBJECT_ATTRIBUTES {
pub SecurityDescriptor: *const SECURITY_DESCRIPTOR,
pub SecurityQualityOfService: *const SECURITY_QUALITY_OF_SERVICE,
}
+impl Default for OBJECT_ATTRIBUTES {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type OBJECT_ATTRIBUTE_FLAGS = u32;
pub const OBJ_DONT_REPARSE: OBJECT_ATTRIBUTE_FLAGS = 4096u32;
pub const OPEN_ALWAYS: FILE_CREATION_DISPOSITION = 4u32;
@@ -2850,14 +2993,24 @@ pub struct OVERLAPPED {
pub Anonymous: OVERLAPPED_0,
pub hEvent: HANDLE,
}
+impl Default for OVERLAPPED {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub union OVERLAPPED_0 {
pub Anonymous: OVERLAPPED_0_0,
pub Pointer: *mut core::ffi::c_void,
}
+impl Default for OVERLAPPED_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct OVERLAPPED_0_0 {
pub Offset: u32,
pub OffsetHigh: u32,
@@ -2895,6 +3048,11 @@ pub struct PROCESS_INFORMATION {
pub dwProcessId: u32,
pub dwThreadId: u32,
}
+impl Default for PROCESS_INFORMATION {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const PROCESS_MODE_BACKGROUND_BEGIN: PROCESS_CREATION_FLAGS = 1048576u32;
pub const PROCESS_MODE_BACKGROUND_END: PROCESS_CREATION_FLAGS = 2097152u32;
pub const PROFILE_KERNEL: PROCESS_CREATION_FLAGS = 536870912u32;
@@ -2926,6 +3084,11 @@ pub struct SECURITY_ATTRIBUTES {
pub lpSecurityDescriptor: *mut core::ffi::c_void,
pub bInheritHandle: BOOL,
}
+impl Default for SECURITY_ATTRIBUTES {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const SECURITY_CONTEXT_TRACKING: FILE_FLAGS_AND_ATTRIBUTES = 262144u32;
pub const SECURITY_DELEGATION: FILE_FLAGS_AND_ATTRIBUTES = 196608u32;
#[repr(C)]
@@ -2939,13 +3102,18 @@ pub struct SECURITY_DESCRIPTOR {
pub Sacl: *mut ACL,
pub Dacl: *mut ACL,
}
+impl Default for SECURITY_DESCRIPTOR {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type SECURITY_DESCRIPTOR_CONTROL = u16;
pub const SECURITY_EFFECTIVE_ONLY: FILE_FLAGS_AND_ATTRIBUTES = 524288u32;
pub const SECURITY_IDENTIFICATION: FILE_FLAGS_AND_ATTRIBUTES = 65536u32;
pub const SECURITY_IMPERSONATION: FILE_FLAGS_AND_ATTRIBUTES = 131072u32;
pub type SECURITY_IMPERSONATION_LEVEL = i32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct SECURITY_QUALITY_OF_SERVICE {
pub Length: u32,
pub ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL,
@@ -2962,6 +3130,11 @@ pub struct SOCKADDR {
pub sa_family: ADDRESS_FAMILY,
pub sa_data: [i8; 14],
}
+impl Default for SOCKADDR {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SOCKADDR_STORAGE {
@@ -2970,12 +3143,22 @@ pub struct SOCKADDR_STORAGE {
pub __ss_align: i64,
pub __ss_pad2: [i8; 112],
}
+impl Default for SOCKADDR_STORAGE {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SOCKADDR_UN {
pub sun_family: ADDRESS_FAMILY,
pub sun_path: [i8; 108],
}
+impl Default for SOCKADDR_UN {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type SOCKET = usize;
pub const SOCKET_ERROR: i32 = -1i32;
pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32;
@@ -2995,6 +3178,11 @@ pub struct SOCKADDR_UN {
pub struct SRWLOCK {
pub Ptr: *mut core::ffi::c_void,
}
+impl Default for SRWLOCK {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32;
pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32;
pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32;
@@ -3021,6 +3209,11 @@ pub struct STARTUPINFOEXW {
pub StartupInfo: STARTUPINFOW,
pub lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST,
}
+impl Default for STARTUPINFOEXW {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct STARTUPINFOW {
@@ -3043,6 +3236,11 @@ pub struct STARTUPINFOW {
pub hStdOutput: HANDLE,
pub hStdError: HANDLE,
}
+impl Default for STARTUPINFOW {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type STARTUPINFOW_FLAGS = u32;
pub const STATUS_DELETE_PENDING: NTSTATUS = 0xC0000056_u32 as _;
pub const STATUS_DIRECTORY_NOT_EMPTY: NTSTATUS = 0xC0000101_u32 as _;
@@ -3078,14 +3276,24 @@ pub struct SYSTEM_INFO {
pub wProcessorLevel: u16,
pub wProcessorRevision: u16,
}
+impl Default for SYSTEM_INFO {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub union SYSTEM_INFO_0 {
pub dwOemId: u32,
pub Anonymous: SYSTEM_INFO_0_0,
}
+impl Default for SYSTEM_INFO_0 {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct SYSTEM_INFO_0_0 {
pub wProcessorArchitecture: PROCESSOR_ARCHITECTURE,
pub wReserved: u16,
@@ -3097,7 +3305,7 @@ pub struct SYSTEM_INFO_0_0 {
pub const TIMER_ALL_ACCESS: SYNCHRONIZATION_ACCESS_RIGHTS = 2031619u32;
pub const TIMER_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32;
#[repr(C)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default)]
pub struct TIMEVAL {
pub tv_sec: i32,
pub tv_usec: i32,
@@ -3134,6 +3342,11 @@ pub struct UNICODE_STRING {
pub MaximumLength: u16,
pub Buffer: PWSTR,
}
+impl Default for UNICODE_STRING {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32;
pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32;
pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32;
@@ -3160,6 +3373,11 @@ pub struct WIN32_FIND_DATAW {
pub cFileName: [u16; 260],
pub cAlternateFileName: [u16; 14],
}
+impl Default for WIN32_FIND_DATAW {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub type WINSOCK_SHUTDOWN_HOW = i32;
pub type WINSOCK_SOCKET_TYPE = i32;
pub const WRITE_DAC: FILE_ACCESS_RIGHTS = 262144u32;
@@ -3171,6 +3389,11 @@ pub struct WSABUF {
pub len: u32,
pub buf: PSTR,
}
+impl Default for WSABUF {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(target_arch = "x86")]
#[derive(Clone, Copy)]
@@ -3183,6 +3406,12 @@ pub struct WSADATA {
pub iMaxUdpDg: u16,
pub lpVendorInfo: PSTR,
}
+#[cfg(target_arch = "x86")]
+impl Default for WSADATA {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
@@ -3195,6 +3424,12 @@ pub struct WSADATA {
pub szDescription: [i8; 257],
pub szSystemStatus: [i8; 129],
}
+#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
+impl Default for WSADATA {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const WSAEACCES: WSA_ERROR = 10013i32;
pub const WSAEADDRINUSE: WSA_ERROR = 10048i32;
pub const WSAEADDRNOTAVAIL: WSA_ERROR = 10049i32;
@@ -3255,6 +3490,11 @@ pub struct WSAPROTOCOLCHAIN {
pub ChainLen: i32,
pub ChainEntries: [u32; 7],
}
+impl Default for WSAPROTOCOLCHAIN {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct WSAPROTOCOL_INFOW {
@@ -3279,6 +3519,11 @@ pub struct WSAPROTOCOL_INFOW {
pub dwProviderReserved: u32,
pub szProtocol: [u16; 256],
}
+impl Default for WSAPROTOCOL_INFOW {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
pub const WSASERVICE_NOT_FOUND: WSA_ERROR = 10108i32;
pub const WSASYSCALLFAILURE: WSA_ERROR = 10107i32;
pub const WSASYSNOTREADY: WSA_ERROR = 10091i32;
@@ -3348,6 +3593,12 @@ pub struct XSAVE_FORMAT {
pub XmmRegisters: [M128A; 8],
pub Reserved4: [u8; 224],
}
+#[cfg(target_arch = "x86")]
+impl Default for XSAVE_FORMAT {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
@@ -3369,6 +3620,12 @@ pub struct XSAVE_FORMAT {
pub XmmRegisters: [M128A; 16],
pub Reserved4: [u8; 96],
}
+#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
+impl Default for XSAVE_FORMAT {
+ fn default() -> Self {
+ unsafe { core::mem::zeroed() }
+ }
+}
#[cfg(target_arch = "arm")]
#[repr(C)]
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index bdf0cc2c..3c0a5c2 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -14,7 +14,6 @@
pub mod api;
-pub mod args;
pub mod c;
pub mod env;
#[cfg(not(target_vendor = "win7"))]
diff --git a/library/std/src/sys/pal/xous/args.rs b/library/std/src/sys/pal/xous/args.rs
deleted file mode 100644
index 00c44ca..0000000
--- a/library/std/src/sys/pal/xous/args.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use crate::ffi::OsString;
-use crate::sys::pal::xous::os::get_application_parameters;
-use crate::sys::pal::xous::os::params::ArgumentList;
-use crate::{fmt, vec};
-
-pub struct Args {
- parsed_args_list: vec::IntoIter<OsString>,
-}
-
-pub fn args() -> Args {
- let Some(params) = get_application_parameters() else {
- return Args { parsed_args_list: vec![].into_iter() };
- };
-
- for param in params {
- if let Ok(args) = ArgumentList::try_from(¶m) {
- let mut parsed_args = vec![];
- for arg in args {
- parsed_args.push(arg.into());
- }
- return Args { parsed_args_list: parsed_args.into_iter() };
- }
- }
- Args { parsed_args_list: vec![].into_iter() }
-}
-
-impl fmt::Debug for Args {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.parsed_args_list.as_slice().fmt(f)
- }
-}
-
-impl Iterator for Args {
- type Item = OsString;
- fn next(&mut self) -> Option<OsString> {
- self.parsed_args_list.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.parsed_args_list.size_hint()
- }
-}
-
-impl DoubleEndedIterator for Args {
- fn next_back(&mut self) -> Option<OsString> {
- self.parsed_args_list.next_back()
- }
-}
-
-impl ExactSizeIterator for Args {
- fn len(&self) -> usize {
- self.parsed_args_list.len()
- }
-}
diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs
index 58926e2..4f652d3 100644
--- a/library/std/src/sys/pal/xous/mod.rs
+++ b/library/std/src/sys/pal/xous/mod.rs
@@ -1,6 +1,5 @@
#![forbid(unsafe_op_in_unsafe_fn)]
-pub mod args;
#[path = "../unsupported/env.rs"]
pub mod env;
pub mod os;
diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs
index 4659dad..ebd7b03 100644
--- a/library/std/src/sys/pal/zkvm/mod.rs
+++ b/library/std/src/sys/pal/zkvm/mod.rs
@@ -8,11 +8,9 @@
//! will likely change over time.
#![forbid(unsafe_op_in_unsafe_fn)]
-const WORD_SIZE: usize = size_of::<u32>();
+pub const WORD_SIZE: usize = size_of::<u32>();
pub mod abi;
-#[path = "../zkvm/args.rs"]
-pub mod args;
pub mod env;
pub mod os;
#[path = "../unsupported/pipe.rs"]
diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs
index 6547ed9..e0e003f 100644
--- a/library/std/src/sys/path/windows.rs
+++ b/library/std/src/sys/path/windows.rs
@@ -10,6 +10,40 @@
pub const MAIN_SEP_STR: &str = "\\";
pub const MAIN_SEP: char = '\\';
+/// A null terminated wide string.
+#[repr(transparent)]
+pub struct WCStr([u16]);
+
+impl WCStr {
+ /// Convert a slice to a WCStr without checks.
+ ///
+ /// Though it is memory safe, the slice should also not contain interior nulls
+ /// as this may lead to unwanted truncation.
+ ///
+ /// # Safety
+ ///
+ /// The slice must end in a null.
+ pub unsafe fn from_wchars_with_null_unchecked(s: &[u16]) -> &Self {
+ unsafe { &*(s as *const [u16] as *const Self) }
+ }
+
+ pub fn as_ptr(&self) -> *const u16 {
+ self.0.as_ptr()
+ }
+
+ pub fn count_bytes(&self) -> usize {
+ self.0.len()
+ }
+}
+
+#[inline]
+pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&WCStr) -> io::Result<T>) -> io::Result<T> {
+ let path = maybe_verbatim(path)?;
+ // SAFETY: maybe_verbatim returns null-terminated strings
+ let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) };
+ f(path)
+}
+
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/' || b == b'\\'
diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs
index b46418a..5f92229 100644
--- a/library/std/src/sys/process/uefi.rs
+++ b/library/std/src/sys/process/uefi.rs
@@ -1,4 +1,4 @@
-use r_efi::protocols::simple_text_output;
+use r_efi::protocols::{simple_text_input, simple_text_output};
use crate::collections::BTreeMap;
pub use crate::ffi::OsString as EnvKey;
@@ -23,6 +23,7 @@ pub struct Command {
args: Vec<OsString>,
stdout: Option<Stdio>,
stderr: Option<Stdio>,
+ stdin: Option<Stdio>,
env: CommandEnv,
}
@@ -48,6 +49,7 @@ pub fn new(program: &OsStr) -> Command {
args: Vec::new(),
stdout: None,
stderr: None,
+ stdin: None,
env: Default::default(),
}
}
@@ -64,8 +66,8 @@ pub fn cwd(&mut self, _dir: &OsStr) {
panic!("unsupported")
}
- pub fn stdin(&mut self, _stdin: Stdio) {
- panic!("unsupported")
+ pub fn stdin(&mut self, stdin: Stdio) {
+ self.stdin = Some(stdin);
}
pub fn stdout(&mut self, stdout: Stdio) {
@@ -122,6 +124,22 @@ fn create_pipe(
}
}
+ fn create_stdin(
+ s: Stdio,
+ ) -> io::Result<Option<helpers::OwnedProtocol<uefi_command_internal::InputProtocol>>> {
+ match s {
+ Stdio::Null => unsafe {
+ helpers::OwnedProtocol::create(
+ uefi_command_internal::InputProtocol::null(),
+ simple_text_input::PROTOCOL_GUID,
+ )
+ }
+ .map(Some),
+ Stdio::Inherit => Ok(None),
+ Stdio::MakePipe => unsupported(),
+ }
+ }
+
pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?;
@@ -149,6 +167,15 @@ pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
cmd.stderr_inherit()
};
+ // Setup Stdin
+ let stdin = self.stdin.unwrap_or(Stdio::Null);
+ let stdin = Self::create_stdin(stdin)?;
+ if let Some(con) = stdin {
+ cmd.stdin_init(con)
+ } else {
+ cmd.stdin_inherit()
+ };
+
let env = env_changes(&self.env);
// Set any new vars
@@ -334,7 +361,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[allow(dead_code)]
mod uefi_command_internal {
- use r_efi::protocols::{loaded_image, simple_text_output};
+ use r_efi::protocols::{loaded_image, simple_text_input, simple_text_output};
use crate::ffi::{OsStr, OsString};
use crate::io::{self, const_error};
@@ -350,6 +377,7 @@ pub struct Image {
handle: NonNull<crate::ffi::c_void>,
stdout: Option<helpers::OwnedProtocol<PipeProtocol>>,
stderr: Option<helpers::OwnedProtocol<PipeProtocol>>,
+ stdin: Option<helpers::OwnedProtocol<InputProtocol>>,
st: OwnedTable<r_efi::efi::SystemTable>,
args: Option<(*mut u16, usize)>,
}
@@ -384,7 +412,14 @@ pub fn load_image(p: &OsStr) -> io::Result<Self> {
helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap();
let st = OwnedTable::from_table(unsafe { (*loaded_image.as_ptr()).system_table });
- Ok(Self { handle: child_handle, stdout: None, stderr: None, st, args: None })
+ Ok(Self {
+ handle: child_handle,
+ stdout: None,
+ stderr: None,
+ stdin: None,
+ st,
+ args: None,
+ })
}
}
@@ -445,6 +480,17 @@ fn set_stderr(
}
}
+ fn set_stdin(
+ &mut self,
+ handle: r_efi::efi::Handle,
+ protocol: *mut simple_text_input::Protocol,
+ ) {
+ unsafe {
+ (*self.st.as_mut_ptr()).console_in_handle = handle;
+ (*self.st.as_mut_ptr()).con_in = protocol;
+ }
+ }
+
pub fn stdout_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) {
self.set_stdout(
protocol.handle().as_ptr(),
@@ -471,6 +517,19 @@ pub fn stderr_inherit(&mut self) {
unsafe { self.set_stderr((*st.as_ptr()).standard_error_handle, (*st.as_ptr()).std_err) }
}
+ pub(crate) fn stdin_init(&mut self, protocol: helpers::OwnedProtocol<InputProtocol>) {
+ self.set_stdin(
+ protocol.handle().as_ptr(),
+ protocol.as_ref() as *const InputProtocol as *mut simple_text_input::Protocol,
+ );
+ self.stdin = Some(protocol);
+ }
+
+ pub(crate) fn stdin_inherit(&mut self) {
+ let st: NonNull<r_efi::efi::SystemTable> = system_table().cast();
+ unsafe { self.set_stdin((*st.as_ptr()).console_in_handle, (*st.as_ptr()).con_in) }
+ }
+
pub fn stderr(&self) -> io::Result<Vec<u8>> {
match &self.stderr {
Some(stderr) => stderr.as_ref().utf8(),
@@ -722,6 +781,56 @@ fn drop(&mut self) {
}
}
+ #[repr(C)]
+ pub(crate) struct InputProtocol {
+ reset: simple_text_input::ProtocolReset,
+ read_key_stroke: simple_text_input::ProtocolReadKeyStroke,
+ wait_for_key: r_efi::efi::Event,
+ }
+
+ impl InputProtocol {
+ pub(crate) fn null() -> Self {
+ let evt = helpers::OwnedEvent::new(
+ r_efi::efi::EVT_NOTIFY_WAIT,
+ r_efi::efi::TPL_CALLBACK,
+ Some(Self::empty_notify),
+ None,
+ )
+ .unwrap();
+
+ Self {
+ reset: Self::null_reset,
+ read_key_stroke: Self::null_read_key,
+ wait_for_key: evt.into_raw(),
+ }
+ }
+
+ extern "efiapi" fn null_reset(
+ _: *mut simple_text_input::Protocol,
+ _: r_efi::efi::Boolean,
+ ) -> r_efi::efi::Status {
+ r_efi::efi::Status::SUCCESS
+ }
+
+ extern "efiapi" fn null_read_key(
+ _: *mut simple_text_input::Protocol,
+ _: *mut simple_text_input::InputKey,
+ ) -> r_efi::efi::Status {
+ r_efi::efi::Status::UNSUPPORTED
+ }
+
+ extern "efiapi" fn empty_notify(_: r_efi::efi::Event, _: *mut crate::ffi::c_void) {}
+ }
+
+ impl Drop for InputProtocol {
+ fn drop(&mut self) {
+ // Close wait_for_key
+ unsafe {
+ let _ = helpers::OwnedEvent::from_raw(self.wait_for_key);
+ }
+ }
+ }
+
pub fn create_args(prog: &OsStr, args: &[OsString]) -> Box<[u16]> {
const QUOTE: u16 = 0x0022;
const SPACE: u16 = 0x0020;
diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs
index 191a09c..3b04ec5 100644
--- a/library/std/src/sys/process/unix/unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -434,9 +434,6 @@ fn posix_spawn(
target_os = "nto",
target_vendor = "apple",
))]
- // FIXME(#115199): Rust currently omits weak function definitions
- // and its metadata from LLVM IR.
- #[cfg_attr(target_os = "linux", no_sanitize(cfi))]
fn posix_spawn(
&mut self,
stdio: &ChildPipes,
diff --git a/library/std/src/sys/stdio/uefi.rs b/library/std/src/sys/stdio/uefi.rs
index 257e321..ccd6bf6 100644
--- a/library/std/src/sys/stdio/uefi.rs
+++ b/library/std/src/sys/stdio/uefi.rs
@@ -142,8 +142,12 @@ fn flush(&mut self) -> io::Result<()> {
// UTF-16 character should occupy 4 bytes at most in UTF-8
pub const STDIN_BUF_SIZE: usize = 4;
-pub fn is_ebadf(_err: &io::Error) -> bool {
- false
+pub fn is_ebadf(err: &io::Error) -> bool {
+ if let Some(x) = err.raw_os_error() {
+ r_efi::efi::Status::UNSUPPORTED.as_usize() == x
+ } else {
+ false
+ }
}
pub fn panic_output() -> Option<impl io::Write> {
diff --git a/library/std/src/sys/thread_local/destructors/linux_like.rs b/library/std/src/sys/thread_local/destructors/linux_like.rs
index 8179412..d7cbaeb 100644
--- a/library/std/src/sys/thread_local/destructors/linux_like.rs
+++ b/library/std/src/sys/thread_local/destructors/linux_like.rs
@@ -12,9 +12,6 @@
use crate::mem::transmute;
-// FIXME: The Rust compiler currently omits weakly function definitions (i.e.,
-// __cxa_thread_atexit_impl) and its metadata from LLVM IR.
-#[no_sanitize(cfi, kcfi)]
pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
/// This is necessary because the __cxa_thread_atexit_impl implementation
/// std links to by default may be a C or C++ implementation that was not
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 3f3ba02..2097f1e 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1676,6 +1676,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// [`Result`]: crate::result::Result
/// [`std::panic::resume_unwind`]: crate::panic::resume_unwind
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), doc(search_unbox))]
pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>;
// This packet is used to communicate the return value between the spawned
diff --git a/library/std/tests/sync/mpmc.rs b/library/std/tests/sync/mpmc.rs
index 81b9229..78abcb3 100644
--- a/library/std/tests/sync/mpmc.rs
+++ b/library/std/tests/sync/mpmc.rs
@@ -64,6 +64,24 @@ fn smoke_port_gone() {
}
#[test]
+fn smoke_receiver_clone() {
+ let (tx, rx) = channel::<i32>();
+ let rx2 = rx.clone();
+ drop(rx);
+ tx.send(1).unwrap();
+ assert_eq!(rx2.recv().unwrap(), 1);
+}
+
+#[test]
+fn smoke_receiver_clone_port_gone() {
+ let (tx, rx) = channel::<i32>();
+ let rx2 = rx.clone();
+ drop(rx);
+ drop(rx2);
+ assert!(tx.send(1).is_err());
+}
+
+#[test]
fn smoke_shared_port_gone() {
let (tx, rx) = channel::<i32>();
drop(rx);
@@ -125,6 +143,18 @@ fn chan_gone_concurrent() {
}
#[test]
+fn receiver_cloning() {
+ let (tx, rx) = channel::<i32>();
+ let rx2 = rx.clone();
+
+ tx.send(1).unwrap();
+ tx.send(2).unwrap();
+
+ assert_eq!(rx2.recv(), Ok(1));
+ assert_eq!(rx.recv(), Ok(2));
+}
+
+#[test]
fn stress() {
let count = if cfg!(miri) { 100 } else { 10000 };
let (tx, rx) = channel::<i32>();
diff --git a/library/stdarch b/library/stdarch
index 9426bb5..4666c73 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit 9426bb56586c6ae4095a2dcbd66c570253e6fb32
+Subproject commit 4666c7376f25a265c74535585d622da3da6dfeb1
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 7ada3f2..acaf026 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -666,10 +666,11 @@ fn run_test_in_process(
io::set_output_capture(None);
- let test_result = match result {
- Ok(()) => calc_result(&desc, Ok(()), time_opts.as_ref(), exec_time.as_ref()),
- Err(e) => calc_result(&desc, Err(e.as_ref()), time_opts.as_ref(), exec_time.as_ref()),
- };
+ // Determine whether the test passed or failed, by comparing its panic
+ // payload (if any) with its `ShouldPanic` value, and by checking for
+ // fatal timeout.
+ let test_result =
+ calc_result(&desc, result.err().as_deref(), time_opts.as_ref(), exec_time.as_ref());
let stdout = data.lock().unwrap_or_else(|e| e.into_inner()).to_vec();
let message = CompletedTest::new(id, desc, test_result, exec_time, stdout);
monitor_ch.send(message).unwrap();
@@ -741,10 +742,7 @@ fn spawn_test_subprocess(
fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! {
let builtin_panic_hook = panic::take_hook();
let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| {
- let test_result = match panic_info {
- Some(info) => calc_result(&desc, Err(info.payload()), None, None),
- None => calc_result(&desc, Ok(()), None, None),
- };
+ let test_result = calc_result(&desc, panic_info.map(|info| info.payload()), None, None);
// We don't support serializing TrFailedMsg, so just
// print the message out to stderr.
diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs
index 73dcc2e..a312894 100644
--- a/library/test/src/test_result.rs
+++ b/library/test/src/test_result.rs
@@ -39,15 +39,18 @@ pub enum TestResult {
/// Creates a `TestResult` depending on the raw result of test execution
/// and associated data.
-pub(crate) fn calc_result<'a>(
+pub(crate) fn calc_result(
desc: &TestDesc,
- task_result: Result<(), &'a (dyn Any + 'static + Send)>,
+ panic_payload: Option<&(dyn Any + Send)>,
time_opts: Option<&time::TestTimeOptions>,
exec_time: Option<&time::TestExecTime>,
) -> TestResult {
- let result = match (&desc.should_panic, task_result) {
- (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk,
- (&ShouldPanic::YesWithMessage(msg), Err(err)) => {
+ let result = match (desc.should_panic, panic_payload) {
+ // The test did or didn't panic, as expected.
+ (ShouldPanic::No, None) | (ShouldPanic::Yes, Some(_)) => TestResult::TrOk,
+
+ // Check the actual panic message against the expected message.
+ (ShouldPanic::YesWithMessage(msg), Some(err)) => {
let maybe_panic_str = err
.downcast_ref::<String>()
.map(|e| &**e)
@@ -71,10 +74,19 @@ pub(crate) fn calc_result<'a>(
))
}
}
- (&ShouldPanic::Yes, Ok(())) | (&ShouldPanic::YesWithMessage(_), Ok(())) => {
- TestResult::TrFailedMsg("test did not panic as expected".to_string())
+
+ // The test should have panicked, but didn't panic.
+ (ShouldPanic::Yes, None) | (ShouldPanic::YesWithMessage(_), None) => {
+ let fn_location = if !desc.source_file.is_empty() {
+ &format!(" at {}:{}:{}", desc.source_file, desc.start_line, desc.start_col)
+ } else {
+ ""
+ };
+ TestResult::TrFailedMsg(format!("test did not panic as expected{}", fn_location))
}
- _ => TestResult::TrFailed,
+
+ // The test should not have panicked, but did panic.
+ (ShouldPanic::No, Some(_)) => TestResult::TrFailed,
};
// If test is already failed (or allowed to fail), do not change the result.
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 140f601..42ad14a 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1331,7 +1331,7 @@
build.check_vendored_status()
if not os.path.exists(build.build_dir):
- os.makedirs(build.build_dir)
+ os.makedirs(os.path.realpath(build.build_dir))
# Fetch/build the bootstrap
build.download_toolchain()
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index e157ff2..b70d452 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
-Last change is for: https://github.com/rust-lang/rust/pull/138784
+Last change is for: https://github.com/rust-lang/rust/pull/139931
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index b191d0f..ae9511b 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -3,7 +3,7 @@
use crate::core::build_steps::compile::{
add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
};
-use crate::core::build_steps::tool::{SourceType, prepare_tool_cargo};
+use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo};
use crate::core::builder::{
self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, crate_description,
};
@@ -416,7 +416,7 @@ fn run(self, builder: &Builder<'_>) {
&[],
);
- cargo.allow_features("test");
+ cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
// For ./x.py clippy, don't run with --all-targets because
// linting tests and benchmarks can produce very noisy results
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index dab58fc..6a5b38d 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -155,7 +155,7 @@ fn run(self, builder: &Builder<'_>) {
// When using `download-rustc`, we already have artifacts for the host available. Don't
// recompile them.
- if builder.download_rustc() && builder.is_builder_target(target)
+ if builder.download_rustc() && builder.config.is_host_target(target)
// NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so
// its artifacts can't be reused.
&& compiler.stage != 0
@@ -229,7 +229,7 @@ fn run(self, builder: &Builder<'_>) {
// The LLD wrappers and `rust-lld` are self-contained linking components that can be
// necessary to link the stdlib on some targets. We'll also need to copy these binaries to
// the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target.
- if compiler.stage == 0 && builder.is_builder_target(compiler.host) {
+ if compiler.stage == 0 && builder.config.is_host_target(compiler.host) {
trace!(
"(build == host) copying linking components to `stage0-sysroot` for bootstrapping"
);
@@ -1374,7 +1374,7 @@ pub fn rustc_cargo_env(
/// Pass down configuration from the LLVM build into the build of
/// rustc_llvm and rustc_codegen_llvm.
fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
- if builder.is_rust_llvm(target) {
+ if builder.config.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
if builder.config.llvm_enzyme {
@@ -2182,7 +2182,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
debug!("copying codegen backends to sysroot");
copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
- if builder.config.lld_enabled {
+ if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) {
builder.ensure(crate::core::build_steps::tool::LldWrapper {
build_compiler,
target_compiler,
@@ -2532,7 +2532,9 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path)
// FIXME: to make things simpler for now, limit this to the host and target where we know
// `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not
// cross-compiling. Expand this to other appropriate targets in the future.
- if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(target) || !path.exists()
+ if target != "x86_64-unknown-linux-gnu"
+ || !builder.config.is_host_target(target)
+ || !path.exists()
{
return;
}
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 83f71ae..ed90ede 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -612,7 +612,7 @@ fn run(self, builder: &Builder<'_>) {
fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
// The only true set of target libraries came from the build triple, so
// let's reduce redundant work by only producing archives from that host.
- if !builder.is_builder_target(compiler.host) {
+ if !builder.config.is_host_target(compiler.host) {
builder.info("\tskipping, not a build host");
true
} else {
@@ -671,7 +671,8 @@ fn copy_target_libs(
&self_contained_dst.join(path.file_name().unwrap()),
FileType::NativeLibrary,
);
- } else if dependency_type == DependencyType::Target || builder.is_builder_target(target) {
+ } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
+ {
builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
}
}
@@ -824,7 +825,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let compiler = self.compiler;
let target = self.target;
- if !builder.is_builder_target(compiler.host) {
+ if !builder.config.is_host_target(compiler.host) {
return None;
}
@@ -2118,7 +2119,7 @@ fn maybe_install_llvm(
//
// If the LLVM is coming from ourselves (just from CI) though, we
// still want to install it, as it otherwise won't be available.
- if builder.is_system_llvm(target) {
+ if builder.config.is_system_llvm(target) {
trace!("system LLVM requested, no install");
return false;
}
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index b1a97bd..9da8b27 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -81,14 +81,19 @@ fn update_rustfmt_version(build: &Builder<'_>) {
let Some((version, stamp_file)) = get_rustfmt_version(build) else {
return;
};
- t!(std::fs::write(stamp_file.path(), version))
+
+ t!(stamp_file.add_stamp(version).write());
}
-/// Returns the Rust files modified between the `merge-base` of HEAD and
-/// rust-lang/master and what is now on the disk. Does not include removed files.
+/// Returns the Rust files modified between the last merge commit and what is now on the disk.
+/// Does not include removed files.
///
/// Returns `None` if all files should be formatted.
fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> {
+ // In CI `get_git_modified_files` returns something different to normal environment.
+ // This shouldn't be called in CI anyway.
+ assert!(!build.config.is_running_on_ci);
+
if !verify_rustfmt_version(build) {
return Ok(None);
}
@@ -103,7 +108,7 @@ struct RustfmtConfig {
// Prints output describing a collection of paths, with lines such as "formatted modified file
// foo/bar/baz" or "skipped 20 untracked files".
-fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths: &[String]) {
+fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
let len = paths.len();
let adjective =
if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
@@ -114,9 +119,6 @@ fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths:
} else {
println!("fmt: {verb} {len} {adjective}files");
}
- if len > 1000 && !build.config.is_running_on_ci {
- println!("hint: if this number seems too high, try running `git fetch origin master`");
- }
}
pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
@@ -189,7 +191,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
)
.map(|x| x.to_string())
.collect();
- print_paths(build, "skipped", Some("untracked"), &untracked_paths);
+ print_paths("skipped", Some("untracked"), &untracked_paths);
for untracked_path in untracked_paths {
// The leading `/` makes it an exact match against the
@@ -212,7 +214,13 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
override_builder.add(&format!("/{file}")).expect(&file);
}
}
- Ok(None) => {}
+ Ok(None) => {
+ // NOTE: `Ok(None)` signifies that we need to format all files.
+ // The tricky part here is that if `override_builder` isn't given any white
+ // list files (i.e. files to be formatted, added without leading `!`), it
+ // will instead look for *all* files. So, by doing nothing here, we are
+ // actually making it so we format all files.
+ }
Err(err) => {
eprintln!("fmt warning: Something went wrong running git commands:");
eprintln!("fmt warning: {err}");
@@ -318,7 +326,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
});
let mut paths = formatted_paths.into_inner().unwrap();
paths.sort();
- print_paths(build, if check { "checked" } else { "formatted" }, adjective, &paths);
+ print_paths(if check { "checked" } else { "formatted" }, adjective, &paths);
drop(tx);
@@ -328,7 +336,10 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
crate::exit!(1);
}
- if !check {
- update_rustfmt_version(build);
- }
+ // Update `build/.rustfmt-stamp`, allowing this code to ignore files which have not been changed
+ // since last merge.
+ //
+ // NOTE: Because of the exit above, this is only reachable if formatting / format checking
+ // succeeded. So we are not commiting the version if formatting was not good.
+ update_rustfmt_version(build);
}
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 69a8bd5..6f6839a 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -370,8 +370,8 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
cfg.define("LLVM_PROFDATA_FILE", path);
}
- // Libraries for ELF section compression.
- if !target.is_windows() {
+ // Libraries for ELF section compression and profraw files merging.
+ if !target.is_msvc() {
cfg.define("LLVM_ENABLE_ZLIB", "ON");
} else {
cfg.define("LLVM_ENABLE_ZLIB", "OFF");
@@ -485,7 +485,7 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
}
// https://llvm.org/docs/HowToCrossCompileLLVM.html
- if !builder.is_builder_target(target) {
+ if !builder.config.is_host_target(target) {
let LlvmResult { llvm_config, .. } =
builder.ensure(Llvm { target: builder.config.build });
if !builder.config.dry_run() {
@@ -637,7 +637,7 @@ fn configure_cmake(
}
cfg.target(&target.triple).host(&builder.config.build.triple);
- if !builder.is_builder_target(target) {
+ if !builder.config.is_host_target(target) {
cfg.define("CMAKE_CROSSCOMPILING", "True");
// NOTE: Ideally, we wouldn't have to do this, and `cmake-rs` would just handle it for us.
@@ -1098,7 +1098,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
.define("LLVM_CMAKE_DIR", llvm_cmake_dir)
.define("LLVM_INCLUDE_TESTS", "OFF");
- if !builder.is_builder_target(target) {
+ if !builder.config.is_host_target(target) {
// Use the host llvm-tblgen binary.
cfg.define(
"LLVM_TABLEGEN_EXE",
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index e23c1ab..096f7de 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -15,7 +15,7 @@
use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
use crate::core::build_steps::llvm::get_llvm_version;
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
-use crate::core::build_steps::tool::{self, SourceType, Tool};
+use crate::core::build_steps::tool::{self, COMPILETEST_ALLOW_FEATURES, SourceType, Tool};
use crate::core::build_steps::toolstate::ToolState;
use crate::core::build_steps::{compile, dist, llvm};
use crate::core::builder::{
@@ -721,7 +721,7 @@ fn run(self, builder: &Builder<'_>) {
SourceType::InTree,
&[],
);
- cargo.allow_features("test");
+ cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
}
}
@@ -1894,7 +1894,7 @@ fn run(self, builder: &Builder<'_>) {
.arg(llvm_components.trim());
llvm_components_passed = true;
}
- if !builder.is_rust_llvm(target) {
+ if !builder.config.is_rust_llvm(target) {
cmd.arg("--system-llvm");
}
@@ -2668,7 +2668,7 @@ fn run(self, builder: &Builder<'_>) {
cargo
} else {
// Also prepare a sysroot for the target.
- if !builder.is_builder_target(target) {
+ if !builder.config.is_host_target(target) {
builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
builder.ensure(RemoteCopyLibs { compiler, target });
}
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 7cc7093..3426da5 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -148,10 +148,9 @@ fn run(mut self, builder: &Builder<'_>) -> ToolBuildResult {
&self.extra_features,
);
- if path.ends_with("/rustdoc") &&
- // rustdoc is performance sensitive, so apply LTO to it.
- is_lto_stage(&self.compiler)
- {
+ // Rustc tools (miri, clippy, cargo, rustfmt, rust-analyzer)
+ // could use the additional optimizations.
+ if self.mode == Mode::ToolRustc && is_lto_stage(&self.compiler) {
let lto = match builder.config.rust_lto {
RustcLto::Off => Some("off"),
RustcLto::Thin => Some("thin"),
@@ -445,7 +444,11 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
SourceType::InTree
},
extra_features: vec![],
- allow_features: concat!($($allow_features)*),
+ allow_features: {
+ let mut _value = "";
+ $( _value = $allow_features; )?
+ _value
+ },
cargo_args: vec![],
artifact_kind: if false $(|| $artifact_kind == ToolArtifactKind::Library)* {
ToolArtifactKind::Library
@@ -459,6 +462,8 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
}
}
+pub(crate) const COMPILETEST_ALLOW_FEATURES: &str = "test,internal_output_capture";
+
bootstrap_tool!(
// This is marked as an external tool because it includes dependencies
// from submodules. Trying to keep the lints in sync between all the repos
@@ -469,7 +474,7 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
Tidy, "src/tools/tidy", "tidy";
Linkchecker, "src/tools/linkchecker", "linkchecker";
CargoTest, "src/tools/cargotest", "cargotest";
- Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test";
+ Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
BuildManifest, "src/tools/build-manifest", "build-manifest";
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
RustInstaller, "src/tools/rust-installer", "rust-installer";
@@ -484,7 +489,8 @@ fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
SuggestTests, "src/tools/suggest-tests", "suggest-tests";
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
- RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test";
+ // rustdoc-gui-test has a crate dependency on compiletest, so it needs the same unstable features.
+ RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
CoverageDump, "src/tools/coverage-dump", "coverage-dump";
WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index fd3b28e..5de824e 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -1107,8 +1107,8 @@ fn test_is_builder_target() {
let build = Build::new(config);
let builder = Builder::new(&build);
- assert!(builder.is_builder_target(target1));
- assert!(!builder.is_builder_target(target2));
+ assert!(builder.config.is_host_target(target1));
+ assert!(!builder.config.is_host_target(target2));
}
}
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 25ec64f..cd97066 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -2397,6 +2397,12 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
);
}
+ if config.lld_enabled && config.is_system_llvm(config.build) {
+ eprintln!(
+ "Warning: LLD is enabled when using external llvm-config. LLD will not be built and copied to the sysroot."
+ );
+ }
+
let default_std_features = BTreeSet::from([String::from("panic-unwind")]);
config.rust_std_features = std_features.unwrap_or(default_std_features);
@@ -2888,6 +2894,13 @@ pub(crate) fn update_submodule(&self, relative_path: &str) {
let absolute_path = self.src.join(relative_path);
+ // NOTE: This check is required because `jj git clone` doesn't create directories for
+ // submodules, they are completely ignored. The code below assumes this directory exists,
+ // so create it here.
+ if !absolute_path.exists() {
+ t!(fs::create_dir_all(&absolute_path));
+ }
+
// NOTE: The check for the empty directory is here because when running x.py the first time,
// the submodule won't be checked out. Check it out now so we can build it.
if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository()
@@ -3233,6 +3246,42 @@ pub fn last_modified_commit(
Some(commit.to_string())
}
+
+ /// Checks if the given target is the same as the host target.
+ pub fn is_host_target(&self, target: TargetSelection) -> bool {
+ self.build == target
+ }
+
+ /// Returns `true` if this is an external version of LLVM not managed by bootstrap.
+ /// In particular, we expect llvm sources to be available when this is false.
+ ///
+ /// NOTE: this is not the same as `!is_rust_llvm` when `llvm_has_patches` is set.
+ pub fn is_system_llvm(&self, target: TargetSelection) -> bool {
+ match self.target_config.get(&target) {
+ Some(Target { llvm_config: Some(_), .. }) => {
+ let ci_llvm = self.llvm_from_ci && self.is_host_target(target);
+ !ci_llvm
+ }
+ // We're building from the in-tree src/llvm-project sources.
+ Some(Target { llvm_config: None, .. }) => false,
+ None => false,
+ }
+ }
+
+ /// Returns `true` if this is our custom, patched, version of LLVM.
+ ///
+ /// This does not necessarily imply that we're managing the `llvm-project` submodule.
+ pub fn is_rust_llvm(&self, target: TargetSelection) -> bool {
+ match self.target_config.get(&target) {
+ // We're using a user-controlled version of LLVM. The user has explicitly told us whether the version has our patches.
+ // (They might be wrong, but that's not a supported use-case.)
+ // In particular, this tries to support `submodules = false` and `patches = false`, for using a newer version of LLVM that's not through `rust-lang/llvm-project`.
+ Some(Target { llvm_has_rust_patches: Some(patched), .. }) => *patched,
+ // The user hasn't promised the patches match.
+ // This only has our patches if it's downloaded from CI or built from source.
+ _ => !self.is_system_llvm(target),
+ }
+ }
}
/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options.
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 5bd947f..4e4b948 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -417,7 +417,7 @@ enum DownloadSource {
Dist,
}
-/// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
+/// Functions that are only ever called once, but named for clarity and to avoid thousand-line functions.
impl Config {
pub(crate) fn download_clippy(&self) -> PathBuf {
self.verbose(|| println!("downloading stage0 clippy artifacts"));
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 891340a..eb0bf1d 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -34,6 +34,7 @@ pub struct Finder {
// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
const STAGE0_MISSING_TARGETS: &[&str] = &[
// just a dummy comment so the list doesn't get onelined
+ "x86_64-lynx-lynxos178",
];
/// Minimum version threshold for libstdc++ required when using prebuilt LLVM
@@ -325,7 +326,7 @@ pub fn check(build: &mut Build) {
if target.contains("musl") && !target.contains("unikraft") {
// If this is a native target (host is also musl) and no musl-root is given,
// fall back to the system toolchain in /usr before giving up
- if build.musl_root(*target).is_none() && build.is_builder_target(*target) {
+ if build.musl_root(*target).is_none() && build.config.is_host_target(*target) {
let target = build.config.target_config.entry(*target).or_default();
target.musl_root = Some("/usr".into());
}
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 1a513a2..88d1815 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -35,7 +35,7 @@
use crate::core::builder;
use crate::core::builder::Kind;
-use crate::core::config::{DryRun, LldMode, LlvmLibunwind, Target, TargetSelection, flags};
+use crate::core::config::{DryRun, LldMode, LlvmLibunwind, TargetSelection, flags};
use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode, command};
use crate::utils::helpers::{
self, dir_is_empty, exe, libdir, output, set_file_times, split_debuginfo, symlink_dir,
@@ -803,7 +803,7 @@ fn cargo_out(&self, compiler: Compiler, mode: Mode, target: TargetSelection) ->
/// Note that if LLVM is configured externally then the directory returned
/// will likely be empty.
fn llvm_out(&self, target: TargetSelection) -> PathBuf {
- if self.config.llvm_from_ci && self.is_builder_target(target) {
+ if self.config.llvm_from_ci && self.config.is_host_target(target) {
self.config.ci_llvm_root()
} else {
self.out.join(target).join("llvm")
@@ -851,37 +851,6 @@ fn vendored_crates_path(&self) -> Option<PathBuf> {
if self.config.vendor { Some(self.src.join(VENDOR_DIR)) } else { None }
}
- /// Returns `true` if this is an external version of LLVM not managed by bootstrap.
- /// In particular, we expect llvm sources to be available when this is false.
- ///
- /// NOTE: this is not the same as `!is_rust_llvm` when `llvm_has_patches` is set.
- fn is_system_llvm(&self, target: TargetSelection) -> bool {
- match self.config.target_config.get(&target) {
- Some(Target { llvm_config: Some(_), .. }) => {
- let ci_llvm = self.config.llvm_from_ci && self.is_builder_target(target);
- !ci_llvm
- }
- // We're building from the in-tree src/llvm-project sources.
- Some(Target { llvm_config: None, .. }) => false,
- None => false,
- }
- }
-
- /// Returns `true` if this is our custom, patched, version of LLVM.
- ///
- /// This does not necessarily imply that we're managing the `llvm-project` submodule.
- fn is_rust_llvm(&self, target: TargetSelection) -> bool {
- match self.config.target_config.get(&target) {
- // We're using a user-controlled version of LLVM. The user has explicitly told us whether the version has our patches.
- // (They might be wrong, but that's not a supported use-case.)
- // In particular, this tries to support `submodules = false` and `patches = false`, for using a newer version of LLVM that's not through `rust-lang/llvm-project`.
- Some(Target { llvm_has_rust_patches: Some(patched), .. }) => *patched,
- // The user hasn't promised the patches match.
- // This only has our patches if it's downloaded from CI or built from source.
- _ => !self.is_system_llvm(target),
- }
- }
-
/// Returns the path to `FileCheck` binary for the specified target
fn llvm_filecheck(&self, target: TargetSelection) -> PathBuf {
let target_config = self.config.target_config.get(&target);
@@ -1356,7 +1325,7 @@ fn linker(&self, target: TargetSelection) -> Option<PathBuf> {
// need to use CXX compiler as linker to resolve the exception functions
// that are only existed in CXX libraries
Some(self.cxx.borrow()[&target].path().into())
- } else if !self.is_builder_target(target)
+ } else if !self.config.is_host_target(target)
&& helpers::use_host_linker(target)
&& !target.is_msvc()
{
@@ -2025,11 +1994,6 @@ fn colored_stream_inner<R, F, C>(&self, constructor: C, is_tty: bool, f: F) -> R
stream.reset().unwrap();
result
}
-
- /// Checks if the given target is the same as the builder target.
- fn is_builder_target(&self, target: TargetSelection) -> bool {
- self.config.build == target
- }
}
#[cfg(unix)]
diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs
index aa564b4..7cf1af1 100644
--- a/src/bootstrap/src/utils/proc_macro_deps.rs
+++ b/src/bootstrap/src/utils/proc_macro_deps.rs
@@ -32,7 +32,6 @@
"mime_guess",
"minimal-lexical",
"nom",
- "num-conv",
"once_cell",
"pest",
"pest_generator",
@@ -50,7 +49,6 @@
"syn",
"synstructure",
"thiserror",
- "time-core",
"tinystr",
"type-map",
"typenum",
diff --git a/src/build_helper/src/fs/mod.rs b/src/build_helper/src/fs/mod.rs
index 0202984..123df76 100644
--- a/src/build_helper/src/fs/mod.rs
+++ b/src/build_helper/src/fs/mod.rs
@@ -22,21 +22,27 @@ pub fn ignore_not_found<Op>(mut op: Op) -> io::Result<()>
/// A wrapper around [`std::fs::remove_dir_all`] that can also be used on *non-directory entries*,
/// including files and symbolic links.
///
-/// - This will produce an error if the target path is not found.
+/// - This will not produce an error if the target path is not found.
/// - Like [`std::fs::remove_dir_all`], this helper does not traverse symbolic links, will remove
/// symbolic link itself.
/// - This helper is **not** robust against races on the underlying filesystem, behavior is
/// unspecified if this helper is called concurrently.
/// - This helper is not robust against TOCTOU problems.
///
-/// FIXME: this implementation is insufficiently robust to replace bootstrap's clean `rm_rf`
-/// implementation:
-///
-/// - This implementation currently does not perform retries.
+/// FIXME: Audit whether this implementation is robust enough to replace bootstrap's clean `rm_rf`.
#[track_caller]
pub fn recursive_remove<P: AsRef<Path>>(path: P) -> io::Result<()> {
let path = path.as_ref();
- let metadata = fs::symlink_metadata(path)?;
+
+ // If the path doesn't exist, we treat it as a successful no-op.
+ // From the caller's perspective, the goal is simply "ensure this file/dir is gone" —
+ // if it's already not there, that's a success, not an error.
+ let metadata = match fs::symlink_metadata(path) {
+ Ok(m) => m,
+ Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(()),
+ Err(e) => return Err(e),
+ };
+
#[cfg(windows)]
let is_dir_like = |meta: &fs::Metadata| {
use std::os::windows::fs::FileTypeExt;
@@ -45,11 +51,35 @@ pub fn recursive_remove<P: AsRef<Path>>(path: P) -> io::Result<()> {
#[cfg(not(windows))]
let is_dir_like = fs::Metadata::is_dir;
- if is_dir_like(&metadata) {
- fs::remove_dir_all(path)
- } else {
- try_remove_op_set_perms(fs::remove_file, path, metadata)
+ const MAX_RETRIES: usize = 5;
+ const RETRY_DELAY_MS: u64 = 100;
+
+ let try_remove = || {
+ if is_dir_like(&metadata) {
+ fs::remove_dir_all(path)
+ } else {
+ try_remove_op_set_perms(fs::remove_file, path, metadata.clone())
+ }
+ };
+
+ // Retry deletion a few times to handle transient filesystem errors.
+ // This is unusual for local file operations, but it's a mitigation
+ // against unlikely events where malware scanners may be holding a
+ // file beyond our control, to give the malware scanners some opportunity
+ // to release their hold.
+ for attempt in 0..MAX_RETRIES {
+ match try_remove() {
+ Ok(()) => return Ok(()),
+ Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(()),
+ Err(_) if attempt < MAX_RETRIES - 1 => {
+ std::thread::sleep(std::time::Duration::from_millis(RETRY_DELAY_MS));
+ continue;
+ }
+ Err(e) => return Err(e),
+ }
}
+
+ Ok(())
}
fn try_remove_op_set_perms<'p, Op>(mut op: Op, path: &'p Path, metadata: Metadata) -> io::Result<()>
@@ -67,3 +97,9 @@ fn try_remove_op_set_perms<'p, Op>(mut op: Op, path: &'p Path, metadata: Metadat
Err(e) => Err(e),
}
}
+
+pub fn remove_and_create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
+ let path = path.as_ref();
+ recursive_remove(path)?;
+ fs::create_dir_all(path)
+}
diff --git a/src/build_helper/src/fs/tests.rs b/src/build_helper/src/fs/tests.rs
index 1e69439..7ce1d89 100644
--- a/src/build_helper/src/fs/tests.rs
+++ b/src/build_helper/src/fs/tests.rs
@@ -14,7 +14,7 @@ fn nonexistent_path() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_nonexistent_path");
assert!(fs::symlink_metadata(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound));
- assert!(recursive_remove(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound));
+ assert!(recursive_remove(&path).is_ok());
}
#[test]
diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs
index 693e0fc..f5347c3 100644
--- a/src/build_helper/src/git.rs
+++ b/src/build_helper/src/git.rs
@@ -114,7 +114,9 @@ fn git_upstream_merge_base(
Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned())
}
-/// Searches for the nearest merge commit in the repository that also exists upstream.
+/// Searches for the nearest merge commit in the repository.
+///
+/// **In CI** finds the nearest merge commit that *also exists upstream*.
///
/// It looks for the most recent commit made by the merge bot by matching the author's email
/// address with the merge bot's email.
@@ -165,7 +167,7 @@ pub fn get_closest_merge_commit(
Ok(output_result(&mut git)?.trim().to_owned())
}
-/// Returns the files that have been modified in the current branch compared to the master branch.
+/// Returns the files that have been modified in the current branch compared to the last merge.
/// The `extensions` parameter can be used to filter the files by their extension.
/// Does not include removed files.
/// If `extensions` is empty, all files will be returned.
diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock
index 800eaae..2fe219f 100644
--- a/src/ci/citool/Cargo.lock
+++ b/src/ci/citool/Cargo.lock
@@ -563,9 +563,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.8.5"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs
index 208a494..9fc7c30 100644
--- a/src/ci/citool/src/analysis.rs
+++ b/src/ci/citool/src/analysis.rs
@@ -520,23 +520,27 @@ fn format_job_group(group: u64) -> String {
}
if doctest_count > 0 {
+ let prefix =
+ if doctest_count < original_diff_count { "Additionally, " } else { "" };
println!(
- "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.",
+ "\n{prefix}{doctest_count} doctest {} were found. These are ignored, as they are noisy.",
pluralize("diff", doctest_count)
);
}
// Now print the job group index
- println!("\n**Job group index**\n");
- for (group, jobs) in job_index.into_iter().enumerate() {
- println!(
- "- {}: {}",
- format_job_group(group as u64),
- jobs.iter()
- .map(|j| format_job_link(job_info_resolver, job_metrics, j))
- .collect::<Vec<_>>()
- .join(", ")
- );
+ if !job_index.is_empty() {
+ println!("\n**Job group index**\n");
+ for (group, jobs) in job_index.into_iter().enumerate() {
+ println!(
+ "- {}: {}",
+ format_job_group(group as u64),
+ jobs.iter()
+ .map(|j| format_job_link(job_info_resolver, job_metrics, j))
+ .collect::<Vec<_>>()
+ .join(", ")
+ );
+ }
}
},
);
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile
new file mode 100644
index 0000000..408b871
--- /dev/null
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile
@@ -0,0 +1,69 @@
+FROM ubuntu:25.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ bzip2 \
+ g++ \
+ gcc-multilib \
+ make \
+ ninja-build \
+ file \
+ curl \
+ ca-certificates \
+ python3 \
+ git \
+ cmake \
+ sudo \
+ gdb \
+ llvm-20-tools \
+ llvm-20-dev \
+ libedit-dev \
+ libssl-dev \
+ pkg-config \
+ zlib1g-dev \
+ xz-utils \
+ nodejs \
+ mingw-w64 \
+ # libgccjit dependencies
+ flex \
+ libmpfr-dev \
+ libgmp-dev \
+ libmpc3 \
+ libmpc-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install powershell (universal package) so we can test x.ps1 on Linux
+# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep.
+RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
+ dpkg --ignore-depends=libicu72 -i powershell.deb && \
+ rm -f powershell.deb
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+ENV EXTERNAL_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+ --build=x86_64-unknown-linux-gnu \
+ --llvm-root=/usr/lib/llvm-20 \
+ --enable-llvm-link-shared \
+ --set rust.randomize-layout=true \
+ --set rust.thin-lto-import-instr-limit=10
+
+COPY scripts/shared.sh /scripts/
+
+ARG SCRIPT_ARG
+
+COPY scripts/add_dummy_commit.sh /tmp/
+COPY scripts/x86_64-gnu-llvm.sh /tmp/
+COPY scripts/x86_64-gnu-llvm2.sh /tmp/
+COPY scripts/x86_64-gnu-llvm3.sh /tmp/
+COPY scripts/stage_2_test_set1.sh /tmp/
+COPY scripts/stage_2_test_set2.sh /tmp/
+
+ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}"
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index fbda749..cb2bec5 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -23,8 +23,8 @@
os: ubuntu-24.04-16core-64gb
<<: *base-job
- - &job-macos-xl
- os: macos-13 # We use the standard runner for now
+ - &job-macos
+ os: macos-13
<<: *base-job
- &job-macos-m1
@@ -304,6 +304,31 @@
- name: x86_64-gnu-distcheck
<<: *job-linux-8c
+ # The x86_64-gnu-llvm-20 job is split into multiple jobs to run tests in parallel.
+ # x86_64-gnu-llvm-20-1 skips tests that run in x86_64-gnu-llvm-20-{2,3}.
+ - name: x86_64-gnu-llvm-20-1
+ env:
+ RUST_BACKTRACE: 1
+ IMAGE: x86_64-gnu-llvm-20
+ DOCKER_SCRIPT: stage_2_test_set1.sh
+ <<: *job-linux-4c
+
+ # Skip tests that run in x86_64-gnu-llvm-20-{1,3}
+ - name: x86_64-gnu-llvm-20-2
+ env:
+ RUST_BACKTRACE: 1
+ IMAGE: x86_64-gnu-llvm-20
+ DOCKER_SCRIPT: x86_64-gnu-llvm2.sh
+ <<: *job-linux-4c
+
+ # Skip tests that run in x86_64-gnu-llvm-20-{1,2}
+ - name: x86_64-gnu-llvm-20-3
+ env:
+ RUST_BACKTRACE: 1
+ IMAGE: x86_64-gnu-llvm-20
+ DOCKER_SCRIPT: x86_64-gnu-llvm3.sh
+ <<: *job-linux-4c
+
# The x86_64-gnu-llvm-19 job is split into multiple jobs to run tests in parallel.
# x86_64-gnu-llvm-19-1 skips tests that run in x86_64-gnu-llvm-19-{2,3}.
- name: x86_64-gnu-llvm-19-1
@@ -355,7 +380,7 @@
NO_OVERFLOW_CHECKS: 1
DIST_REQUIRE_ALL_TOOLS: 1
CODEGEN_BACKENDS: llvm,cranelift
- <<: *job-macos-xl
+ <<: *job-macos
- name: dist-apple-various
env:
@@ -372,18 +397,18 @@
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
- <<: *job-macos-xl
+ <<: *job-macos
- name: x86_64-apple-1
env:
<<: *env-x86_64-apple-tests
- <<: *job-macos-xl
+ <<: *job-macos
- name: x86_64-apple-2
env:
SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc
<<: *env-x86_64-apple-tests
- <<: *job-macos-xl
+ <<: *job-macos
- name: dist-aarch64-apple
env:
diff --git a/src/doc/book b/src/doc/book
index 45f0536..d339163 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 45f05367360f033f89235eacbbb54e8d73ce6b70
+Subproject commit d33916341d480caede1d0ae57cbeae23aab23e88
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
index 1e27e5e..467f456 160000
--- a/src/doc/edition-guide
+++ b/src/doc/edition-guide
@@ -1 +1 @@
-Subproject commit 1e27e5e6d5133ae4612f5cc195c15fc8d51b1c9c
+Subproject commit 467f45637b73ec6aa70fb36bc3054bb50b8967ea
diff --git a/src/doc/nomicon b/src/doc/nomicon
index b4448fa..0c10c30 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit b4448fa406a6dccde62d1e2f34f70fc51814cdcc
+Subproject commit 0c10c30cc54736c5c194ce98c50e2de84eeb6e79
diff --git a/src/doc/reference b/src/doc/reference
index 46435cd..3340922 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 46435cd4eba11b66acaa42c01da5c80ad88aee4b
+Subproject commit 3340922df189bddcbaad17dc3927d51a76bcd5ed
diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md
index a7c3236..1837b59 100644
--- a/src/doc/rustc-dev-guide/src/appendix/glossary.md
+++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md
@@ -31,7 +31,6 @@
<span id="generics">generics</span> | The list of generic parameters defined on an item. There are three kinds of generic parameters: Type, lifetime and const parameters.
<span id="hir">HIR</span> | The _high-level [IR](#ir)_, created by lowering and desugaring the AST. ([see more](../hir.md))
<span id="hir-id">`HirId`</span> | Identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
-<span id="hir-map">HIR map</span> | The HIR map, accessible via `tcx.hir()`, allows you to quickly navigate the HIR and convert between various forms of identifiers.
<span id="ice">ICE</span> | Short for _internal compiler error_, this is when the compiler crashes.
<span id="ich">ICH</span> | Short for _incremental compilation hash_, these are used as fingerprints for things such as HIR and crate metadata, to check if changes have been made. This is useful in incremental compilation to see if part of a crate has changed and should be recompiled.
<span id="infcx">`infcx`</span> | The type inference context (`InferCtxt`). (see `rustc_middle::infer`)
diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md
index 0849464..62dfaca 100644
--- a/src/doc/rustc-dev-guide/src/building/optimized-build.md
+++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md
@@ -109,11 +109,16 @@
Here is an example of how can `opt-dist` be used locally (outside of CI):
-1. Build the tool with the following command:
+1. Enable metrics in your `bootstrap.toml` file, because `opt-dist` expects it to be enabled:
+ ```toml
+ [build]
+ metrics = true
+ ```
+2. Build the tool with the following command:
```bash
./x build tools/opt-dist
```
-2. Run the tool with the `local` mode and provide necessary parameters:
+3. Run the tool with the `local` mode and provide necessary parameters:
```bash
./build/host/stage0-tools-bin/opt-dist local \
--target-triple <target> \ # select target, e.g. "x86_64-unknown-linux-gnu"
diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md
index 47f3976..102e202 100644
--- a/src/doc/rustc-dev-guide/src/compiler-debugging.md
+++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md
@@ -301,7 +301,8 @@
Some compiler options for debugging specific features yield graphviz graphs -
e.g. the `#[rustc_mir(borrowck_graphviz_postflow="suffix.dot")]` attribute
-dumps various borrow-checker dataflow graphs.
+on a function dumps various borrow-checker dataflow graphs in conjunction with
+`-Zdump-mir-dataflow`.
These all produce `.dot` files. To view these files, install graphviz (e.g.
`apt-get install graphviz`) and then run the following commands:
diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md
index 75f5a9e..65779f3 100644
--- a/src/doc/rustc-dev-guide/src/hir.md
+++ b/src/doc/rustc-dev-guide/src/hir.md
@@ -100,7 +100,7 @@
a wrapper around a [`HirId`]. For more info about HIR bodies, please refer to the
[HIR chapter][hir-bodies].
-These identifiers can be converted into one another through the [HIR map][map].
+These identifiers can be converted into one another through the `TyCtxt`.
[`DefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
[`LocalDefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.LocalDefId.html
@@ -110,30 +110,24 @@
[`CrateNum`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.CrateNum.html
[`DefIndex`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefIndex.html
[`Body`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Body.html
-[hir-map]: ./hir.md#the-hir-map
[hir-bodies]: ./hir.md#hir-bodies
-[map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html
-## The HIR Map
+## HIR Operations
Most of the time when you are working with the HIR, you will do so via
-the **HIR Map**, accessible in the tcx via [`tcx.hir()`] (and defined in
-the [`hir::map`] module). The [HIR map] contains a [number of methods] to
-convert between IDs of various kinds and to lookup data associated
-with a HIR node.
+`TyCtxt`. It contains a number of methods, defined in the `hir::map` module and
+mostly prefixed with `hir_`, to convert between IDs of various kinds and to
+lookup data associated with a HIR node.
-[`tcx.hir()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir
-[`hir::map`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/index.html
-[HIR map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html
-[number of methods]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#methods
+[`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
For example, if you have a [`LocalDefId`], and you would like to convert it
-to a [`HirId`], you can use [`tcx.hir().local_def_id_to_hir_id(def_id)`][local_def_id_to_hir_id].
+to a [`HirId`], you can use [`tcx.local_def_id_to_hir_id(def_id)`][local_def_id_to_hir_id].
You need a `LocalDefId`, rather than a `DefId`, since only local items have HIR nodes.
-[local_def_id_to_hir_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.local_def_id_to_hir_id
+[local_def_id_to_hir_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.local_def_id_to_hir_id
-Similarly, you can use [`tcx.hir().find(n)`][find] to lookup the node for a
+Similarly, you can use [`tcx.hir_node(n)`][hir_node] to lookup the node for a
[`HirId`]. This returns a `Option<Node<'hir>>`, where [`Node`] is an enum
defined in the map. By matching on this, you can find out what sort of
node the `HirId` referred to and also get a pointer to the data
@@ -142,15 +136,16 @@
[`tcx.hir_expect_expr(n)`][expect_expr], which will extract and return the
[`&hir::Expr`][Expr], panicking if `n` is not in fact an expression.
-[find]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.find
+[hir_node]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir_node
[`Node`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.Node.html
[expect_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.expect_expr
[Expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Expr.html
-Finally, you can use the HIR map to find the parents of nodes, via
-calls like [`tcx.hir().get_parent(n)`][get_parent].
+Finally, you can find the parents of nodes, via
+calls like [`tcx.parent_hir_node(n)`][parent_hir_node].
-[get_parent]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent
+[get_parent_item]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.parent_hir_node
+
## HIR Bodies
@@ -158,10 +153,10 @@
of a function/closure or the definition of a constant. Bodies are
associated with an **owner**, which is typically some kind of item
(e.g. an `fn()` or `const`), but could also be a closure expression
-(e.g. `|x, y| x + y`). You can use the HIR map to find the body
-associated with a given def-id ([`maybe_body_owned_by`]) or to find
-the owner of a body ([`body_owner_def_id`]).
+(e.g. `|x, y| x + y`). You can use the `TyCtxt` to find the body
+associated with a given def-id ([`hir_maybe_body_owned_by`]) or to find
+the owner of a body ([`hir_body_owner_def_id`]).
[`rustc_hir::Body`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Body.html
-[`maybe_body_owned_by`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.maybe_body_owned_by
-[`body_owner_def_id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.body_owner_def_id
+[`hir_maybe_body_owned_by`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir_maybe_body_owned_by
+[`hir_body_owner_def_id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir_body_owner_def_id
diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md
index 6905ee1..2bdc7f3 100644
--- a/src/doc/rustc-dev-guide/src/tests/best-practices.md
+++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md
@@ -175,6 +175,8 @@
- For `ignore-*`/`needs-*`/`only-*` directives, unless extremely obvious,
provide a brief remark on why the directive is needed. E.g. `"//@ ignore-wasi
(wasi codegens the main symbol differently)"`.
+- When using `//@ ignore-auxiliary`, specify the corresponding main test files,
+ e.g. ``//@ ignore-auxiliary (used by `./foo.rs`)``.
## FileCheck best practices
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index 7ed583c..dae659e 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -101,6 +101,7 @@
| `normalize-stdout` | Normalize actual stdout with a rule `"<raw>" -> "<normalized>"` before comparing against snapshot | `ui`, `incremental` | `"<RAW>" -> "<NORMALIZED>"`, `<RAW>`/`<NORMALIZED>` is regex capture and replace syntax |
| `dont-check-compiler-stderr` | Don't check actual compiler stderr vs stderr snapshot | `ui` | N/A |
| `dont-check-compiler-stdout` | Don't check actual compiler stdout vs stdout snapshot | `ui` | N/A |
+| `dont-require-annotations` | Don't require line annotations for the given diagnostic kind (`//~ KIND`) to be exhaustive | `ui`, `incremental` | `ERROR`, `WARN`, `NOTE`, `HELP`, `SUGGESTION` |
| `run-rustfix` | Apply all suggestions via `rustfix`, snapshot fixed output, and check fixed output builds | `ui` | N/A |
| `rustfix-only-machine-applicable` | `run-rustfix` but only machine-applicable suggestions | `ui` | N/A |
| `exec-env` | Env var to set when executing a test | `ui`, `crashes` | `<KEY>=<VALUE>` |
@@ -123,6 +124,9 @@
* `ignore-X` where `X` is a target detail or other criteria on which to ignore the test (see below)
* `only-X` is like `ignore-X`, but will *only* run the test on that target or
stage
+* `ignore-auxiliary` is intended for files that *participate* in one or more other
+ main test files but that `compiletest` should not try to build the file itself.
+ Please backlink to which main test is actually using the auxiliary file.
* `ignore-test` always ignores the test. This can be used to temporarily disable
a test if it is currently not working, but you want to keep it in tree to
re-enable it later.
@@ -234,14 +238,14 @@
### Affecting how tests are built
-| Directive | Explanation | Supported test suites | Possible values |
-|---------------------|----------------------------------------------------------------------------------------------|---------------------------|------------------------------------------------------------------------------|
-| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental`. |
-| `edition` | Alias for `compile-flags: --edition=xxx` | All except for `run-make` | Any valid `--edition` value |
-| `rustc-env` | Env var to set when running `rustc` | All except for `run-make` | `<KEY>=<VALUE>` |
-| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make` | Any env var name |
-| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A |
-| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |
+| Directive | Explanation | Supported test suites | Possible values |
+|---------------------|----------------------------------------------------------------------------------------------|---------------------------|--------------------------------------------------------------------------------------------|
+| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
+| `edition` | The edition used to build the test | All except for `run-make` | Any valid `--edition` value |
+| `rustc-env` | Env var to set when running `rustc` | All except for `run-make` | `<KEY>=<VALUE>` |
+| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make` | Any env var name |
+| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A |
+| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |
<div class="warning">
Tests (outside of `run-make`) that want to use incremental tests not in the
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index e862a07..3243a35 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -303,8 +303,7 @@
### `error-pattern`
The `error-pattern` [directive](directives.md) can be used for runtime messages, which don't
-have a specific span, or for compile time messages if imprecise matching is required due to
-multi-line platform specific diagnostics.
+have a specific span, or in exceptional cases for compile time messages.
Let's think about this test:
@@ -318,7 +317,7 @@
```
We want to ensure this shows "index out of bounds" but we cannot use the `ERROR`
-annotation since the error doesn't have any span. Then it's time to use the
+annotation since the runtime error doesn't have any span. Then it's time to use the
`error-pattern` directive:
```rust,ignore
@@ -331,29 +330,51 @@
}
```
-But for strict testing, try to use the `ERROR` annotation as much as possible,
-including `//~?` annotations for diagnostics without span.
-For compile time diagnostics `error-pattern` should very rarely be necessary.
+Use of `error-pattern` is not recommended in general.
-Per-line annotations (`//~`) are still checked in tests using `error-pattern`.
-To opt out of these checks, use `//@ compile-flags: --error-format=human`.
-Do that only in exceptional cases.
+For strict testing of compile time output, try to use the line annotations `//~` as much as
+possible, including `//~?` annotations for diagnostics without span.
-### Error levels
+If the compile time output is target dependent or too verbose, use directive
+`//@ dont-require-annotations: <diagnostic-kind>` to make the line annotation checking
+non-exhaustive, some of the compiler messages can stay uncovered by annotations in this mode.
-The error levels that you can have are:
+For checking runtime output `//@ check-run-results` may be preferable.
+
+Only use `error-pattern` if none of the above works.
+
+Line annotations `//~` are still checked in tests using `error-pattern`.
+In exceptional cases use `//@ compile-flags: --error-format=human` to opt out of these checks.
+
+### Diagnostic kinds (error levels)
+
+The diagnostic kinds that you can have are:
- `ERROR`
-- `WARN` or `WARNING`
+- `WARN` (or `WARNING`)
- `NOTE`
-- `HELP` and `SUGGESTION`
+- `HELP`
+- `SUGGESTION`
-You are allowed to not include a level, but you should include it at least for
-the primary message.
-
-The `SUGGESTION` level is used for specifying what the expected replacement text
+The `SUGGESTION` kind is used for specifying what the expected replacement text
should be for a diagnostic suggestion.
+`ERROR` and `WARN` kinds are required to be exhaustively covered by line annotations
+`//~` by default.
+
+Other kinds only need to be line-annotated if at least one annotation of that kind appears
+in the test file. For example, one `//~ NOTE` will also require all other `//~ NOTE`s in the file
+to be written out explicitly.
+
+Use directive `//@ dont-require-annotations` to opt out of exhaustive annotations.
+E.g. use `//@ dont-require-annotations: NOTE` to annotate notes selectively.
+Avoid using this directive for `ERROR`s and `WARN`ings, unless there's a serious reason, like
+target-dependent compiler output.
+
+Missing diagnostic kinds (`//~ message`) are currently accepted, but are being phased away.
+They will match any compiler output kind, but will not force exhaustive annotations for that kind.
+Prefer explicit kind and `//@ dont-require-annotations` to achieve the same effect.
+
UI tests use the `-A unused` flag by default to ignore all unused warnings, as
unused warnings are usually not the focus of a test. However, simple code
samples often have unused warnings. If the test is specifically testing an
diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md
index b33d540..ce6cffe 100644
--- a/src/doc/rustc-dev-guide/src/ty.md
+++ b/src/doc/rustc-dev-guide/src/ty.md
@@ -61,11 +61,11 @@
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Describe the *syntax* of a type: what the user wrote (with some desugaring). | Describe the *semantics* of a type: the meaning of what the user wrote. |
| Each `rustc_hir::Ty` has its own spans corresponding to the appropriate place in the program. | Doesn’t correspond to a single place in the user’s program. |
-| `rustc_hir::Ty` has generics and lifetimes; however, some of those lifetimes are special markers like [`LifetimeName::Implicit`][implicit]. | `ty::Ty` has the full type, including generics and lifetimes, even if the user left them out |
+| `rustc_hir::Ty` has generics and lifetimes; however, some of those lifetimes are special markers like [`LifetimeKind::Implicit`][implicit]. | `ty::Ty` has the full type, including generics and lifetimes, even if the user left them out |
| `fn foo(x: u32) → u32 { }` - Two `rustc_hir::Ty` representing each usage of `u32`, each has its own `Span`s, and `rustc_hir::Ty` doesn’t tell us that both are the same type | `fn foo(x: u32) → u32 { }` - One `ty::Ty` for all instances of `u32` throughout the program, and `ty::Ty` tells us that both usages of `u32` mean the same type. |
-| `fn foo(x: &u32) -> &u32)` - Two `rustc_hir::Ty` again. Lifetimes for the references show up in the `rustc_hir::Ty`s using a special marker, [`LifetimeName::Implicit`][implicit]. | `fn foo(x: &u32) -> &u32)`- A single `ty::Ty`. The `ty::Ty` has the hidden lifetime param. |
+| `fn foo(x: &u32) -> &u32)` - Two `rustc_hir::Ty` again. Lifetimes for the references show up in the `rustc_hir::Ty`s using a special marker, [`LifetimeKind::Implicit`][implicit]. | `fn foo(x: &u32) -> &u32)`- A single `ty::Ty`. The `ty::Ty` has the hidden lifetime param. |
-[implicit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.LifetimeName.html#variant.Implicit
+[implicit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.LifetimeKind.html#variant.Implicit
**Order**
@@ -323,4 +323,4 @@
- Generic parameters: `{name}/#{index}` e.g. `T/#0`, where `index` corresponds to its position in the list of generic parameters
- Inference variables: `?{id}` e.g. `?x`/`?0`, where `id` identifies the inference variable
- Variables from binders: `^{binder}_{index}` e.g. `^0_x`/`^0_2`, where `binder` and `index` identify which variable from which binder is being referred to
-- Placeholders: `!{id}` or `!{id}_{universe}` e.g. `!x`/`!0`/`!x_2`/`!0_2`, representing some unique type in the specified universe. The universe is often elided when it is `0`
\ No newline at end of file
+- Placeholders: `!{id}` or `!{id}_{universe}` e.g. `!x`/`!0`/`!x_2`/`!0_2`, representing some unique type in the specified universe. The universe is often elided when it is `0`
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 9bb64ad..cf41f5b8 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -78,6 +78,7 @@
- [illumos](platform-support/illumos.md)
- [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
- [loongarch\*-unknown-none\*](platform-support/loongarch-none.md)
+ - [\*-lynxos178-\*](platform-support/lynxos178.md)
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
- [m68k-unknown-none-elf](platform-support/m68k-unknown-none-elf.md)
- [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 8c1769a..a3b70e7 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -110,6 +110,19 @@
If this flag is not specified, a dlltool executable will be inferred based on
the host environment and target.
+## dwarf-version
+
+This option controls the version of DWARF that the compiler emits, on platforms
+that use DWARF to encode debug information. It takes one of the following
+values:
+
+* `2`: DWARF version 2 (the default on certain platforms, like Android).
+* `3`: DWARF version 3 (the default on certain platforms, like AIX).
+* `4`: DWARF version 4 (the default on most platforms, like Linux & macOS).
+* `5`: DWARF version 5.
+
+DWARF version 1 is not supported.
+
## embed-bitcode
This flag controls whether or not the compiler embeds LLVM bitcode into object
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 4149b4c..9870e50 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -407,6 +407,7 @@
[`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI)
[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
+[`x86_64-lynx-lynxos178`](platform-support/lynxos178.md) | | | x86_64 LynxOS-178
[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ✓ | | 64-bit x86 Cygwin |
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) |
[`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) |
diff --git a/src/doc/rustc/src/platform-support/lynxos178.md b/src/doc/rustc/src/platform-support/lynxos178.md
new file mode 100644
index 0000000..6463f95
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/lynxos178.md
@@ -0,0 +1,77 @@
+# `*-lynxos178-*`
+
+**Tier: 3**
+
+Targets for the LynxOS-178 operating system.
+
+[LynxOS-178](https://www.lynx.com/products/lynxos-178-do-178c-certified-posix-rtos)
+is a commercial RTOS designed for safety-critical real-time systems. It is
+developed by Lynx Software Technologies as part of the
+[MOSA.ic](https://www.lynx.com/solutions/safe-and-secure-operating-environment)
+product suite.
+
+Target triples available:
+- `x86_64-lynx-lynxos178`
+
+## Target maintainers
+
+- Renat Fatykhov, https://github.com/rfatykhov-lynx
+
+## Requirements
+
+To build Rust programs for LynxOS-178, you must first have LYNX MOSA.ic
+installed on the build machine.
+
+This target supports only cross-compilation, from the same hosts supported by
+the Lynx CDK.
+
+Currently only `no_std` programs are supported. Work to support `std` is in
+progress.
+
+## Building the target
+
+You can build Rust with support for x86_64-lynx-lynxos178 by adding that
+to the `target` list in `config.toml`, and then running `./x build --target
+x86_64-lynx-lynxos178 compiler`.
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will need to build Rust with the target enabled (see "Building
+the target" above).
+
+Before executing `cargo`, you must configure the environment to build LynxOS-178
+binaries by running `source setup.sh` from the los178 directory.
+
+If your program/crates contain procedural macros, Rust must be able to build
+binaries for the host as well. The host gcc is hidden by sourcing setup.sh. To
+deal with this, add the following to your project's `.cargo/config.toml`:
+```toml
+[target.x86_64-unknown-linux-gnu]
+linker = "lynx-host-gcc"
+```
+(If necessary substitute your host target triple for x86_64-unknown-linux-gnu.)
+
+To point `cargo` at the correct rustc binary, set the RUSTC environment
+variable.
+
+The core library should be usable. You can try by building it as part of your
+project:
+```bash
+cargo +nightly build -Z build-std=core --target x86_64-lynx-lynxos178
+```
+
+## Testing
+
+Binaries built with rust can be provided to a LynxOS-178 instance on its file
+system, where they can be executed. Rust binaries tend to be large, so it may
+be necessary to strip them first.
+
+It is possible to run the Rust testsuite by providing a test runner that takes
+the test binary and executes it under LynxOS-178. Most (all?) tests won't run
+without std support though, which is not yet supported.
+
+## Cross-compilation toolchains and C code
+
+LYNX MOSA.ic comes with all the tools required to cross-compile C code for
+LynxOS-178.
diff --git a/src/doc/unstable-book/src/compiler-flags/allow-features.md b/src/doc/unstable-book/src/compiler-flags/allow-features.md
new file mode 100644
index 0000000..84fa465
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/allow-features.md
@@ -0,0 +1,14 @@
+# `allow-features`
+
+This feature is perma-unstable and has no tracking issue.
+
+----
+
+This flag allows limiting the features which can be enabled with `#![feature(...)]` attributes.
+By default, all features are allowed on nightly and no features are allowed on stable or beta (but see [`RUSTC_BOOTSTRAP`]).
+
+Features are comma-separated, for example `-Z allow-features=ffi_pure,f16`.
+If the flag is present, any feature listed will be allowed and any feature not listed will be disallowed.
+Any unrecognized feature is ignored.
+
+[`RUSTC_BOOTSTRAP`]: ./rustc-bootstrap.html
diff --git a/src/doc/unstable-book/src/compiler-flags/dwarf-version.md b/src/doc/unstable-book/src/compiler-flags/dwarf-version.md
deleted file mode 100644
index e88799d..0000000
--- a/src/doc/unstable-book/src/compiler-flags/dwarf-version.md
+++ /dev/null
@@ -1,13 +0,0 @@
-## `dwarf-version`
-
-The tracking issue for this feature is: <https://github.com/rust-lang/rust/issues/103057>
-
-----------------------------
-
-This option controls the version of DWARF that the compiler emits, on platforms
-that use DWARF to encode debug information. It takes one of the following
-values:
-
-* `2`: DWARF version 2 (the default on certain platforms, like macOS).
-* `4`: DWARF version 4 (the default on certain platforms, like Linux).
-* `5`: DWARF version 5.
diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md b/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md
new file mode 100644
index 0000000..6895f23
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md
@@ -0,0 +1,56 @@
+# `RUSTC_BOOTSTRAP`
+
+This feature is perma-unstable and has no tracking issue.
+
+----
+
+The `RUSTC_BOOTSTRAP` environment variable tells rustc to act as if it is a nightly compiler;
+in particular, it allows `#![feature(...)]` attributes and `-Z` flags even on the stable release channel.
+
+Setting `RUSTC_BOOTSTRAP=1` instructs rustc to enable this for all crates.
+Setting `RUSTC_BOOTSTRAP=crate_name` instructs rustc to only apply this to crates named `crate_name`.
+Setting `RUSTC_BOOTSTRAP=-1` instructs rustc to act as if it is a stable compiler, even on the nightly release channel.
+Cargo disallows setting `cargo::rustc-env=RUSTC_BOOTSTRAP` in build scripts.
+Build systems can limit the features they enable with [`-Z allow-features=feature1,feature2`][Z-allow-features].
+Crates can fully opt out of unstable features by using [`#![forbid(unstable_features)]`][unstable-features] at the crate root (or any other way of enabling lints, such as `-F unstable-features`).
+
+[Z-allow-features]: ./allow-features.html
+[unstable-features]: ../../rustc/lints/listing/allowed-by-default.html#unstable-features
+
+## Why does this environment variable exist?
+
+`RUSTC_BOOTSTRAP`, as the name suggests, is used for bootstrapping the compiler from an earlier version.
+In particular, nightly is built with beta, and beta is built with stable.
+Since the standard library and compiler both use unstable features, `RUSTC_BOOTSTRAP` is required so that we can use the previous version to build them.
+
+## Why is this environment variable so easy to use for people not in the rust project?
+
+Originally, `RUSTC_BOOTSTRAP` required passing in a hash of the previous compiler version, to discourage using it for any purpose other than bootstrapping.
+That constraint was later relaxed; see <https://github.com/rust-lang/rust/issues/36548> for the discussion that happened at that time.
+
+People have at various times proposed re-adding the technical constraints.
+However, doing so is extremely disruptive for several major projects that we very much want to keep using the latest stable toolchain version, such as Firefox, Rust for Linux, and Chromium.
+We continue to allow `RUSTC_BOOTSTRAP` until we can come up with an alternative that does not disrupt our largest constituents.
+
+## Stability policy
+
+Despite being usable on stable, this is an unstable feature.
+Like any other unstable feature, we reserve the right to change or remove this feature in the future, as well as any other unstable feature that it enables.
+Using this feature opts you out of the normal stability/backwards compatibility guarantee of stable.
+
+Although we do not take technical measures to prevent it from being used, we strongly discourage using this feature.
+If at all possible, please contribute to stabilizing the features you care about instead of bypassing the Rust project's stability policy.
+
+For library crates, we especially discourage the use of this feature.
+The crates depending on you do not know that you use this feature, have little recourse if it breaks, and can be used in contexts that are hard to predict.
+
+For libraries that do use this feature, please document the versions you support (including a *maximum* as well as minimum version), and a mechanism to disable it.
+If you do not have a mechanism to disable the use of `RUSTC_BOOTSTRAP`, consider removing its use altogether, such that people can only use your library if they are already using a nightly toolchain.
+This leaves the choice of whether to opt-out of Rust's stability guarantees up to the end user building their code.
+
+## History
+
+- [Allowed without a hash](https://github.com/rust-lang/rust/pull/37265) ([discussion](https://github.com/rust-lang/rust/issues/36548))
+- [Extended to crate names](https://github.com/rust-lang/rust/pull/77802) ([discussion](https://github.com/rust-lang/cargo/issues/7088))
+- [Disallowed for build scripts](https://github.com/rust-lang/cargo/pull/9181) ([discussion](https://github.com/rust-lang/compiler-team/issues/350))
+- [Extended to emulate stable](https://github.com/rust-lang/rust/pull/132993) ([discussion](https://github.com/rust-lang/rust/issues/123404))
diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md b/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md
new file mode 100644
index 0000000..3d867b5
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md
@@ -0,0 +1,39 @@
+# `RUSTC_OVERRIDE_VERSION_STRING`
+
+This feature is perma-unstable and has no tracking issue.
+
+----
+
+The `RUSTC_OVERRIDE_VERSION_STRING` environment variable overrides the version reported by `rustc --version`. For example:
+
+```console
+$ rustc --version
+rustc 1.87.0-nightly (43f0014ef 2025-03-25)
+$ env RUSTC_OVERRIDE_VERSION_STRING=1.81.0-nightly rustc --version
+rustc 1.81.0-nightly
+```
+
+Note that the version string is completely overwritten; i.e. rustc discards commit hash and commit date information unless it is explicitly included in the environment variable. The string only applies to the "release" part of the version; for example:
+```console
+$ RUSTC_OVERRIDE_VERSION_STRING="1.81.0-nightly (aaaaaaaaa 2025-03-22)" rustc -vV
+rustc 1.81.0-nightly (aaaaaaaaa 2025-03-22)
+binary: rustc
+commit-hash: 43f0014ef0f242418674f49052ed39b70f73bc1c
+commit-date: 2025-03-25
+host: x86_64-unknown-linux-gnu
+release: 1.81.0-nightly (aaaaaaaaa 2025-03-22)
+LLVM version: 20.1.1
+```
+
+Note here that `commit-hash` and `commit-date` do not match the values in the string, and `release` includes the fake hash and date.
+
+This variable has no effect on whether or not unstable features are allowed to be used. It only affects the output of `--version`.
+
+## Why does this environment variable exist?
+
+Various library crates have incomplete or incorrect feature detection.
+This environment variable allows bisecting crates that do incorrect detection with `version_check::supports_feature`.
+
+This is not intended to be used for any other case (and, except for bisection, is not particularly useful).
+
+See <https://github.com/rust-lang/rust/pull/124339> for further discussion.
diff --git a/src/doc/unstable-book/src/language-features/box-patterns.md b/src/doc/unstable-book/src/language-features/box-patterns.md
index a1ac096..c8a15b8 100644
--- a/src/doc/unstable-book/src/language-features/box-patterns.md
+++ b/src/doc/unstable-book/src/language-features/box-patterns.md
@@ -6,6 +6,8 @@
------------------------
+> **Note**: This feature will be superseded by [`deref_patterns`] in the future.
+
Box patterns let you match on `Box<T>`s:
@@ -28,3 +30,5 @@
}
}
```
+
+[`deref_patterns`]: ./deref-patterns.md
diff --git a/src/doc/unstable-book/src/language-features/cfg-boolean-literals.md b/src/doc/unstable-book/src/language-features/cfg-boolean-literals.md
deleted file mode 100644
index ad795ff..0000000
--- a/src/doc/unstable-book/src/language-features/cfg-boolean-literals.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# `cfg_boolean_literals`
-
-The tracking issue for this feature is: [#131204]
-
-[#131204]: https://github.com/rust-lang/rust/issues/131204
-
-------------------------
-
-The `cfg_boolean_literals` feature makes it possible to use the `true`/`false`
-literal as cfg predicate. They always evaluate to true/false respectively.
-
-## Examples
-
-```rust
-#![feature(cfg_boolean_literals)]
-
-#[cfg(true)]
-const A: i32 = 5;
-
-#[cfg(all(false))]
-const A: i32 = 58 * 89;
-```
diff --git a/src/doc/unstable-book/src/language-features/deref-patterns.md b/src/doc/unstable-book/src/language-features/deref-patterns.md
new file mode 100644
index 0000000..d0102a6
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/deref-patterns.md
@@ -0,0 +1,57 @@
+# `deref_patterns`
+
+The tracking issue for this feature is: [#87121]
+
+[#87121]: https://github.com/rust-lang/rust/issues/87121
+
+------------------------
+
+> **Note**: This feature is incomplete. In the future, it is meant to supersede
+> [`box_patterns`](./box-patterns.md) and [`string_deref_patterns`](./string-deref-patterns.md).
+
+This feature permits pattern matching on [smart pointers in the standard library] through their
+`Deref` target types, either implicitly or with explicit `deref!(_)` patterns (the syntax of which
+is currently a placeholder).
+
+```rust
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+let mut v = vec![Box::new(Some(0))];
+
+// Implicit dereferences are inserted when a pattern can match against the
+// result of repeatedly dereferencing but can't match against a smart
+// pointer itself. This works alongside match ergonomics for references.
+if let [Some(x)] = &mut v {
+ *x += 1;
+}
+
+// Explicit `deref!(_)` patterns may instead be used when finer control is
+// needed, e.g. to dereference only a single smart pointer, or to bind the
+// the result of dereferencing to a variable.
+if let deref!([deref!(opt_x @ Some(1))]) = &mut v {
+ opt_x.as_mut().map(|x| *x += 1);
+}
+
+assert_eq!(v, [Box::new(Some(2))]);
+```
+
+Without this feature, it may be necessary to introduce temporaries to represent dereferenced places
+when matching on nested structures:
+
+```rust
+let mut v = vec![Box::new(Some(0))];
+if let [b] = &mut *v {
+ if let Some(x) = &mut **b {
+ *x += 1;
+ }
+}
+if let [b] = &mut *v {
+ if let opt_x @ Some(1) = &mut **b {
+ opt_x.as_mut().map(|x| *x += 1);
+ }
+}
+assert_eq!(v, [Box::new(Some(2))]);
+```
+
+[smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors
diff --git a/src/doc/unstable-book/src/language-features/explicit-extern-abis.md b/src/doc/unstable-book/src/language-features/explicit-extern-abis.md
new file mode 100644
index 0000000..ba62246
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/explicit-extern-abis.md
@@ -0,0 +1,23 @@
+# `explicit_extern_abis`
+
+The tracking issue for this feature is: #134986
+
+------
+
+Disallow `extern` without an explicit ABI. We should write `extern "C"`
+(or another ABI) instead of just `extern`.
+
+By making the ABI explicit, it becomes much clearer that "C" is just one of the
+possible choices, rather than the "standard" way for external functions.
+Removing the default makes it easier to add a new ABI on equal footing as "C".
+
+```rust,editionfuture,compile_fail
+#![feature(explicit_extern_abis)]
+
+extern fn function1() {} // ERROR `extern` declarations without an explicit ABI
+ // are disallowed
+
+extern "C" fn function2() {} // compiles
+
+extern "aapcs" fn function3() {} // compiles
+```
diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md
new file mode 100644
index 0000000..b6dbdb1
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md
@@ -0,0 +1,133 @@
+# `macro_metavar_expr_concat`
+
+The tracking issue for this feature is: [#124225]
+
+------------------------
+
+In stable Rust, there is no way to create new identifiers by joining identifiers to literals or other identifiers without using procedural macros such as [`paste`].
+ `#![feature(macro_metavar_expr_concat)]` introduces a way to do this, using the concat metavariable expression.
+
+> This feature uses the syntax from [`macro_metavar_expr`] but is otherwise
+> independent. It replaces the old unstable feature [`concat_idents`].
+
+> This is an experimental feature; it and its syntax will require a RFC before stabilization.
+
+
+### Overview
+
+`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable expression for creating new identifiers:
+
+```rust
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! create_some_structs {
+ ($name:ident) => {
+ pub struct ${ concat(First, $name) };
+ pub struct ${ concat(Second, $name) };
+ pub struct ${ concat(Third, $name) };
+ }
+}
+
+create_some_structs!(Thing);
+```
+
+This macro invocation expands to:
+
+```rust
+pub struct FirstThing;
+pub struct SecondThing;
+pub struct ThirdThing;
+```
+
+### Syntax
+
+This feature builds upon the metavariable expression syntax `${ .. }` as specified in [RFC 3086] ([`macro_metavar_expr`]).
+ `concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or literals.
+
+### Examples
+
+#### Create a function or method with a concatenated name
+
+```rust
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! make_getter {
+ ($name:ident, $field: ident, $ret:ty) => {
+ impl $name {
+ pub fn ${ concat(get_, $field) }(&self) -> &$ret {
+ &self.$field
+ }
+ }
+ }
+}
+
+pub struct Thing {
+ description: String,
+}
+
+make_getter!(Thing, description, String);
+```
+
+This expands to:
+
+```rust
+pub struct Thing {
+ description: String,
+}
+
+impl Thing {
+ pub fn get_description(&self) -> &String {
+ &self.description
+ }
+}
+```
+
+#### Create names for macro generated tests
+
+```rust
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! test_math {
+ ($integer:ident) => {
+ #[test]
+ fn ${ concat(test_, $integer, _, addition) } () {
+ let a: $integer = 73;
+ let b: $integer = 42;
+ assert_eq!(a + b, 115)
+ }
+
+ #[test]
+ fn ${ concat(test_, $integer, _, subtraction) } () {
+ let a: $integer = 73;
+ let b: $integer = 42;
+ assert_eq!(a - b, 31)
+ }
+ }
+}
+
+test_math!(i32);
+test_math!(u64);
+test_math!(u128);
+```
+
+Running this returns the following output:
+
+```text
+running 6 tests
+test test_i32_subtraction ... ok
+test test_i32_addition ... ok
+test test_u128_addition ... ok
+test test_u128_subtraction ... ok
+test test_u64_addition ... ok
+test test_u64_subtraction ... ok
+
+test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+```
+
+[`paste`]: https://crates.io/crates/paste
+[RFC 3086]: https://rust-lang.github.io/rfcs/3086-macro-metavar-expr.html
+[`concat_idents!`]: https://doc.rust-lang.org/nightly/std/macro.concat_idents.html
+[`macro_metavar_expr`]: ../language-features/macro-metavar-expr.md
+[`concat_idents`]: ../library-features/concat-idents.md
+[#124225]: https://github.com/rust-lang/rust/issues/124225
+[declarative macros]: https://doc.rust-lang.org/stable/reference/macros-by-example.html
diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr.md
new file mode 100644
index 0000000..7ce64c1
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr.md
@@ -0,0 +1,10 @@
+# `macro_metavar_expr`
+
+The tracking issue for this feature is: [#83527]
+
+------------------------
+
+> This feature is not to be confused with [`macro_metavar_expr_concat`].
+
+[`macro_metavar_expr_concat`]: ./macro-metavar-expr-concat.md
+[#83527]: https://github.com/rust-lang/rust/issues/83527
diff --git a/src/doc/unstable-book/src/language-features/string-deref-patterns.md b/src/doc/unstable-book/src/language-features/string-deref-patterns.md
index 3723830..366bb15 100644
--- a/src/doc/unstable-book/src/language-features/string-deref-patterns.md
+++ b/src/doc/unstable-book/src/language-features/string-deref-patterns.md
@@ -6,6 +6,8 @@
------------------------
+> **Note**: This feature will be superseded by [`deref_patterns`] in the future.
+
This feature permits pattern matching `String` to `&str` through [its `Deref` implementation].
```rust
@@ -42,4 +44,5 @@
}
```
+[`deref_patterns`]: ./deref-patterns.md
[its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String
diff --git a/src/doc/unstable-book/src/library-features/concat-idents.md b/src/doc/unstable-book/src/library-features/concat-idents.md
index 73f6cfa..4366172 100644
--- a/src/doc/unstable-book/src/library-features/concat-idents.md
+++ b/src/doc/unstable-book/src/library-features/concat-idents.md
@@ -6,6 +6,8 @@
------------------------
+> This feature is expected to be superseded by [`macro_metavar_expr_concat`](../language-features/macro-metavar-expr-concat.md).
+
The `concat_idents` feature adds a macro for concatenating multiple identifiers
into one identifier.
diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis
index 8a441cf..8fe87a9 100644
--- a/src/etc/natvis/libcore.natvis
+++ b/src/etc/natvis/libcore.natvis
@@ -69,9 +69,9 @@
</Type>
<Type Name="core::pin::Pin<*>">
- <DisplayString>Pin({(void*)__pointer}: {__pointer})</DisplayString>
+ <DisplayString>Pin({(void*)pointer}: {pointer})</DisplayString>
<Expand>
- <ExpandedItem>__pointer</ExpandedItem>
+ <ExpandedItem>pointer</ExpandedItem>
</Expand>
</Type>
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3a2b697..55a116a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -67,9 +67,13 @@ pub(crate) fn try_inline(
record_extern_fqn(cx, did, ItemType::Trait);
cx.with_param_env(did, |cx| {
build_impls(cx, did, attrs_without_docs, &mut ret);
- clean::TraitItem(Box::new(build_external_trait(cx, did)))
+ clean::TraitItem(Box::new(build_trait(cx, did)))
})
}
+ Res::Def(DefKind::TraitAlias, did) => {
+ record_extern_fqn(cx, did, ItemType::TraitAlias);
+ cx.with_param_env(did, |cx| clean::TraitAliasItem(build_trait_alias(cx, did)))
+ }
Res::Def(DefKind::Fn, did) => {
record_extern_fqn(cx, did, ItemType::Function);
cx.with_param_env(did, |cx| {
@@ -251,7 +255,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
}
}
-pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
+pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
let trait_items = cx
.tcx
.associated_items(did)
@@ -263,11 +267,18 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
let predicates = cx.tcx.predicates_of(did);
let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
let generics = filter_non_trait_generics(did, generics);
- let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
+ let (generics, supertrait_bounds) = separate_self_bounds(generics);
clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
}
-pub(crate) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
+fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
+ let predicates = cx.tcx.predicates_of(did);
+ let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
+ let (generics, bounds) = separate_self_bounds(generics);
+ clean::TraitAlias { generics, bounds }
+}
+
+pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
let sig = cx.tcx.fn_sig(def_id).instantiate_identity();
// The generics need to be cleaned before the signature.
let mut generics =
@@ -490,17 +501,17 @@ pub(crate) fn build_impl(
return true;
}
if let Some(associated_trait) = associated_trait {
- let assoc_kind = match item.kind {
- hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
- hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn,
- hir::ImplItemKind::Type(..) => ty::AssocKind::Type,
+ let assoc_tag = match item.kind {
+ hir::ImplItemKind::Const(..) => ty::AssocTag::Const,
+ hir::ImplItemKind::Fn(..) => ty::AssocTag::Fn,
+ hir::ImplItemKind::Type(..) => ty::AssocTag::Type,
};
let trait_item = tcx
.associated_items(associated_trait.def_id)
.find_by_ident_and_kind(
tcx,
item.ident,
- assoc_kind,
+ assoc_tag,
associated_trait.def_id,
)
.unwrap(); // SAFETY: For all impl items there exists trait item that has the same name.
@@ -527,7 +538,7 @@ pub(crate) fn build_impl(
.find_by_ident_and_kind(
tcx,
item.ident(tcx),
- item.kind,
+ item.as_tag(),
associated_trait.def_id,
)
.unwrap(); // corresponding associated item has to exist
@@ -788,12 +799,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
g
}
-/// Supertrait bounds for a trait are also listed in the generics coming from
-/// the metadata for a crate, so we want to separate those out and create a new
-/// list of explicit supertrait bounds to render nicely.
-fn separate_supertrait_bounds(
- mut g: clean::Generics,
-) -> (clean::Generics, Vec<clean::GenericBound>) {
+fn separate_self_bounds(mut g: clean::Generics) -> (clean::Generics, Vec<clean::GenericBound>) {
let mut ty_bounds = Vec::new();
g.where_predicates.retain(|pred| match *pred {
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
@@ -806,22 +812,17 @@ fn separate_supertrait_bounds(
}
pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
- if did.is_local() {
+ if did.is_local()
+ || cx.external_traits.contains_key(&did)
+ || cx.active_extern_traits.contains(&did)
+ {
return;
}
- {
- if cx.external_traits.contains_key(&did) || cx.active_extern_traits.contains(&did) {
- return;
- }
- }
-
- {
- cx.active_extern_traits.insert(did);
- }
+ cx.active_extern_traits.insert(did);
debug!("record_extern_trait: {did:?}");
- let trait_ = build_external_trait(cx, did);
+ let trait_ = build_trait(cx, did);
cx.external_traits.insert(did, trait_);
cx.active_extern_traits.remove(&did);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 45a9157..034ecb2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -117,7 +117,14 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
hir::ItemKind::Use(path, kind) => {
let hir::UsePath { segments, span, .. } = *path;
let path = hir::Path { segments, res: *res, span };
- clean_use_statement_inner(import, name, &path, kind, cx, &mut Default::default())
+ clean_use_statement_inner(
+ import,
+ Some(name),
+ &path,
+ kind,
+ cx,
+ &mut Default::default(),
+ )
}
_ => unreachable!(),
}
@@ -125,8 +132,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
// Now we actually lower the imports, skipping everything else.
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
- let name = renamed.unwrap_or(kw::Empty); // using kw::Empty is a bit of a hack
- clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted)
+ clean_use_statement(item, *renamed, path, hir::UseKind::Glob, cx, &mut inserted)
} else {
// skip everything else
Vec::new()
@@ -521,7 +527,7 @@ fn projection_to_path_segment<'tcx>(
let item = cx.tcx.associated_item(def_id);
let generics = cx.tcx.generics_of(def_id);
PathSegment {
- name: item.name,
+ name: item.name(),
args: GenericArgs::AngleBracketed {
args: clean_middle_generic_args(
cx,
@@ -1046,7 +1052,7 @@ fn clean_fn_or_proc_macro<'tcx>(
match macro_kind {
Some(kind) => clean_proc_macro(item, name, kind, cx),
None => {
- let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id));
+ let mut func = clean_function(cx, sig, generics, ParamsSrc::Body(body_id));
clean_fn_decl_legacy_const_generics(&mut func, attrs);
FunctionItem(func)
}
@@ -1065,17 +1071,12 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib
for (pos, literal) in meta_item_list.iter().filter_map(|meta| meta.lit()).enumerate() {
match literal.kind {
ast::LitKind::Int(a, _) => {
- let param = func.generics.params.remove(0);
- if let GenericParamDef {
- name,
- kind: GenericParamDefKind::Const { ty, .. },
- ..
- } = param
- {
- func.decl
- .inputs
- .values
- .insert(a.get() as _, Argument { name, type_: *ty, is_const: true });
+ let GenericParamDef { name, kind, .. } = func.generics.params.remove(0);
+ if let GenericParamDefKind::Const { ty, .. } = kind {
+ func.decl.inputs.insert(
+ a.get() as _,
+ Parameter { name: Some(name), type_: *ty, is_const: true },
+ );
} else {
panic!("unexpected non const in position {pos}");
}
@@ -1086,7 +1087,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib
}
}
-enum FunctionArgs<'tcx> {
+enum ParamsSrc<'tcx> {
Body(hir::BodyId),
Idents(&'tcx [Option<Ident>]),
}
@@ -1095,86 +1096,62 @@ fn clean_function<'tcx>(
cx: &mut DocContext<'tcx>,
sig: &hir::FnSig<'tcx>,
generics: &hir::Generics<'tcx>,
- args: FunctionArgs<'tcx>,
+ params: ParamsSrc<'tcx>,
) -> Box<Function> {
let (generics, decl) = enter_impl_trait(cx, |cx| {
- // NOTE: generics must be cleaned before args
+ // NOTE: Generics must be cleaned before params.
let generics = clean_generics(generics, cx);
- let args = match args {
- FunctionArgs::Body(body_id) => {
- clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id)
- }
- FunctionArgs::Idents(idents) => {
- clean_args_from_types_and_names(cx, sig.decl.inputs, idents)
- }
+ let params = match params {
+ ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id),
+ // Let's not perpetuate anon params from Rust 2015; use `_` for them.
+ ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents, |ident| {
+ Some(ident.map_or(kw::Underscore, |ident| ident.name))
+ }),
};
- let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args);
+ let decl = clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params);
(generics, decl)
});
Box::new(Function { decl, generics })
}
-fn clean_args_from_types_and_names<'tcx>(
+fn clean_params<'tcx>(
cx: &mut DocContext<'tcx>,
types: &[hir::Ty<'tcx>],
idents: &[Option<Ident>],
-) -> Arguments {
- fn nonempty_name(ident: &Option<Ident>) -> Option<Symbol> {
- if let Some(ident) = ident
- && ident.name != kw::Underscore
- {
- Some(ident.name)
- } else {
- None
- }
- }
-
- // If at least one argument has a name, use `_` as the name of unnamed
- // arguments. Otherwise omit argument names.
- let default_name = if idents.iter().any(|ident| nonempty_name(ident).is_some()) {
- kw::Underscore
- } else {
- kw::Empty
- };
-
- Arguments {
- values: types
- .iter()
- .enumerate()
- .map(|(i, ty)| Argument {
- type_: clean_ty(ty, cx),
- name: idents.get(i).and_then(nonempty_name).unwrap_or(default_name),
- is_const: false,
- })
- .collect(),
- }
+ postprocess: impl Fn(Option<Ident>) -> Option<Symbol>,
+) -> Vec<Parameter> {
+ types
+ .iter()
+ .enumerate()
+ .map(|(i, ty)| Parameter {
+ name: postprocess(idents[i]),
+ type_: clean_ty(ty, cx),
+ is_const: false,
+ })
+ .collect()
}
-fn clean_args_from_types_and_body_id<'tcx>(
+fn clean_params_via_body<'tcx>(
cx: &mut DocContext<'tcx>,
types: &[hir::Ty<'tcx>],
body_id: hir::BodyId,
-) -> Arguments {
- let body = cx.tcx.hir_body(body_id);
-
- Arguments {
- values: types
- .iter()
- .zip(body.params)
- .map(|(ty, param)| Argument {
- name: name_from_pat(param.pat),
- type_: clean_ty(ty, cx),
- is_const: false,
- })
- .collect(),
- }
+) -> Vec<Parameter> {
+ types
+ .iter()
+ .zip(cx.tcx.hir_body(body_id).params)
+ .map(|(ty, param)| Parameter {
+ name: Some(name_from_pat(param.pat)),
+ type_: clean_ty(ty, cx),
+ is_const: false,
+ })
+ .collect()
}
-fn clean_fn_decl_with_args<'tcx>(
+fn clean_fn_decl_with_params<'tcx>(
cx: &mut DocContext<'tcx>,
decl: &hir::FnDecl<'tcx>,
header: Option<&hir::FnHeader>,
- args: Arguments,
+ params: Vec<Parameter>,
) -> FnDecl {
let mut output = match decl.output {
hir::FnRetTy::Return(typ) => clean_ty(typ, cx),
@@ -1185,7 +1162,7 @@ fn clean_fn_decl_with_args<'tcx>(
{
output = output.sugared_async_return_type();
}
- FnDecl { inputs: args, output, c_variadic: decl.c_variadic }
+ FnDecl { inputs: params, output, c_variadic: decl.c_variadic }
}
fn clean_poly_fn_sig<'tcx>(
@@ -1193,10 +1170,6 @@ fn clean_poly_fn_sig<'tcx>(
did: Option<DefId>,
sig: ty::PolyFnSig<'tcx>,
) -> FnDecl {
- let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_idents(did)).iter();
-
- // We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
- // but shouldn't change any code meaning.
let mut output = clean_middle_ty(sig.output(), cx, None, None);
// If the return type isn't an `impl Trait`, we can safely assume that this
@@ -1209,25 +1182,25 @@ fn clean_poly_fn_sig<'tcx>(
output = output.sugared_async_return_type();
}
- FnDecl {
- output,
- c_variadic: sig.skip_binder().c_variadic,
- inputs: Arguments {
- values: sig
- .inputs()
- .iter()
- .map(|t| Argument {
- type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None),
- name: if let Some(Some(ident)) = names.next() {
- ident.name
- } else {
- kw::Underscore
- },
- is_const: false,
- })
- .collect(),
- },
- }
+ let mut idents = did.map(|did| cx.tcx.fn_arg_idents(did)).unwrap_or_default().iter().copied();
+
+ // If this comes from a fn item, let's not perpetuate anon params from Rust 2015; use `_` for them.
+ // If this comes from a fn ptr ty, we just keep params unnamed since it's more conventional stylistically.
+ // Since the param name is not part of the semantic type, these params never bear a name unlike
+ // in the HIR case, thus we can't peform any fancy fallback logic unlike `clean_bare_fn_ty`.
+ let fallback = did.map(|_| kw::Underscore);
+
+ let params = sig
+ .inputs()
+ .iter()
+ .map(|ty| Parameter {
+ name: idents.next().flatten().map(|ident| ident.name).or(fallback),
+ type_: clean_middle_ty(ty.map_bound(|ty| *ty), cx, None, None),
+ is_const: false,
+ })
+ .collect();
+
+ FnDecl { inputs: params, output, c_variadic: sig.skip_binder().c_variadic }
}
fn clean_trait_ref<'tcx>(trait_ref: &hir::TraitRef<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
@@ -1267,11 +1240,11 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
- let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
+ let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body));
MethodItem(m, None)
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => {
- let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Idents(idents));
+ let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Idents(idents));
RequiredMethodItem(m)
}
hir::TraitItemKind::Type(bounds, Some(default)) => {
@@ -1312,7 +1285,7 @@ pub(crate) fn clean_impl_item<'tcx>(
type_: clean_ty(ty, cx),
})),
hir::ImplItemKind::Fn(ref sig, body) => {
- let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
+ let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body));
let defaultness = cx.tcx.defaultness(impl_.owner_id);
MethodItem(m, Some(defaultness))
}
@@ -1340,7 +1313,7 @@ pub(crate) fn clean_impl_item<'tcx>(
pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocContext<'_>) -> Item {
let tcx = cx.tcx;
let kind = match assoc_item.kind {
- ty::AssocKind::Const => {
+ ty::AssocKind::Const { .. } => {
let ty = clean_middle_ty(
ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()),
cx,
@@ -1374,24 +1347,24 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
}
}
}
- ty::AssocKind::Fn => {
+ ty::AssocKind::Fn { has_self, .. } => {
let mut item = inline::build_function(cx, assoc_item.def_id);
- if assoc_item.fn_has_self_parameter {
+ if has_self {
let self_ty = match assoc_item.container {
ty::AssocItemContainer::Impl => {
tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity()
}
ty::AssocItemContainer::Trait => tcx.types.self_param,
};
- let self_arg_ty =
+ let self_param_ty =
tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
- if self_arg_ty == self_ty {
- item.decl.inputs.values[0].type_ = SelfTy;
- } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind()
+ if self_param_ty == self_ty {
+ item.decl.inputs[0].type_ = SelfTy;
+ } else if let ty::Ref(_, ty, _) = *self_param_ty.kind()
&& ty == self_ty
{
- match item.decl.inputs.values[0].type_ {
+ match item.decl.inputs[0].type_ {
BorrowedRef { ref mut type_, .. } => **type_ = SelfTy,
_ => unreachable!(),
}
@@ -1412,8 +1385,8 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
RequiredMethodItem(item)
}
}
- ty::AssocKind::Type => {
- let my_name = assoc_item.name;
+ ty::AssocKind::Type { .. } => {
+ let my_name = assoc_item.name();
fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
match (¶m.kind, arg) {
@@ -1554,7 +1527,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
}
};
- Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx)
+ Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx)
}
fn first_non_private_clean_path<'tcx>(
@@ -2223,7 +2196,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
Type::QPath(Box::new(QPathData {
assoc: PathSegment {
- name: cx.tcx.associated_item(def_id).name,
+ name: cx.tcx.associated_item(def_id).name(),
args: GenericArgs::AngleBracketed {
args: clean_middle_generic_args(
cx,
@@ -2605,15 +2578,25 @@ fn clean_bare_fn_ty<'tcx>(
cx: &mut DocContext<'tcx>,
) -> BareFunctionDecl {
let (generic_params, decl) = enter_impl_trait(cx, |cx| {
- // NOTE: generics must be cleaned before args
+ // NOTE: Generics must be cleaned before params.
let generic_params = bare_fn
.generic_params
.iter()
.filter(|p| !is_elided_lifetime(p))
.map(|x| clean_generic_param(cx, None, x))
.collect();
- let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_idents);
- let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args);
+ // Since it's more conventional stylistically, elide the name of all params called `_`
+ // unless there's at least one interestingly named param in which case don't elide any
+ // name since mixing named and unnamed params is less legible.
+ let filter = |ident: Option<Ident>| {
+ ident.map(|ident| ident.name).filter(|&ident| ident != kw::Underscore)
+ };
+ let fallback =
+ bare_fn.param_idents.iter().copied().find_map(filter).map(|_| kw::Underscore);
+ let params = clean_params(cx, bare_fn.decl.inputs, bare_fn.param_idents, |ident| {
+ filter(ident).or(fallback)
+ });
+ let decl = clean_fn_decl_with_params(cx, bare_fn.decl, None, params);
(generic_params, decl)
});
BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params }
@@ -2623,7 +2606,6 @@ fn clean_unsafe_binder_ty<'tcx>(
unsafe_binder_ty: &hir::UnsafeBinderTy<'tcx>,
cx: &mut DocContext<'tcx>,
) -> UnsafeBinderTy {
- // NOTE: generics must be cleaned before args
let generic_params = unsafe_binder_ty
.generic_params
.iter()
@@ -2792,10 +2774,7 @@ fn clean_maybe_renamed_item<'tcx>(
use hir::ItemKind;
let def_id = item.owner_id.to_def_id();
- let mut name = renamed.unwrap_or_else(|| {
- // FIXME: using kw::Empty is a bit of a hack
- cx.tcx.hir_opt_name(item.hir_id()).unwrap_or(kw::Empty)
- });
+ let mut name = if renamed.is_some() { renamed } else { cx.tcx.hir_opt_name(item.hir_id()) };
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
@@ -2836,7 +2815,7 @@ fn clean_maybe_renamed_item<'tcx>(
item_type: Some(type_),
})),
item.owner_id.def_id.to_def_id(),
- name,
+ name.unwrap(),
import_id,
renamed,
));
@@ -2861,13 +2840,15 @@ fn clean_maybe_renamed_item<'tcx>(
}),
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
ItemKind::Macro(_, macro_def, MacroKind::Bang) => MacroItem(Macro {
- source: display_macro_source(cx, name, macro_def),
+ source: display_macro_source(cx, name.unwrap(), macro_def),
macro_rules: macro_def.macro_rules,
}),
- ItemKind::Macro(_, _, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
+ ItemKind::Macro(_, _, macro_kind) => {
+ clean_proc_macro(item, name.as_mut().unwrap(), macro_kind, cx)
+ }
// proc macros can have a name set by attributes
ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
- clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
+ clean_fn_or_proc_macro(item, sig, generics, body_id, name.as_mut().unwrap(), cx)
}
ItemKind::Trait(_, _, _, generics, bounds, item_ids) => {
let items = item_ids
@@ -2883,7 +2864,7 @@ fn clean_maybe_renamed_item<'tcx>(
}))
}
ItemKind::ExternCrate(orig_name, _) => {
- return clean_extern_crate(item, name, orig_name, cx);
+ return clean_extern_crate(item, name.unwrap(), orig_name, cx);
}
ItemKind::Use(path, kind) => {
return clean_use_statement(item, name, path, kind, cx, &mut FxHashSet::default());
@@ -2895,7 +2876,7 @@ fn clean_maybe_renamed_item<'tcx>(
cx,
kind,
item.owner_id.def_id.to_def_id(),
- name,
+ name.unwrap(),
import_id,
renamed,
)]
@@ -3006,7 +2987,7 @@ fn clean_extern_crate<'tcx>(
fn clean_use_statement<'tcx>(
import: &hir::Item<'tcx>,
- name: Symbol,
+ name: Option<Symbol>,
path: &hir::UsePath<'tcx>,
kind: hir::UseKind,
cx: &mut DocContext<'tcx>,
@@ -3023,7 +3004,7 @@ fn clean_use_statement<'tcx>(
fn clean_use_statement_inner<'tcx>(
import: &hir::Item<'tcx>,
- name: Symbol,
+ name: Option<Symbol>,
path: &hir::Path<'tcx>,
kind: hir::UseKind,
cx: &mut DocContext<'tcx>,
@@ -3042,7 +3023,7 @@ fn clean_use_statement_inner<'tcx>(
let visibility = cx.tcx.visibility(import.owner_id);
let attrs = cx.tcx.hir_attrs(import.hir_id());
let inline_attr = hir_attr_lists(attrs, sym::doc).get_word_attr(sym::inline);
- let pub_underscore = visibility.is_public() && name == kw::Underscore;
+ let pub_underscore = visibility.is_public() && name == Some(kw::Underscore);
let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
let import_def_id = import.owner_id.def_id;
@@ -3108,6 +3089,7 @@ fn clean_use_statement_inner<'tcx>(
}
Import::new_glob(resolve_use_source(cx, path), true)
} else {
+ let name = name.unwrap();
if inline_attr.is_none()
&& let Res::Def(DefKind::Mod, did) = path.res
&& !did.is_local()
@@ -3149,7 +3131,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem(
- clean_function(cx, &sig, generics, FunctionArgs::Idents(idents)),
+ clean_function(cx, &sig, generics, ParamsSrc::Idents(idents)),
sig.header.safety(),
),
hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem(
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 06e75fe..bbe11bf 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -517,7 +517,7 @@ pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
Some(RenderedLink {
original_text: s.clone(),
new_text: link_text.clone(),
- tooltip: link_tooltip(*id, fragment, cx),
+ tooltip: link_tooltip(*id, fragment, cx).to_string(),
href,
})
} else {
@@ -788,7 +788,7 @@ pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -
}
_ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
}
- } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
+ } else if attr.has_any_name(ALLOWED_ATTRIBUTES) {
Some(
rustc_hir_pretty::attribute_to_string(&tcx, attr)
.replace("\\\n", "")
@@ -1407,34 +1407,30 @@ pub(crate) struct Function {
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct FnDecl {
- pub(crate) inputs: Arguments,
+ pub(crate) inputs: Vec<Parameter>,
pub(crate) output: Type,
pub(crate) c_variadic: bool,
}
impl FnDecl {
pub(crate) fn receiver_type(&self) -> Option<&Type> {
- self.inputs.values.first().and_then(|v| v.to_receiver())
+ self.inputs.first().and_then(|v| v.to_receiver())
}
}
+/// A function parameter.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub(crate) struct Arguments {
- pub(crate) values: Vec<Argument>,
-}
-
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub(crate) struct Argument {
+pub(crate) struct Parameter {
+ pub(crate) name: Option<Symbol>,
pub(crate) type_: Type,
- pub(crate) name: Symbol,
/// This field is used to represent "const" arguments from the `rustc_legacy_const_generics`
/// feature. More information in <https://github.com/rust-lang/rust/issues/83167>.
pub(crate) is_const: bool,
}
-impl Argument {
+impl Parameter {
pub(crate) fn to_receiver(&self) -> Option<&Type> {
- if self.name == kw::SelfLower { Some(&self.type_) } else { None }
+ if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None }
}
}
@@ -2504,7 +2500,7 @@ pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet<Symbo
self.trait_
.as_ref()
.map(|t| t.def_id())
- .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
+ .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect())
.unwrap_or_default()
}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index afcca81..af7986d 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -234,7 +234,7 @@ pub(super) fn clean_middle_path<'tcx>(
args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> Path {
let def_kind = cx.tcx.def_kind(did);
- let name = cx.tcx.opt_item_name(did).unwrap_or(kw::Empty);
+ let name = cx.tcx.opt_item_name(did).unwrap_or(sym::dummy);
Path {
res: Res::Def(def_kind, did),
segments: thin_vec![PathSegment {
@@ -303,13 +303,12 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
debug!("trying to get a name from pattern: {p:?}");
Symbol::intern(&match &p.kind {
- // FIXME(never_patterns): does this make sense?
- PatKind::Missing => unreachable!(),
- PatKind::Wild
- | PatKind::Err(_)
+ PatKind::Err(_)
+ | PatKind::Missing // Let's not perpetuate anon params from Rust 2015; use `_` for them.
| PatKind::Never
+ | PatKind::Range(..)
| PatKind::Struct(..)
- | PatKind::Range(..) => {
+ | PatKind::Wild => {
return kw::Underscore;
}
PatKind::Binding(_, _, ident, _) => return ident.name,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index c4dea79..9d1c9ff 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -27,7 +27,7 @@
use rustc_span::symbol::sym;
use tracing::{debug, info};
-use crate::clean::inline::build_external_trait;
+use crate::clean::inline::build_trait;
use crate::clean::{self, ItemId};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
@@ -385,7 +385,7 @@ pub(crate) fn run_global_ctxt(
//
// Note that in case of `#![no_core]`, the trait is not available.
if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() {
- let sized_trait = build_external_trait(&mut ctxt, sized_trait_did);
+ let sized_trait = build_trait(&mut ctxt, sized_trait_did);
ctxt.external_traits.insert(sized_trait_did, sized_trait);
}
@@ -412,9 +412,7 @@ pub(crate) fn run_global_ctxt(
// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
for attr in krate.module.attrs.lists(sym::doc) {
- let name = attr.name_or_empty();
-
- if attr.is_word() && name == sym::document_private_items {
+ if attr.is_word() && attr.has_name(sym::document_private_items) {
ctxt.render_options.document_private = true;
}
}
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index 4edd543..d5c965f 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -345,7 +345,7 @@ fn push_to_s(s: &mut String, source: &str, span: rustc_span::Span, prev_span_hi:
fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool {
let mut is_extern_crate = false;
if !info.has_global_allocator
- && item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator)
+ && item.attrs.iter().any(|attr| attr.has_name(sym::global_allocator))
{
info.has_global_allocator = true;
}
@@ -377,7 +377,7 @@ fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<
}
let mut prev_span_hi = 0;
- let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect];
+ let not_crate_attrs = &[sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect];
let parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No);
let result = match parsed {
@@ -386,17 +386,13 @@ fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<
&& let Some(ref body) = fn_item.body =>
{
for attr in &item.attrs {
- let attr_name = attr.name_or_empty();
-
- if attr.style == AttrStyle::Outer || not_crate_attrs.contains(&attr_name) {
+ if attr.style == AttrStyle::Outer || attr.has_any_name(not_crate_attrs) {
// There is one exception to these attributes:
// `#![allow(internal_features)]`. If this attribute is used, we need to
// consider it only as a crate-level attribute.
- if attr_name == sym::allow
+ if attr.has_name(sym::allow)
&& let Some(list) = attr.meta_item_list()
- && list.iter().any(|sub_attr| {
- sub_attr.name_or_empty().as_str() == "internal_features"
- })
+ && list.iter().any(|sub_attr| sub_attr.has_name(sym::internal_features))
{
push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
} else {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 41e9a5a..299fd6b 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -11,6 +11,7 @@
use std::cmp::Ordering;
use std::fmt::{self, Display, Write};
use std::iter::{self, once};
+use std::slice;
use itertools::Either;
use rustc_abi::ExternAbi;
@@ -650,33 +651,35 @@ pub(crate) fn href_relative_parts<'fqp>(
}
}
-pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Context<'_>) -> String {
- let cache = cx.cache();
- let Some((fqp, shortty)) = cache.paths.get(&did).or_else(|| cache.external_paths.get(&did))
- else {
- return String::new();
- };
- let mut buf = String::new();
- let fqp = if *shortty == ItemType::Primitive {
- // primitives are documented in a crate, but not actually part of it
- &fqp[fqp.len() - 1..]
- } else {
- fqp
- };
- if let &Some(UrlFragment::Item(id)) = fragment {
- write_str(&mut buf, format_args!("{} ", cx.tcx().def_descr(id)));
- for component in fqp {
- write_str(&mut buf, format_args!("{component}::"));
+pub(crate) fn link_tooltip(
+ did: DefId,
+ fragment: &Option<UrlFragment>,
+ cx: &Context<'_>,
+) -> impl fmt::Display {
+ fmt::from_fn(move |f| {
+ let cache = cx.cache();
+ let Some((fqp, shortty)) = cache.paths.get(&did).or_else(|| cache.external_paths.get(&did))
+ else {
+ return Ok(());
+ };
+ let fqp = if *shortty == ItemType::Primitive {
+ // primitives are documented in a crate, but not actually part of it
+ slice::from_ref(fqp.last().unwrap())
+ } else {
+ fqp
+ };
+ if let &Some(UrlFragment::Item(id)) = fragment {
+ write!(f, "{} ", cx.tcx().def_descr(id))?;
+ for component in fqp {
+ write!(f, "{component}::")?;
+ }
+ write!(f, "{}", cx.tcx().item_name(id))?;
+ } else if !fqp.is_empty() {
+ write!(f, "{shortty} ")?;
+ fqp.iter().joined("::", f)?;
}
- write_str(&mut buf, format_args!("{}", cx.tcx().item_name(id)));
- } else if !fqp.is_empty() {
- let mut fqp_it = fqp.iter();
- write_str(&mut buf, format_args!("{shortty} {}", fqp_it.next().unwrap()));
- for component in fqp_it {
- write_str(&mut buf, format_args!("::{component}"));
- }
- }
- buf
+ Ok(())
+ })
}
/// Used to render a [`clean::Path`].
@@ -1183,8 +1186,8 @@ fn print_type(
{
primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?;
} else if let clean::BareFunction(bare_fn) = &type_
- && let [clean::Argument { type_: clean::Type::Generic(name), .. }] =
- &bare_fn.decl.inputs.values[..]
+ && let [clean::Parameter { type_: clean::Type::Generic(name), .. }] =
+ &bare_fn.decl.inputs[..]
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
{
// Hardcoded anchor library/core/src/primitive_docs.rs
@@ -1231,22 +1234,20 @@ fn print_type(
}
}
-impl clean::Arguments {
- pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
- fmt::from_fn(move |f| {
- self.values
- .iter()
- .map(|input| {
- fmt::from_fn(|f| {
- if !input.name.is_empty() {
- write!(f, "{}: ", input.name)?;
- }
- input.type_.print(cx).fmt(f)
- })
+pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> impl Display {
+ fmt::from_fn(move |f| {
+ params
+ .iter()
+ .map(|param| {
+ fmt::from_fn(|f| {
+ if let Some(name) = param.name {
+ write!(f, "{}: ", name)?;
+ }
+ param.type_.print(cx).fmt(f)
})
- .joined(", ", f)
- })
- }
+ })
+ .joined(", ", f)
+ })
}
// Implements Write but only counts the bytes "written".
@@ -1278,16 +1279,16 @@ pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
if f.alternate() {
write!(
f,
- "({args:#}{ellipsis}){arrow:#}",
- args = self.inputs.print(cx),
+ "({params:#}{ellipsis}){arrow:#}",
+ params = print_params(&self.inputs, cx),
ellipsis = ellipsis,
arrow = self.print_output(cx)
)
} else {
write!(
f,
- "({args}{ellipsis}){arrow}",
- args = self.inputs.print(cx),
+ "({params}{ellipsis}){arrow}",
+ params = print_params(&self.inputs, cx),
ellipsis = ellipsis,
arrow = self.print_output(cx)
)
@@ -1333,14 +1334,14 @@ fn inner_full_print(
write!(f, "(")?;
if let Some(n) = line_wrapping_indent
- && !self.inputs.values.is_empty()
+ && !self.inputs.is_empty()
{
write!(f, "\n{}", Indent(n + 4))?;
}
- let last_input_index = self.inputs.values.len().checked_sub(1);
- for (i, input) in self.inputs.values.iter().enumerate() {
- if let Some(selfty) = input.to_receiver() {
+ let last_input_index = self.inputs.len().checked_sub(1);
+ for (i, param) in self.inputs.iter().enumerate() {
+ if let Some(selfty) = param.to_receiver() {
match selfty {
clean::SelfTy => {
write!(f, "self")?;
@@ -1358,11 +1359,13 @@ fn inner_full_print(
}
}
} else {
- if input.is_const {
+ if param.is_const {
write!(f, "const ")?;
}
- write!(f, "{}: ", input.name)?;
- input.type_.print(cx).fmt(f)?;
+ if let Some(name) = param.name {
+ write!(f, "{}: ", name)?;
+ }
+ param.type_.print(cx).fmt(f)?;
}
match (line_wrapping_indent, last_input_index) {
(_, None) => (),
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index e2d1f58..f22935d 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -521,23 +521,23 @@ fn init(
// Crawl the crate attributes looking for attributes which control how we're
// going to emit HTML
for attr in krate.module.attrs.lists(sym::doc) {
- match (attr.name_or_empty(), attr.value_str()) {
- (sym::html_favicon_url, Some(s)) => {
+ match (attr.name(), attr.value_str()) {
+ (Some(sym::html_favicon_url), Some(s)) => {
layout.favicon = s.to_string();
}
- (sym::html_logo_url, Some(s)) => {
+ (Some(sym::html_logo_url), Some(s)) => {
layout.logo = s.to_string();
}
- (sym::html_playground_url, Some(s)) => {
+ (Some(sym::html_playground_url), Some(s)) => {
playground = Some(markdown::Playground {
crate_name: Some(krate.name(tcx)),
url: s.to_string(),
});
}
- (sym::issue_tracker_base_url, Some(s)) => {
+ (Some(sym::issue_tracker_base_url), Some(s)) => {
issue_tracker_base_url = Some(s.to_string());
}
- (sym::html_no_source, None) if attr.is_word() => {
+ (Some(sym::html_no_source), None) if attr.is_word() => {
include_sources = false;
}
_ => {}
@@ -650,15 +650,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
bar.render_into(&mut sidebar).unwrap();
- let v = layout::render(
- &shared.layout,
- &page,
- sidebar,
- BufDisplay(|buf: &mut String| {
- all.print(buf);
- }),
- &shared.style_files,
- );
+ let v = layout::render(&shared.layout, &page, sidebar, all.print(), &shared.style_files);
shared.fs.write(final_file, v)?;
// if to avoid writing help, settings files to doc root unless we're on the final invocation
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 21c823f..7e17f09 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -40,6 +40,7 @@
mod type_layout;
mod write_shared;
+use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt::{self, Display as _, Write};
use std::iter::Peekable;
@@ -47,6 +48,7 @@
use std::{fs, str};
use askama::Template;
+use itertools::Either;
use rustc_attr_parsing::{
ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince,
};
@@ -98,6 +100,19 @@ enum AssocItemRender<'a> {
DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool },
}
+impl AssocItemRender<'_> {
+ fn render_mode(&self) -> RenderMode {
+ match self {
+ Self::All => RenderMode::Normal,
+ &Self::DerefFor { deref_mut_, .. } => RenderMode::ForDeref { mut_: deref_mut_ },
+ }
+ }
+
+ fn class(&self) -> Option<&'static str> {
+ if let Self::DerefFor { .. } = self { Some("impl-items") } else { None }
+ }
+}
+
/// For different handling of associated items from the Deref target of a type rather than the type
/// itself.
#[derive(Copy, Clone, PartialEq)]
@@ -208,7 +223,7 @@ pub(crate) struct IndexItemFunctionType {
inputs: Vec<RenderType>,
output: Vec<RenderType>,
where_clause: Vec<Vec<RenderType>>,
- param_names: Vec<Symbol>,
+ param_names: Vec<Option<Symbol>>,
}
impl IndexItemFunctionType {
@@ -439,44 +454,49 @@ fn item_sections(&self) -> FxHashSet<ItemSection> {
sections
}
- fn print(&self, f: &mut String) {
- fn print_entries(f: &mut String, e: &FxIndexSet<ItemEntry>, kind: ItemSection) {
- if !e.is_empty() {
- let mut e: Vec<&ItemEntry> = e.iter().collect();
- e.sort();
- write_str(
- f,
- format_args!(
- "<h3 id=\"{id}\">{title}</h3><ul class=\"all-items\">",
- id = kind.id(),
- title = kind.name(),
- ),
- );
-
- for s in e.iter() {
- write_str(f, format_args!("<li>{}</li>", s.print()));
+ fn print(&self) -> impl fmt::Display {
+ fn print_entries(e: &FxIndexSet<ItemEntry>, kind: ItemSection) -> impl fmt::Display {
+ fmt::from_fn(move |f| {
+ if e.is_empty() {
+ return Ok(());
}
- f.push_str("</ul>");
- }
+ let mut e: Vec<&ItemEntry> = e.iter().collect();
+ e.sort();
+ write!(
+ f,
+ "<h3 id=\"{id}\">{title}</h3><ul class=\"all-items\">",
+ id = kind.id(),
+ title = kind.name(),
+ )?;
+
+ for s in e.iter() {
+ write!(f, "<li>{}</li>", s.print())?;
+ }
+
+ f.write_str("</ul>")
+ })
}
- f.push_str("<h1>List of all items</h1>");
- // Note: print_entries does not escape the title, because we know the current set of titles
- // doesn't require escaping.
- print_entries(f, &self.structs, ItemSection::Structs);
- print_entries(f, &self.enums, ItemSection::Enums);
- print_entries(f, &self.unions, ItemSection::Unions);
- print_entries(f, &self.primitives, ItemSection::PrimitiveTypes);
- print_entries(f, &self.traits, ItemSection::Traits);
- print_entries(f, &self.macros, ItemSection::Macros);
- print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros);
- print_entries(f, &self.derive_macros, ItemSection::DeriveMacros);
- print_entries(f, &self.functions, ItemSection::Functions);
- print_entries(f, &self.type_aliases, ItemSection::TypeAliases);
- print_entries(f, &self.trait_aliases, ItemSection::TraitAliases);
- print_entries(f, &self.statics, ItemSection::Statics);
- print_entries(f, &self.constants, ItemSection::Constants);
+ fmt::from_fn(|f| {
+ f.write_str("<h1>List of all items</h1>")?;
+ // Note: print_entries does not escape the title, because we know the current set of titles
+ // doesn't require escaping.
+ print_entries(&self.structs, ItemSection::Structs).fmt(f)?;
+ print_entries(&self.enums, ItemSection::Enums).fmt(f)?;
+ print_entries(&self.unions, ItemSection::Unions).fmt(f)?;
+ print_entries(&self.primitives, ItemSection::PrimitiveTypes).fmt(f)?;
+ print_entries(&self.traits, ItemSection::Traits).fmt(f)?;
+ print_entries(&self.macros, ItemSection::Macros).fmt(f)?;
+ print_entries(&self.attribute_macros, ItemSection::AttributeMacros).fmt(f)?;
+ print_entries(&self.derive_macros, ItemSection::DeriveMacros).fmt(f)?;
+ print_entries(&self.functions, ItemSection::Functions).fmt(f)?;
+ print_entries(&self.type_aliases, ItemSection::TypeAliases).fmt(f)?;
+ print_entries(&self.trait_aliases, ItemSection::TraitAliases).fmt(f)?;
+ print_entries(&self.statics, ItemSection::Statics).fmt(f)?;
+ print_entries(&self.constants, ItemSection::Constants).fmt(f)?;
+ Ok(())
+ })
}
}
@@ -1205,7 +1225,7 @@ fn anchor(&self, id: &'a str) -> Self {
}
fn write_section_heading(
- title: &str,
+ title: impl fmt::Display,
id: &str,
extra_class: Option<&str>,
extra: impl fmt::Display,
@@ -1225,7 +1245,7 @@ fn write_section_heading(
})
}
-fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display {
+fn write_impl_section_heading(title: impl fmt::Display, id: &str) -> impl fmt::Display {
write_section_heading(title, id, None, "")
}
@@ -1302,20 +1322,17 @@ fn render_assoc_items_inner(
let (mut non_trait, traits): (Vec<_>, _) =
v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
- let mut close_tags = <Vec<&str>>::with_capacity(1);
- let mut tmp_buf = String::new();
- let (render_mode, id, class_html) = match what {
- AssocItemRender::All => {
- write_str(
- &mut tmp_buf,
- format_args!(
- "{}",
- write_impl_section_heading("Implementations", "implementations")
- ),
- );
- (RenderMode::Normal, "implementations-list".to_owned(), "")
- }
- AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
+ let render_mode = what.render_mode();
+ let class_html = what
+ .class()
+ .map(|class| fmt::from_fn(move |f| write!(f, r#" class="{class}""#)))
+ .maybe_display();
+ let (section_heading, id) = match what {
+ AssocItemRender::All => (
+ Either::Left(write_impl_section_heading("Implementations", "implementations")),
+ Cow::Borrowed("implementations-list"),
+ ),
+ AssocItemRender::DerefFor { trait_, type_, .. } => {
let id =
cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
// the `impls.get` above only looks at the outermost type,
@@ -1329,25 +1346,27 @@ fn render_assoc_items_inner(
type_.is_doc_subtype_of(&impl_.inner_impl().for_, &cx.shared.cache)
});
let derived_id = cx.derive_id(&id);
- close_tags.push("</details>");
- write_str(
- &mut tmp_buf,
- format_args!(
- "<details class=\"toggle big-toggle\" open><summary>{}</summary>",
- write_impl_section_heading(
- &format!(
- "<span>Methods from {trait_}<Target = {type_}></span>",
- trait_ = trait_.print(cx),
- type_ = type_.print(cx),
- ),
- &id,
- )
- ),
- );
if let Some(def_id) = type_.def_id(cx.cache()) {
- cx.deref_id_map.borrow_mut().insert(def_id, id);
+ cx.deref_id_map.borrow_mut().insert(def_id, id.clone());
}
- (RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#)
+ (
+ Either::Right(fmt::from_fn(move |f| {
+ write!(
+ f,
+ "<details class=\"toggle big-toggle\" open><summary>{}</summary>",
+ write_impl_section_heading(
+ fmt::from_fn(|f| write!(
+ f,
+ "<span>Methods from {trait_}<Target = {type_}></span>",
+ trait_ = trait_.print(cx),
+ type_ = type_.print(cx),
+ )),
+ &id,
+ )
+ )
+ })),
+ Cow::Owned(derived_id),
+ )
}
};
let mut impls_buf = String::new();
@@ -1375,10 +1394,14 @@ fn render_assoc_items_inner(
);
}
if !impls_buf.is_empty() {
- write!(w, "{tmp_buf}<div id=\"{id}\"{class_html}>{impls_buf}</div>").unwrap();
- for tag in close_tags.into_iter().rev() {
- w.write_str(tag).unwrap();
- }
+ write!(
+ w,
+ "{section_heading}<div id=\"{id}\"{class_html}>{impls_buf}</div>{}",
+ matches!(what, AssocItemRender::DerefFor { .. })
+ .then_some("</details>")
+ .maybe_display(),
+ )
+ .unwrap();
}
}
@@ -1639,8 +1662,8 @@ fn render_impl(
// `containing_item` is used for rendering stability info. If the parent is a trait impl,
// `containing_item` will the grandparent, since trait impls can't have stability attached.
fn doc_impl_item(
- boring: &mut String,
- interesting: &mut String,
+ boring: impl fmt::Write,
+ interesting: impl fmt::Write,
cx: &Context<'_>,
item: &clean::Item,
parent: &clean::Item,
@@ -1649,7 +1672,7 @@ fn doc_impl_item(
is_default_item: bool,
trait_: Option<&clean::Trait>,
rendering_params: ImplRenderingParameters,
- ) {
+ ) -> fmt::Result {
let item_type = item.type_();
let name = item.name.as_ref().unwrap();
@@ -1724,15 +1747,16 @@ fn doc_impl_item(
);
}
}
- let w = if short_documented && trait_.is_some() { interesting } else { boring };
+ let mut w = if short_documented && trait_.is_some() {
+ Either::Left(interesting)
+ } else {
+ Either::Right(boring)
+ };
let toggled = !doc_buffer.is_empty();
if toggled {
let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
- write_str(
- w,
- format_args!("<details class=\"toggle{method_toggle_class}\" open><summary>"),
- );
+ write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>")?;
}
match &item.kind {
clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
@@ -1747,172 +1771,151 @@ fn doc_impl_item(
.find(|item| item.name.map(|n| n == *name).unwrap_or(false))
})
.map(|item| format!("{}.{name}", item.type_()));
- write_str(
+ write!(
w,
- format_args!(
- "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+ "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
{}",
- render_rightside(cx, item, render_mode)
- ),
- );
+ render_rightside(cx, item, render_mode)
+ )?;
if trait_.is_some() {
// Anchors are only used on trait impls.
- write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+ write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>")?;
}
- write_str(
+ write!(
w,
- format_args!(
- "<h4 class=\"code-header\">{}</h4></section>",
- render_assoc_item(
- item,
- link.anchor(source_id.as_ref().unwrap_or(&id)),
- ItemType::Impl,
- cx,
- render_mode,
- ),
+ "<h4 class=\"code-header\">{}</h4></section>",
+ render_assoc_item(
+ item,
+ link.anchor(source_id.as_ref().unwrap_or(&id)),
+ ItemType::Impl,
+ cx,
+ render_mode,
),
- );
+ )?;
}
}
clean::RequiredAssocConstItem(generics, ty) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
- write_str(
+ write!(
w,
- format_args!(
- "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+ "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
{}",
- render_rightside(cx, item, render_mode)
- ),
- );
+ render_rightside(cx, item, render_mode)
+ )?;
if trait_.is_some() {
// Anchors are only used on trait impls.
- write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+ write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>")?;
}
- write_str(
+ write!(
w,
- format_args!(
- "<h4 class=\"code-header\">{}</h4></section>",
- assoc_const(
- item,
- generics,
- ty,
- AssocConstValue::None,
- link.anchor(if trait_.is_some() { &source_id } else { &id }),
- 0,
- cx,
- )
+ "<h4 class=\"code-header\">{}</h4></section>",
+ assoc_const(
+ item,
+ generics,
+ ty,
+ AssocConstValue::None,
+ link.anchor(if trait_.is_some() { &source_id } else { &id }),
+ 0,
+ cx,
),
- );
+ )?;
}
clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
- write_str(
+ write!(
w,
- format_args!(
- "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+ "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
{}",
- render_rightside(cx, item, render_mode)
- ),
- );
+ render_rightside(cx, item, render_mode),
+ )?;
if trait_.is_some() {
// Anchors are only used on trait impls.
- write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+ write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>")?;
}
- write_str(
+ write!(
w,
- format_args!(
- "<h4 class=\"code-header\">{}</h4></section>",
- assoc_const(
- item,
- &ci.generics,
- &ci.type_,
- match item.kind {
- clean::ProvidedAssocConstItem(_) =>
- AssocConstValue::TraitDefault(&ci.kind),
- clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind),
- _ => unreachable!(),
- },
- link.anchor(if trait_.is_some() { &source_id } else { &id }),
- 0,
- cx,
- )
+ "<h4 class=\"code-header\">{}</h4></section>",
+ assoc_const(
+ item,
+ &ci.generics,
+ &ci.type_,
+ match item.kind {
+ clean::ProvidedAssocConstItem(_) =>
+ AssocConstValue::TraitDefault(&ci.kind),
+ clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind),
+ _ => unreachable!(),
+ },
+ link.anchor(if trait_.is_some() { &source_id } else { &id }),
+ 0,
+ cx,
),
- );
+ )?;
}
clean::RequiredAssocTypeItem(generics, bounds) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
- write_str(
+ write!(
w,
- format_args!(
- "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+ "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
{}",
- render_rightside(cx, item, render_mode)
- ),
- );
+ render_rightside(cx, item, render_mode),
+ )?;
if trait_.is_some() {
// Anchors are only used on trait impls.
- write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+ write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>")?;
}
- write_str(
+ write!(
w,
- format_args!(
- "<h4 class=\"code-header\">{}</h4></section>",
- assoc_type(
- item,
- generics,
- bounds,
- None,
- link.anchor(if trait_.is_some() { &source_id } else { &id }),
- 0,
- cx,
- )
+ "<h4 class=\"code-header\">{}</h4></section>",
+ assoc_type(
+ item,
+ generics,
+ bounds,
+ None,
+ link.anchor(if trait_.is_some() { &source_id } else { &id }),
+ 0,
+ cx,
),
- );
+ )?;
}
clean::AssocTypeItem(tydef, _bounds) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
- write_str(
+ write!(
w,
- format_args!(
- "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+ "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
{}",
- render_rightside(cx, item, render_mode)
- ),
- );
+ render_rightside(cx, item, render_mode),
+ )?;
if trait_.is_some() {
// Anchors are only used on trait impls.
- write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+ write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>")?;
}
- write_str(
+ write!(
w,
- format_args!(
- "<h4 class=\"code-header\">{}</h4></section>",
- assoc_type(
- item,
- &tydef.generics,
- &[], // intentionally leaving out bounds
- Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)),
- link.anchor(if trait_.is_some() { &source_id } else { &id }),
- 0,
- cx,
- )
+ "<h4 class=\"code-header\">{}</h4></section>",
+ assoc_type(
+ item,
+ &tydef.generics,
+ &[], // intentionally leaving out bounds
+ Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)),
+ link.anchor(if trait_.is_some() { &source_id } else { &id }),
+ 0,
+ cx,
),
- );
+ )?;
}
- clean::StrippedItem(..) => return,
+ clean::StrippedItem(..) => return Ok(()),
_ => panic!("can't make docs for trait item with name {:?}", item.name),
}
- w.push_str(&info_buffer);
+ w.write_str(&info_buffer)?;
if toggled {
- w.push_str("</summary>");
- w.push_str(&doc_buffer);
- w.push_str("</details>");
+ write!(w, "</summary>{doc_buffer}</details>")?;
}
+ Ok(())
}
let mut impl_items = String::new();
@@ -1955,7 +1958,7 @@ fn doc_impl_item(
false,
trait_,
rendering_params,
- );
+ )?;
}
_ => {}
}
@@ -1973,7 +1976,7 @@ fn doc_impl_item(
false,
trait_,
rendering_params,
- );
+ )?;
}
for method in methods {
doc_impl_item(
@@ -1987,20 +1990,20 @@ fn doc_impl_item(
false,
trait_,
rendering_params,
- );
+ )?;
}
}
fn render_default_items(
- boring: &mut String,
- interesting: &mut String,
+ mut boring: impl fmt::Write,
+ mut interesting: impl fmt::Write,
cx: &Context<'_>,
t: &clean::Trait,
i: &clean::Impl,
parent: &clean::Item,
render_mode: RenderMode,
rendering_params: ImplRenderingParameters,
- ) {
+ ) -> fmt::Result {
for trait_item in &t.items {
// Skip over any default trait items that are impossible to reference
// (e.g. if it has a `Self: Sized` bound on an unsized type).
@@ -2020,8 +2023,8 @@ fn render_default_items(
let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_methods);
doc_impl_item(
- boring,
- interesting,
+ &mut boring,
+ &mut interesting,
cx,
trait_item,
parent,
@@ -2030,8 +2033,9 @@ fn render_default_items(
true,
Some(t),
rendering_params,
- );
+ )?;
}
+ Ok(())
}
// If we've implemented a trait, then also emit documentation for all
@@ -2051,7 +2055,7 @@ fn render_default_items(
&i.impl_item,
render_mode,
rendering_params,
- );
+ )?;
}
}
if render_mode == RenderMode::Normal {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 96847f1..39a631b 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -11,7 +11,7 @@
use rustc_index::IndexVec;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::{Symbol, kw, sym};
+use rustc_span::symbol::{Symbol, sym};
use tracing::{debug, info};
use super::type_layout::document_type_layout;
@@ -347,9 +347,12 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
// but we actually want stable items to come first
return is_stable2.cmp(&is_stable1);
}
- let lhs = i1.name.unwrap_or(kw::Empty);
- let rhs = i2.name.unwrap_or(kw::Empty);
- compare_names(lhs.as_str(), rhs.as_str())
+ match (i1.name, i2.name) {
+ (Some(name1), Some(name2)) => compare_names(name1.as_str(), name2.as_str()),
+ (Some(_), None) => Ordering::Greater,
+ (None, Some(_)) => Ordering::Less,
+ (None, None) => Ordering::Equal,
+ }
}
let tcx = cx.tcx();
@@ -1229,12 +1232,13 @@ fn item_trait_alias(
wrap_item(w, |w| {
write!(
w,
- "{attrs}trait {name}{generics}{where_b} = {bounds};",
+ "{attrs}trait {name}{generics} = {bounds}{where_clause};",
attrs = render_attributes_in_pre(it, "", cx),
name = it.name.unwrap(),
generics = t.generics.print(cx),
- where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(),
bounds = bounds(&t.bounds, true, cx),
+ where_clause =
+ print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(),
)
})?;
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index b39701f..aff8684 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -709,8 +709,11 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
let mut result = Vec::new();
for (index, item) in self.items.iter().enumerate() {
if let Some(ty) = &item.search_type
- && let my =
- ty.param_names.iter().map(|sym| sym.as_str()).collect::<Vec<_>>()
+ && let my = ty
+ .param_names
+ .iter()
+ .filter_map(|sym| sym.map(|sym| sym.to_string()))
+ .collect::<Vec<_>>()
&& my != prev
{
result.push((index, my.join(",")));
@@ -1109,7 +1112,7 @@ fn simplify_fn_type<'a, 'tcx>(
}
Type::BareFunction(ref bf) => {
let mut ty_generics = Vec::new();
- for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) {
+ for ty in bf.decl.inputs.iter().map(|arg| &arg.type_) {
simplify_fn_type(
self_,
generics,
@@ -1372,7 +1375,7 @@ fn simplify_fn_constraint<'a>(
/// Used to allow type-based search on constants and statics.
fn make_nullary_fn(
clean_type: &clean::Type,
-) -> (Vec<RenderType>, Vec<RenderType>, Vec<Symbol>, Vec<Vec<RenderType>>) {
+) -> (Vec<RenderType>, Vec<RenderType>, Vec<Option<Symbol>>, Vec<Vec<RenderType>>) {
let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> = Default::default();
let output = get_index_type(clean_type, vec![], &mut rgen);
(vec![], vec![output], vec![], vec![])
@@ -1387,7 +1390,7 @@ fn get_fn_inputs_and_outputs(
tcx: TyCtxt<'_>,
impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>,
cache: &Cache,
-) -> (Vec<RenderType>, Vec<RenderType>, Vec<Symbol>, Vec<Vec<RenderType>>) {
+) -> (Vec<RenderType>, Vec<RenderType>, Vec<Option<Symbol>>, Vec<Vec<RenderType>>) {
let decl = &func.decl;
let mut rgen: FxIndexMap<SimplifiedParam, (isize, Vec<RenderType>)> = Default::default();
@@ -1415,15 +1418,15 @@ fn get_fn_inputs_and_outputs(
(None, &func.generics)
};
- let mut arg_types = Vec::new();
- for arg in decl.inputs.values.iter() {
+ let mut param_types = Vec::new();
+ for param in decl.inputs.iter() {
simplify_fn_type(
self_,
generics,
- &arg.type_,
+ ¶m.type_,
tcx,
0,
- &mut arg_types,
+ &mut param_types,
&mut rgen,
false,
cache,
@@ -1436,15 +1439,15 @@ fn get_fn_inputs_and_outputs(
let mut simplified_params = rgen.into_iter().collect::<Vec<_>>();
simplified_params.sort_by_key(|(_, (idx, _))| -idx);
(
- arg_types,
+ param_types,
ret_types,
simplified_params
.iter()
.map(|(name, (_idx, _traits))| match name {
- SimplifiedParam::Symbol(name) => *name,
- SimplifiedParam::Anonymous(_) => kw::Empty,
+ SimplifiedParam::Symbol(name) => Some(*name),
+ SimplifiedParam::Anonymous(_) => None,
SimplifiedParam::AssociatedType(def_id, name) => {
- Symbol::intern(&format!("{}::{}", tcx.item_name(*def_id), name))
+ Some(Symbol::intern(&format!("{}::{}", tcx.item_name(*def_id), name)))
}
})
.collect(),
diff --git a/src/librustdoc/html/render/tests.rs b/src/librustdoc/html/render/tests.rs
index 657cd3c..327a308 100644
--- a/src/librustdoc/html/render/tests.rs
+++ b/src/librustdoc/html/render/tests.rs
@@ -47,8 +47,7 @@ fn test_all_types_prints_header_once() {
// Regression test for #82477
let all_types = AllTypes::new();
- let mut buffer = String::new();
- all_types.print(&mut buffer);
+ let buffer = all_types.print().to_string();
assert_eq!(1, buffer.matches("List of all items").count());
}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 9d8eb70f..dab23f8 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -11,7 +11,7 @@
use rustc_hir::def_id::DefId;
use rustc_metadata::rendered_const;
use rustc_middle::{bug, ty};
-use rustc_span::{Pos, Symbol};
+use rustc_span::{Pos, Symbol, kw};
use rustdoc_json_types::*;
use crate::clean::{self, ItemId};
@@ -609,9 +609,13 @@ fn from_clean(decl: clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self {
let clean::FnDecl { inputs, output, c_variadic } = decl;
FunctionSignature {
inputs: inputs
- .values
.into_iter()
- .map(|arg| (arg.name.to_string(), arg.type_.into_json(renderer)))
+ .map(|param| {
+ // `_` is the most sensible name for missing param names.
+ let name = param.name.unwrap_or(kw::Underscore).to_string();
+ let type_ = param.type_.into_json(renderer);
+ (name, type_)
+ })
.collect(),
output: if output.is_unit() { None } else { Some(output.into_json(renderer)) },
is_c_variadic: c_variadic,
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index ba27eed..131a12c 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -14,6 +14,7 @@
use std::path::PathBuf;
use std::rc::Rc;
+use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
@@ -123,6 +124,58 @@ fn serialize_and_write<T: Write>(
}
}
+fn target(sess: &rustc_session::Session) -> types::Target {
+ // Build a set of which features are enabled on this target
+ let globally_enabled_features: FxHashSet<&str> =
+ sess.unstable_target_features.iter().map(|name| name.as_str()).collect();
+
+ // Build a map of target feature stability by feature name
+ use rustc_target::target_features::Stability;
+ let feature_stability: FxHashMap<&str, Stability> = sess
+ .target
+ .rust_target_features()
+ .into_iter()
+ .copied()
+ .map(|(name, stability, _)| (name, stability))
+ .collect();
+
+ types::Target {
+ triple: sess.opts.target_triple.tuple().into(),
+ target_features: sess
+ .target
+ .rust_target_features()
+ .into_iter()
+ .copied()
+ .filter(|(_, stability, _)| {
+ // Describe only target features which the user can toggle
+ stability.toggle_allowed().is_ok()
+ })
+ .map(|(name, stability, implied_features)| {
+ types::TargetFeature {
+ name: name.into(),
+ unstable_feature_gate: match stability {
+ Stability::Unstable(feature_gate) => Some(feature_gate.as_str().into()),
+ _ => None,
+ },
+ implies_features: implied_features
+ .into_iter()
+ .copied()
+ .filter(|name| {
+ // Imply only target features which the user can toggle
+ feature_stability
+ .get(name)
+ .map(|stability| stability.toggle_allowed().is_ok())
+ .unwrap_or(false)
+ })
+ .map(String::from)
+ .collect(),
+ globally_enabled: globally_enabled_features.contains(name),
+ }
+ })
+ .collect(),
+ }
+}
+
impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
fn descr() -> &'static str {
"json"
@@ -248,6 +301,12 @@ fn after_krate(&mut self) -> Result<(), Error> {
let e = ExternalCrate { crate_num: LOCAL_CRATE };
let index = (*self.index).clone().into_inner();
+ // Note that tcx.rust_target_features is inappropriate here because rustdoc tries to run for
+ // multiple targets: https://github.com/rust-lang/rust/pull/137632
+ //
+ // We want to describe a single target, so pass tcx.sess rather than tcx.
+ let target = target(self.tcx.sess);
+
debug!("Constructing Output");
let output_crate = types::Crate {
root: self.id_from_item_default(e.def_id().into()),
@@ -288,6 +347,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
)
})
.collect(),
+ target,
format_version: types::FORMAT_VERSION,
};
if let Some(ref out_dir) = self.out_dir {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index fdbb792..297597b 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -60,7 +60,7 @@ fn filter_assoc_items_by_name_and_namespace(
ns: Namespace,
) -> impl Iterator<Item = &ty::AssocItem> {
tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| {
- item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of)
+ item.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of)
})
}
@@ -743,7 +743,7 @@ fn resolve_associated_item(
ns,
)
.map(|item| {
- let res = Res::Def(item.kind.as_def_kind(), item.def_id);
+ let res = Res::Def(item.as_def_kind(), item.def_id);
(res, item.def_id)
})
.collect::<Vec<_>>(),
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 137fe4c..7247950 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -30,7 +30,7 @@
/// This integer is incremented with every breaking change to the API,
/// and is returned along with the JSON blob as [`Crate::format_version`].
/// Consuming code should assert that this value matches the format version(s) that it supports.
-pub const FORMAT_VERSION: u32 = 43;
+pub const FORMAT_VERSION: u32 = 44;
/// The root of the emitted JSON blob.
///
@@ -52,11 +52,67 @@ pub struct Crate {
pub paths: HashMap<Id, ItemSummary>,
/// Maps `crate_id` of items to a crate name and html_root_url if it exists.
pub external_crates: HashMap<u32, ExternalCrate>,
+ /// Information about the target for which this documentation was generated
+ pub target: Target,
/// A single version number to be used in the future when making backwards incompatible changes
/// to the JSON output.
pub format_version: u32,
}
+/// Information about a target
+#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub struct Target {
+ /// The target triple for which this documentation was generated
+ pub triple: String,
+ /// A list of features valid for use in `#[target_feature]` attributes
+ /// for the target where this rustdoc JSON was generated.
+ pub target_features: Vec<TargetFeature>,
+}
+
+/// Information about a target feature.
+///
+/// Rust target features are used to influence code generation, especially around selecting
+/// instructions which are not universally supported by the target architecture.
+///
+/// Target features are commonly enabled by the [`#[target_feature]` attribute][1] to influence code
+/// generation for a particular function, and less commonly enabled by compiler options like
+/// `-Ctarget-feature` or `-Ctarget-cpu`. Targets themselves automatically enable certain target
+/// features by default, for example because the target's ABI specification requires saving specific
+/// registers which only exist in an architectural extension.
+///
+/// Target features can imply other target features: for example, x86-64 `avx2` implies `avx`, and
+/// aarch64 `sve2` implies `sve`, since both of these architectural extensions depend on their
+/// predecessors.
+///
+/// Target features can be probed at compile time by [`#[cfg(target_feature)]`][2] or `cfg!(…)`
+/// conditional compilation to determine whether a target feature is enabled in a particular
+/// context.
+///
+/// [1]: https://doc.rust-lang.org/stable/reference/attributes/codegen.html#the-target_feature-attribute
+/// [2]: https://doc.rust-lang.org/reference/conditional-compilation.html#target_feature
+#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub struct TargetFeature {
+ /// The name of this target feature.
+ pub name: String,
+ /// Other target features which are implied by this target feature, if any.
+ pub implies_features: Vec<String>,
+ /// If this target feature is unstable, the name of the associated language feature gate.
+ pub unstable_feature_gate: Option<String>,
+ /// Whether this feature is globally enabled for this compilation session.
+ ///
+ /// Target features can be globally enabled implicitly as a result of the target's definition.
+ /// For example, x86-64 hardware floating point ABIs require saving x87 and SSE2 registers,
+ /// which in turn requires globally enabling the `x87` and `sse2` target features so that the
+ /// generated machine code conforms to the target's ABI.
+ ///
+ /// Target features can also be globally enabled explicitly as a result of compiler flags like
+ /// [`-Ctarget-feature`][1] or [`-Ctarget-cpu`][2].
+ ///
+ /// [1]: https://doc.rust-lang.org/beta/rustc/codegen-options/index.html#target-feature
+ /// [2]: https://doc.rust-lang.org/beta/rustc/codegen-options/index.html#target-cpu
+ pub globally_enabled: bool,
+}
+
/// Metadata of a crate, either the same crate on which `rustdoc` was invoked, or its dependency.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ExternalCrate {
diff --git a/src/stage0 b/src/stage0
index b3841d2..6e86501 100644
--- a/src/stage0
+++ b/src/stage0
@@ -476,4 +476,4 @@
dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=0ea7e17d7bb67d6a6c4b2f864aaffcd96512f15f17f0acc63751eb1df6c486a7
dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=b73d37b704ab58921172cc561f5598db6a504dcd4d7980966f7c26caaf6d3594
dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.gz=986f6c594d37bcbd3833e053640ba8775f68d26a65c5618386654ef55d7b3542
-dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.xz=c0d9a88c30d2ab38ec3a11fabb5515ed9bc3ac1a8e35a438d68bf7ff82f6b843
\ No newline at end of file
+dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.xz=c0d9a88c30d2ab38ec3a11fabb5515ed9bc3ac1a8e35a438d68bf7ff82f6b843
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
index f510727..d679084 100644
--- a/src/tools/bump-stage0/src/main.rs
+++ b/src/tools/bump-stage0/src/main.rs
@@ -65,32 +65,33 @@ fn update_stage0_file(mut self) -> Result<(), Error> {
nightly_branch,
} = &self.config;
- file_content.push_str(&format!("dist_server={}", dist_server));
- file_content.push_str(&format!("\nartifacts_server={}", artifacts_server));
+ file_content.push_str(&format!("dist_server={}\n", dist_server));
+ file_content.push_str(&format!("artifacts_server={}\n", artifacts_server));
file_content.push_str(&format!(
- "\nartifacts_with_llvm_assertions_server={}",
+ "artifacts_with_llvm_assertions_server={}\n",
artifacts_with_llvm_assertions_server
));
- file_content.push_str(&format!("\ngit_merge_commit_email={}", git_merge_commit_email));
- file_content.push_str(&format!("\ngit_repository={}", git_repository));
- file_content.push_str(&format!("\nnightly_branch={}", nightly_branch));
+ file_content.push_str(&format!("git_merge_commit_email={}\n", git_merge_commit_email));
+ file_content.push_str(&format!("git_repository={}\n", git_repository));
+ file_content.push_str(&format!("nightly_branch={}\n", nightly_branch));
- file_content.push_str("\n\n");
+ file_content.push_str("\n");
file_content.push_str(COMMENTS);
+ file_content.push_str("\n");
let compiler = self.detect_compiler()?;
- file_content.push_str(&format!("\ncompiler_date={}", compiler.date));
- file_content.push_str(&format!("\ncompiler_version={}", compiler.version));
+ file_content.push_str(&format!("compiler_date={}\n", compiler.date));
+ file_content.push_str(&format!("compiler_version={}\n", compiler.version));
if let Some(rustfmt) = self.detect_rustfmt()? {
- file_content.push_str(&format!("\nrustfmt_date={}", rustfmt.date));
- file_content.push_str(&format!("\nrustfmt_version={}", rustfmt.version));
+ file_content.push_str(&format!("rustfmt_date={}\n", rustfmt.date));
+ file_content.push_str(&format!("rustfmt_version={}\n", rustfmt.version));
}
file_content.push_str("\n");
for (key, value) in self.checksums {
- file_content.push_str(&format!("\n{}={}", key, value));
+ file_content.push_str(&format!("{}={}\n", key, value));
}
std::fs::write(PATH, file_content)?;
diff --git a/src/tools/cargo b/src/tools/cargo
index 0e93c5b..d811228 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 0e93c5bf6a1d5ee7bc2af63d1afb16cd28793601
+Subproject commit d811228b14ae2707323f37346aee3f4147e247e6
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index ab34af7..e5439a6 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -111,8 +111,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
// Only suggest if `clone_from`/`clone_into` is explicitly implemented
&& resolved_assoc_items.in_definition_order().any(|assoc|
match which_trait {
- CloneTrait::Clone => assoc.name == sym::clone_from,
- CloneTrait::ToOwned => assoc.name.as_str() == "clone_into",
+ CloneTrait::Clone => assoc.name() == sym::clone_from,
+ CloneTrait::ToOwned => assoc.name().as_str() == "clone_into",
}
)
&& !clone_source_borrows_from_dest(cx, lhs, rhs.span)
diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
index ad18c70..4a876b8 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -56,7 +56,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -
cx.tcx.associated_items(trait_id).find_by_ident_and_kind(
cx.tcx,
Ident::from_str("Output"),
- ty::AssocKind::Type,
+ ty::AssocTag::Type,
trait_id,
)
})
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 3862ff7..06224f5 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -550,7 +550,7 @@ fn can_display_format(&self, ty: Ty<'tcx>) -> bool {
// a `Target` that is in `self.ty_msrv_map`.
if let Some(deref_trait_id) = self.cx.tcx.lang_items().deref_trait()
&& implements_trait(self.cx, ty, deref_trait_id, &[])
- && let Some(target_ty) = self.cx.get_associated_type(ty, deref_trait_id, "Target")
+ && let Some(target_ty) = self.cx.get_associated_type(ty, deref_trait_id, sym::Target)
&& let Some(msrv) = self.ty_msrv_map.get(&target_ty)
&& msrv.is_none_or(|msrv| self.msrv.meets(self.cx, msrv))
{
diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
index d02d9b2..430f241 100644
--- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
@@ -315,7 +315,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) {
assocs
.filter_by_name_unhygienic(constraint.ident.name)
.next()
- .is_some_and(|assoc| assoc.kind == ty::AssocKind::Type)
+ .is_some_and(|assoc| assoc.is_type())
})
{
emit_lint(cx, poly_trait, bounds, index, implied_constraints, bound);
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 72e22ae..77085d5 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -13,7 +13,7 @@
QPath, TraitItemRef, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
+use rustc_middle::ty::{self, FnSig, Ty};
use rustc_session::declare_lint_pass;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
@@ -288,8 +288,7 @@ fn fill_trait_set(traitt: DefId, set: &mut DefIdSet, cx: &LateContext<'_>) {
.items()
.flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty))
.any(|i| {
- i.kind == AssocKind::Fn
- && i.fn_has_self_parameter
+ i.is_method()
&& cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1
});
@@ -466,7 +465,7 @@ fn check_for_is_empty(
.inherent_impls(impl_ty)
.iter()
.flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty))
- .find(|item| item.kind == AssocKind::Fn);
+ .find(|item| item.is_fn());
let (msg, is_empty_span, self_kind) = match is_empty {
None => (
@@ -486,7 +485,7 @@ fn check_for_is_empty(
None,
),
Some(is_empty)
- if !(is_empty.fn_has_self_parameter
+ if !(is_empty.is_method()
&& check_is_empty_sig(
cx,
cx.tcx.fn_sig(is_empty.def_id).instantiate_identity().skip_binder(),
@@ -608,7 +607,7 @@ fn is_empty_array(expr: &Expr<'_>) -> bool {
fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
- if item.kind == AssocKind::Fn {
+ if item.is_fn() {
let sig = cx.tcx.fn_sig(item.def_id).skip_binder();
let ty = sig.skip_binder();
ty.inputs().len() == 1
@@ -644,7 +643,7 @@ fn ty_has_is_empty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, depth: usize) ->
&& cx.tcx.get_diagnostic_item(sym::Deref).is_some_and(|deref_id| {
implements_trait(cx, ty, deref_id, &[])
&& cx
- .get_associated_type(ty, deref_id, "Target")
+ .get_associated_type(ty, deref_id, sym::Target)
.is_some_and(|deref_ty| ty_has_is_empty(cx, deref_ty, depth + 1))
}))
},
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 8d47c75..dabef18 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -14,7 +14,7 @@
};
use rustc_hir::{
AmbigArg, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind,
- Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node,
+ Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeKind, LifetimeParamKind, Node,
PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate,
WherePredicateKind, lang_items,
};
@@ -218,7 +218,7 @@ fn check_fn_inner<'tcx>(
for bound in pred.bounds {
let mut visitor = RefVisitor::new(cx);
walk_param_bound(&mut visitor, bound);
- if visitor.lts.iter().any(|lt| matches!(lt.res, LifetimeName::Param(_))) {
+ if visitor.lts.iter().any(|lt| matches!(lt.kind, LifetimeKind::Param(_))) {
return;
}
if let GenericBound::Trait(ref trait_ref) = *bound {
@@ -235,7 +235,7 @@ fn check_fn_inner<'tcx>(
_ => None,
});
for bound in lifetimes {
- if bound.res != LifetimeName::Static && !bound.is_elided() {
+ if bound.kind != LifetimeKind::Static && !bound.is_elided() {
return;
}
}
@@ -421,8 +421,8 @@ fn named_lifetime_occurrences(lts: &[Lifetime]) -> Vec<(LocalDefId, usize)> {
}
fn named_lifetime(lt: &Lifetime) -> Option<LocalDefId> {
- match lt.res {
- LifetimeName::Param(id) if !lt.is_anonymous() => Some(id),
+ match lt.kind {
+ LifetimeKind::Param(id) if !lt.is_anonymous() => Some(id),
_ => None,
}
}
@@ -614,7 +614,7 @@ impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F>
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
- if let LifetimeName::Param(def_id) = lifetime.res
+ if let LifetimeKind::Param(def_id) = lifetime.kind
&& let Some(usages) = self.map.get_mut(&def_id)
{
usages.push(Usage {
@@ -826,7 +826,7 @@ fn report_elidable_lifetimes(
.iter()
.map(|<| cx.tcx.def_span(lt))
.chain(usages.iter().filter_map(|usage| {
- if let LifetimeName::Param(def_id) = usage.res
+ if let LifetimeKind::Param(def_id) = usage.kind
&& elidable_lts.contains(&def_id)
{
return Some(usage.ident.span);
diff --git a/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs b/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs
index e82211b..b5adc69 100644
--- a/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs
@@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Exp
&& let Ok(Some(fn_def)) = Instance::try_resolve(cx.tcx, cx.typing_env(), id, args)
// find the provided definition of Iterator::last
&& let Some(item) = cx.tcx.get_diagnostic_item(sym::Iterator)
- && let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name.as_str() == "last")
+ && let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name().as_str() == "last")
// if the resolved method is the same as the provided definition
&& fn_def.def_id() == last_def.def_id
{
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
index f51bdc7..7bb6252 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -48,7 +48,7 @@ pub(super) fn check<'tcx>(
&& let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id)
&& cx.tcx.trait_of_item(method_id) == Some(iter_id)
&& let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv)
- && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, "Item")
+ && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, sym::Item)
&& matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty))
{
if needs_into_iter
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 239ee6c..e4a29b6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -17,7 +17,7 @@
};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
+use rustc_middle::ty::{self, AssocTag, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
use rustc_span::symbol::Ident;
use rustc_span::{Span, sym};
@@ -241,7 +241,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
&& let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_ident_and_kind(
cx.tcx,
Ident::with_dummy_span(sym::Item),
- AssocKind::Type,
+ AssocTag::Type,
iter_trait,
)
&& let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index c03420a..6eeeea5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -78,7 +78,7 @@ fn check_unwrap_or_default(
.iter()
.flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
.find_map(|assoc| {
- if assoc.fn_has_self_parameter
+ if assoc.is_method()
&& cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1
{
Some(assoc.def_id)
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index c0e0156..20cf353 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -99,7 +99,7 @@ fn is_caller_or_fields_change(cx: &LateContext<'_>, body: &Expr<'_>, caller: &Ex
&& let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
&& let collection_ty = cx.typeck_results().expr_ty(collection)
&& implements_trait(cx, collection_ty, into_iterator_trait_id, &[])
- && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item")
+ && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, sym::Item)
&& iter_item_ty == into_iter_item_ty
&& let Some(collection_snippet) = collection.span.get_source_text(cx)
{
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 62ba301..206b0a8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -153,7 +153,7 @@ fn check_addr_of_expr(
}
if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
&& implements_trait(cx, receiver_ty, deref_trait_id, &[])
- && cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty)
+ && cx.get_associated_type(receiver_ty, deref_trait_id, sym::Target) == Some(target_ty)
// Make sure that it's actually calling the right `.to_string()`, (#10033)
// *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow)
// but that's ok for Cow::into_owned specifically)
@@ -322,7 +322,7 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb
// add `.as_ref()` to the suggestion.
let as_ref = if is_type_lang_item(cx, cx.typeck_results().expr_ty(expr), LangItem::String)
&& let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
- && cx.get_associated_type(cx.typeck_results().expr_ty(receiver), deref_trait_id, "Target")
+ && cx.get_associated_type(cx.typeck_results().expr_ty(receiver), deref_trait_id, sym::Target)
!= Some(cx.tcx.types.str_)
{
".as_ref()"
@@ -648,7 +648,7 @@ fn is_to_string_on_string_like<'a>(
&& let GenericArgKind::Type(ty) = generic_arg.unpack()
&& let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
&& let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
- && (cx.get_associated_type(ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_)
+ && (cx.get_associated_type(ty, deref_trait_id, sym::Target) == Some(cx.tcx.types.str_)
|| implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()]))
{
true
diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
index 7ee7463..e266c36 100644
--- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
@@ -81,7 +81,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
cx,
MISSING_TRAIT_METHODS,
cx.tcx.def_span(item.owner_id),
- format!("missing trait method provided by default: `{}`", assoc.name),
+ format!("missing trait method provided by default: `{}`", assoc.name()),
|diag| {
diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method");
},
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index f686cc9..e579dd5 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -299,7 +299,7 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
.associated_items(trait_def_id)
.in_definition_order()
.any(|assoc_item| {
- if assoc_item.fn_has_self_parameter {
+ if assoc_item.is_method() {
let self_ty = cx
.tcx
.fn_sig(assoc_item.def_id)
diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
index 8f1a1ee..96d3f71 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -179,7 +179,7 @@ fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mut
};
if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) {
if let [first, ..] = **adjustments {
- if let ty::Ref(.., mutability) = *first.kind() {
+ if let ty::Ref(.., mutability) = *first.source.kind() {
let level = if p.hir_id == pat.hir_id {
Level::Top
} else {
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 50ef56d..901a163 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -3,7 +3,7 @@
use clippy_utils::sugg::Sugg;
use clippy_utils::visitors::contains_unsafe_block;
use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, std_or_core};
-use hir::LifetimeName;
+use hir::LifetimeKind;
use rustc_abi::ExternAbi;
use rustc_errors::{Applicability, MultiSpan};
use rustc_hir::hir_id::{HirId, HirIdMap};
@@ -432,7 +432,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
}
None
}) {
- if let LifetimeName::Param(param_def_id) = lifetime.res
+ if let LifetimeKind::Param(param_def_id) = lifetime.kind
&& !lifetime.is_anonymous()
&& fn_sig
.output()
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index 552135b..33815cc 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -3,7 +3,6 @@
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{HirId, Impl, ItemKind, Node, Path, QPath, TraitRef, TyKind};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::AssocKind;
use rustc_session::declare_lint_pass;
use rustc_span::Span;
use rustc_span::symbol::Symbol;
@@ -85,8 +84,8 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
cx.tcx
.associated_items(did)
.in_definition_order()
- .filter(|assoc_item| matches!(assoc_item.kind, AssocKind::Fn))
- .map(|assoc_item| assoc_item.name)
+ .filter(|assoc_item| assoc_item.is_fn())
+ .map(|assoc_item| assoc_item.name())
.collect()
} else {
BTreeSet::new()
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 51c7d6f..0c17cc5 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -10,7 +10,7 @@
use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, AssocKind, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::impl_lint_pass;
use rustc_span::symbol::{Ident, kw};
use rustc_span::{Span, sym};
@@ -322,7 +322,7 @@ fn init_default_impl_for_type_if_needed(&mut self, cx: &LateContext<'_>) {
.in_definition_order()
// We're not interested in foreign implementations of the `Default` trait.
.find(|item| {
- item.kind == AssocKind::Fn && item.def_id.is_local() && item.name == kw::Default
+ item.is_fn() && item.def_id.is_local() && item.name() == kw::Default
})
&& let Some(body_node) = cx.tcx.hir_get_if_local(assoc_item.def_id)
&& let Some(body_id) = body_node.body_id()
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 582aa6e..d0067b1 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -74,7 +74,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>)
.is_some()
};
if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind
- && assoc_item.fn_has_self_parameter
+ && assoc_item.is_method()
&& let ImplItemKind::Fn(.., body_id) = &impl_item.kind
&& (!cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api)
&& let body = cx.tcx.hir_body(*body_id)
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index b813cd3..be295b5 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -8,7 +8,7 @@
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{
AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField,
- ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName,
+ ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeKind,
Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind,
};
@@ -483,7 +483,7 @@ fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool {
}
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
- left.res == right.res
+ left.kind == right.kind
}
fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
@@ -1245,8 +1245,8 @@ pub fn hash_stmt(&mut self, b: &Stmt<'_>) {
pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
lifetime.ident.name.hash(&mut self.s);
- std::mem::discriminant(&lifetime.res).hash(&mut self.s);
- if let LifetimeName::Param(param_id) = lifetime.res {
+ std::mem::discriminant(&lifetime.kind).hash(&mut self.s);
+ if let LifetimeKind::Param(param_id) = lifetime.kind {
param_id.hash(&mut self.s);
}
}
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 2ba70c4..f715fc8 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2363,14 +2363,14 @@ pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
- .any(|attr| attr.name_or_empty() == sym::no_std)
+ .any(|attr| attr.has_name(sym::no_std))
}
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
- .any(|attr| attr.name_or_empty() == sym::no_core)
+ .any(|attr| attr.has_name(sym::no_core))
}
/// Check if parent of a hir node is a trait implementation block.
@@ -3504,7 +3504,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// a::b::c ::d::sym refers to
// e::f::sym:: ::
// result should be super::super::super::super::e::f
- if let DefPathData::TypeNs(Some(s)) = l {
+ if let DefPathData::TypeNs(s) = l {
path.push(s.to_string());
}
if let DefPathData::TypeNs(_) = r {
@@ -3515,7 +3515,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// a::b::sym:: :: refers to
// c::d::e ::f::sym
// when looking at `f`
- Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()),
+ Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
// consider:
// a::b::c ::d::sym refers to
// e::f::sym:: ::
@@ -3529,7 +3529,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// `super` chain would be too long, just use the absolute path instead
once(String::from("crate"))
.chain(to.data.iter().filter_map(|el| {
- if let DefPathData::TypeNs(Some(sym)) = el.data {
+ if let DefPathData::TypeNs(sym) = el.data {
Some(sym.to_string())
} else {
None
diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs
index 29cbf62..d33e593 100644
--- a/src/tools/clippy/clippy_utils/src/ty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs
@@ -19,7 +19,7 @@
use rustc_middle::traits::EvaluationResult;
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{
- self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind,
+ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind,
GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
};
@@ -156,7 +156,7 @@ fn contains_ty_adt_constructor_opaque_inner<'tcx>(
pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
cx.tcx
.get_diagnostic_item(sym::Iterator)
- .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item"))
+ .and_then(|iter_did| cx.get_associated_type(ty, iter_did, sym::Item))
}
/// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type
@@ -1112,7 +1112,7 @@ fn helper<'tcx>(
let Some(assoc_item) = tcx.associated_items(container_id).find_by_ident_and_kind(
tcx,
Ident::with_dummy_span(assoc_ty),
- AssocKind::Type,
+ AssocTag::Type,
container_id,
) else {
debug_assert!(false, "type `{assoc_ty}` not found in `{container_id:?}`");
@@ -1345,7 +1345,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n
.associated_items(did)
.filter_by_name_unhygienic(method_name)
.next()
- .filter(|item| item.kind == AssocKind::Fn)
+ .filter(|item| item.as_tag() == AssocTag::Fn)
})
} else {
None
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 3db34ed..ba1b8f2 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -10,6 +10,7 @@
# tidy-alphabetical-start
anstyle-svg = "0.1.3"
build_helper = { path = "../../build_helper" }
+camino = "1"
colored = "2"
diff = "0.1.10"
getopts = "0.2"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 6750b52..31c696e 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -1,18 +1,17 @@
use std::collections::{BTreeSet, HashMap, HashSet};
-use std::ffi::OsString;
-use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::sync::OnceLock;
use std::{fmt, iter};
use build_helper::git::GitConfig;
+use camino::{Utf8Path, Utf8PathBuf};
use semver::Version;
use serde::de::{Deserialize, Deserializer, Error as _};
pub use self::Mode::*;
use crate::executor::{ColorConfig, OutputFormat};
-use crate::util::{PathBufExt, add_dylib_path};
+use crate::util::{Utf8PathBufExt, add_dylib_path};
macro_rules! string_enum {
($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => {
@@ -183,25 +182,25 @@ pub struct Config {
pub fail_fast: bool,
/// The library paths required for running the compiler.
- pub compile_lib_path: PathBuf,
+ pub compile_lib_path: Utf8PathBuf,
/// The library paths required for running compiled programs.
- pub run_lib_path: PathBuf,
+ pub run_lib_path: Utf8PathBuf,
/// The rustc executable.
- pub rustc_path: PathBuf,
+ pub rustc_path: Utf8PathBuf,
/// The cargo executable.
- pub cargo_path: Option<PathBuf>,
+ pub cargo_path: Option<Utf8PathBuf>,
/// Rustc executable used to compile run-make recipes.
- pub stage0_rustc_path: Option<PathBuf>,
+ pub stage0_rustc_path: Option<Utf8PathBuf>,
/// The rustdoc executable.
- pub rustdoc_path: Option<PathBuf>,
+ pub rustdoc_path: Option<Utf8PathBuf>,
/// The coverage-dump executable.
- pub coverage_dump_path: Option<PathBuf>,
+ pub coverage_dump_path: Option<Utf8PathBuf>,
/// The Python executable to use for LLDB and htmldocck.
pub python: String,
@@ -213,27 +212,27 @@ pub struct Config {
pub jsondoclint_path: Option<String>,
/// The LLVM `FileCheck` binary path.
- pub llvm_filecheck: Option<PathBuf>,
+ pub llvm_filecheck: Option<Utf8PathBuf>,
/// Path to LLVM's bin directory.
- pub llvm_bin_dir: Option<PathBuf>,
+ pub llvm_bin_dir: Option<Utf8PathBuf>,
/// The path to the Clang executable to run Clang-based tests with. If
/// `None` then these tests will be ignored.
pub run_clang_based_tests_with: Option<String>,
/// The directory containing the sources.
- pub src_root: PathBuf,
+ pub src_root: Utf8PathBuf,
/// The directory containing the test suite sources. Must be a subdirectory of `src_root`.
- pub src_test_suite_root: PathBuf,
+ pub src_test_suite_root: Utf8PathBuf,
/// Root build directory (e.g. `build/`).
- pub build_root: PathBuf,
+ pub build_root: Utf8PathBuf,
/// Test suite specific build directory (e.g. `build/host/test/ui/`).
- pub build_test_suite_root: PathBuf,
+ pub build_test_suite_root: Utf8PathBuf,
/// The directory containing the compiler sysroot
- pub sysroot_base: PathBuf,
+ pub sysroot_base: Utf8PathBuf,
/// The number of the stage under test.
pub stage: u32,
@@ -301,7 +300,7 @@ pub struct Config {
pub host: String,
/// Path to / name of the Microsoft Console Debugger (CDB) executable
- pub cdb: Option<OsString>,
+ pub cdb: Option<Utf8PathBuf>,
/// Version of CDB
pub cdb_version: Option<[u16; 4]>,
@@ -322,7 +321,7 @@ pub struct Config {
pub system_llvm: bool,
/// Path to the android tools
- pub android_cross_path: PathBuf,
+ pub android_cross_path: Utf8PathBuf,
/// Extra parameter to run adb on arm-linux-androideabi
pub adb_path: String,
@@ -346,7 +345,7 @@ pub struct Config {
pub color: ColorConfig,
/// where to find the remote test client process, if we're using it
- pub remote_test_client: Option<PathBuf>,
+ pub remote_test_client: Option<Utf8PathBuf>,
/// mode describing what file the actual ui output will be compared to
pub compare_mode: Option<CompareMode>,
@@ -414,7 +413,12 @@ pub struct Config {
/// Path to minicore aux library, used for `no_core` tests that need `core` stubs in
/// cross-compilation scenarios that do not otherwise want/need to `-Zbuild-std`. Used in e.g.
/// ABI tests.
- pub minicore_path: PathBuf,
+ pub minicore_path: Utf8PathBuf,
+
+ /// If true, run tests with the "new" executor that was written to replace
+ /// compiletest's dependency on libtest. Eventually this will become the
+ /// default, and the libtest dependency will be removed.
+ pub new_executor: bool,
}
impl Config {
@@ -804,8 +808,8 @@ fn serde_parse_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u32, D:
#[derive(Debug, Clone)]
pub struct TestPaths {
- pub file: PathBuf, // e.g., compile-test/foo/bar/baz.rs
- pub relative_dir: PathBuf, // e.g., foo/bar
+ pub file: Utf8PathBuf, // e.g., compile-test/foo/bar/baz.rs
+ pub relative_dir: Utf8PathBuf, // e.g., foo/bar
}
/// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
@@ -814,7 +818,7 @@ pub fn expected_output_path(
revision: Option<&str>,
compare_mode: &Option<CompareMode>,
kind: &str,
-) -> PathBuf {
+) -> Utf8PathBuf {
assert!(UI_EXTENSIONS.contains(&kind));
let mut parts = Vec::new();
@@ -865,7 +869,7 @@ pub fn expected_output_path(
/// ```
///
/// This is created early when tests are collected to avoid race conditions.
-pub fn output_relative_path(config: &Config, relative_dir: &Path) -> PathBuf {
+pub fn output_relative_path(config: &Config, relative_dir: &Utf8Path) -> Utf8PathBuf {
config.build_test_suite_root.join(relative_dir)
}
@@ -874,10 +878,10 @@ pub fn output_testname_unique(
config: &Config,
testpaths: &TestPaths,
revision: Option<&str>,
-) -> PathBuf {
+) -> Utf8PathBuf {
let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str());
let debugger = config.debugger.as_ref().map_or("", |m| m.to_str());
- PathBuf::from(&testpaths.file.file_stem().unwrap())
+ Utf8PathBuf::from(&testpaths.file.file_stem().unwrap())
.with_extra_extension(config.mode.output_dir_disambiguator())
.with_extra_extension(revision.unwrap_or(""))
.with_extra_extension(mode)
@@ -887,7 +891,11 @@ pub fn output_testname_unique(
/// Absolute path to the directory where all output for the given
/// test/revision should reside. Example:
/// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/
-pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+pub fn output_base_dir(
+ config: &Config,
+ testpaths: &TestPaths,
+ revision: Option<&str>,
+) -> Utf8PathBuf {
output_relative_path(config, &testpaths.relative_dir)
.join(output_testname_unique(config, testpaths, revision))
}
@@ -895,12 +903,20 @@ pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<
/// Absolute path to the base filename used as output for the given
/// test/revision. Example:
/// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/testname
-pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+pub fn output_base_name(
+ config: &Config,
+ testpaths: &TestPaths,
+ revision: Option<&str>,
+) -> Utf8PathBuf {
output_base_dir(config, testpaths, revision).join(testpaths.file.file_stem().unwrap())
}
/// Absolute path to the directory to use for incremental compilation. Example:
/// /path/to/build/host-tuple/test/ui/relative/testname.mode/testname.inc
-pub fn incremental_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+pub fn incremental_dir(
+ config: &Config,
+ testpaths: &TestPaths,
+ revision: Option<&str>,
+) -> Utf8PathBuf {
output_base_name(config, testpaths, revision).with_extension("inc")
}
diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/compute_diff.rs
index 4c942c5..509e7e1 100644
--- a/src/tools/compiletest/src/compute_diff.rs
+++ b/src/tools/compiletest/src/compute_diff.rs
@@ -1,6 +1,7 @@
use std::collections::VecDeque;
use std::fs::{File, FileType};
-use std::path::Path;
+
+use camino::Utf8Path;
#[derive(Debug, PartialEq)]
pub enum DiffLine {
@@ -112,8 +113,8 @@ pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> S
/// Returns whether any data was actually written.
pub(crate) fn write_filtered_diff<Filter>(
diff_filename: &str,
- out_dir: &Path,
- compare_dir: &Path,
+ out_dir: &Utf8Path,
+ compare_dir: &Utf8Path,
verbose: bool,
filter: Filter,
) -> bool
@@ -123,19 +124,21 @@ pub(crate) fn write_filtered_diff<Filter>(
use std::io::{Read, Write};
let mut diff_output = File::create(diff_filename).unwrap();
let mut wrote_data = false;
- for entry in walkdir::WalkDir::new(out_dir) {
+ for entry in walkdir::WalkDir::new(out_dir.as_std_path()) {
let entry = entry.expect("failed to read file");
let extension = entry.path().extension().and_then(|p| p.to_str());
if filter(entry.file_type(), extension) {
- let expected_path = compare_dir.join(entry.path().strip_prefix(&out_dir).unwrap());
+ let expected_path = compare_dir
+ .as_std_path()
+ .join(entry.path().strip_prefix(&out_dir.as_std_path()).unwrap());
let expected = if let Ok(s) = std::fs::read(&expected_path) { s } else { continue };
let actual_path = entry.path();
let actual = std::fs::read(&actual_path).unwrap();
let diff = unified_diff::diff(
&expected,
- &expected_path.to_string_lossy(),
+ &expected_path.to_str().unwrap(),
&actual,
- &actual_path.to_string_lossy(),
+ &actual_path.to_str().unwrap(),
3,
);
wrote_data |= !diff.is_empty();
diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs
index 5126e55..c133d7f 100644
--- a/src/tools/compiletest/src/debuggers.rs
+++ b/src/tools/compiletest/src/debuggers.rs
@@ -1,9 +1,9 @@
use std::env;
-use std::ffi::OsString;
-use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::Arc;
+use camino::{Utf8Path, Utf8PathBuf};
+
use crate::common::{Config, Debugger};
pub(crate) fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
@@ -78,12 +78,15 @@ fn is_pc_windows_msvc_target(target: &str) -> bool {
target.ends_with("-pc-windows-msvc")
}
-fn find_cdb(target: &str) -> Option<OsString> {
+fn find_cdb(target: &str) -> Option<Utf8PathBuf> {
if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
return None;
}
- let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
+ let pf86 = Utf8PathBuf::from_path_buf(
+ env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?.into(),
+ )
+ .unwrap();
let cdb_arch = if cfg!(target_arch = "x86") {
"x86"
} else if cfg!(target_arch = "x86_64") {
@@ -96,8 +99,7 @@ fn find_cdb(target: &str) -> Option<OsString> {
return None; // No compatible CDB.exe in the Windows 10 SDK
};
- let mut path = PathBuf::new();
- path.push(pf86);
+ let mut path = pf86;
path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
path.push(cdb_arch);
path.push(r"cdb.exe");
@@ -106,15 +108,15 @@ fn find_cdb(target: &str) -> Option<OsString> {
return None;
}
- Some(path.into_os_string())
+ Some(path)
}
/// Returns Path to CDB
pub(crate) fn analyze_cdb(
cdb: Option<String>,
target: &str,
-) -> (Option<OsString>, Option<[u16; 4]>) {
- let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
+) -> (Option<Utf8PathBuf>, Option<[u16; 4]>) {
+ let cdb = cdb.map(Utf8PathBuf::from).or_else(|| find_cdb(target));
let mut version = None;
if let Some(cdb) = cdb.as_ref() {
@@ -143,7 +145,7 @@ pub(crate) fn analyze_cdb(
pub(crate) fn analyze_gdb(
gdb: Option<String>,
target: &str,
- android_cross_path: &Path,
+ android_cross_path: &Utf8Path,
) -> (Option<String>, Option<u32>) {
#[cfg(not(windows))]
const GDB_FALLBACK: &str = "gdb";
@@ -152,10 +154,7 @@ pub(crate) fn analyze_gdb(
let fallback_gdb = || {
if is_android_gdb_target(target) {
- let mut gdb_path = match android_cross_path.to_str() {
- Some(x) => x.to_owned(),
- None => panic!("cannot find android cross path"),
- };
+ let mut gdb_path = android_cross_path.to_string();
gdb_path.push_str("/bin/gdb");
gdb_path
} else {
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 086a8a6..1449e9a 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -44,6 +44,7 @@
"ignore-arm-unknown-linux-gnueabihf",
"ignore-arm-unknown-linux-musleabi",
"ignore-arm-unknown-linux-musleabihf",
+ "ignore-auxiliary",
"ignore-avr",
"ignore-beta",
"ignore-cdb",
@@ -177,6 +178,7 @@
"only-32bit",
"only-64bit",
"only-aarch64",
+ "only-aarch64-apple-darwin",
"only-aarch64-unknown-linux-gnu",
"only-apple",
"only-arm",
@@ -190,6 +192,7 @@
"only-gnu",
"only-i686-pc-windows-gnu",
"only-i686-pc-windows-msvc",
+ "only-i686-unknown-linux-gnu",
"only-ios",
"only-linux",
"only-loongarch64",
@@ -221,6 +224,7 @@
"only-windows-msvc",
"only-x86",
"only-x86_64",
+ "only-x86_64-apple-darwin",
"only-x86_64-fortanix-unknown-sgx",
"only-x86_64-pc-windows-gnu",
"only-x86_64-pc-windows-msvc",
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 64d68eb..3bb9827 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -2,9 +2,9 @@
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
-use std::path::Path;
use std::sync::OnceLock;
+use camino::Utf8Path;
use regex::Regex;
use tracing::*;
@@ -102,8 +102,8 @@ pub fn line_num_str(&self) -> String {
///
/// If revision is not None, then we look
/// for `//[X]~` instead, where `X` is the current revision.
-pub fn load_errors(testfile: &Path, revision: Option<&str>) -> Vec<Error> {
- let rdr = BufReader::new(File::open(testfile).unwrap());
+pub fn load_errors(testfile: &Utf8Path, revision: Option<&str>) -> Vec<Error> {
+ let rdr = BufReader::new(File::open(testfile.as_std_path()).unwrap());
// `last_nonfollow_error` tracks the most recently seen
// line with an error template that did not use the
diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs
index 527d6b8..0c173d4 100644
--- a/src/tools/compiletest/src/executor.rs
+++ b/src/tools/compiletest/src/executor.rs
@@ -1,22 +1,251 @@
-//! This module encapsulates all of the code that interacts directly with
-//! libtest, to execute the collected tests.
-//!
-//! This will hopefully make it easier to migrate away from libtest someday.
+//! This module contains a reimplementation of the subset of libtest
+//! functionality needed by compiletest.
use std::borrow::Cow;
-use std::io;
-use std::sync::Arc;
+use std::collections::HashMap;
+use std::hash::{BuildHasherDefault, DefaultHasher};
+use std::num::NonZero;
+use std::sync::{Arc, Mutex, mpsc};
+use std::{env, hint, io, mem, panic, thread};
use crate::common::{Config, TestPaths};
-/// Delegates to libtest to run the list of collected tests.
-///
-/// Returns `Ok(true)` if all tests passed, or `Ok(false)` if one or more tests failed.
-pub(crate) fn execute_tests(config: &Config, tests: Vec<CollectedTest>) -> io::Result<bool> {
- let opts = test_opts(config);
- let tests = tests.into_iter().map(|t| t.into_libtest()).collect::<Vec<_>>();
+mod deadline;
+mod json;
+pub(crate) mod libtest;
- test::run_tests_console(&opts, tests)
+pub(crate) fn run_tests(config: &Config, tests: Vec<CollectedTest>) -> bool {
+ let tests_len = tests.len();
+ let filtered = filter_tests(config, tests);
+ // Iterator yielding tests that haven't been started yet.
+ let mut fresh_tests = (0..).map(TestId).zip(&filtered);
+
+ let concurrency = get_concurrency();
+ assert!(concurrency > 0);
+ let concurrent_capacity = concurrency.min(filtered.len());
+
+ let mut listener = json::Listener::new();
+ let mut running_tests = HashMap::with_capacity_and_hasher(
+ concurrent_capacity,
+ BuildHasherDefault::<DefaultHasher>::new(),
+ );
+ let mut deadline_queue = deadline::DeadlineQueue::with_capacity(concurrent_capacity);
+
+ let num_filtered_out = tests_len - filtered.len();
+ listener.suite_started(filtered.len(), num_filtered_out);
+
+ // Channel used by test threads to report the test outcome when done.
+ let (completion_tx, completion_rx) = mpsc::channel::<TestCompletion>();
+
+ // Unlike libtest, we don't have a separate code path for concurrency=1.
+ // In that case, the tests will effectively be run serially anyway.
+ loop {
+ // Spawn new test threads, up to the concurrency limit.
+ // FIXME(let_chains): Use a let-chain here when stable in bootstrap.
+ 'spawn: while running_tests.len() < concurrency {
+ let Some((id, test)) = fresh_tests.next() else { break 'spawn };
+ listener.test_started(test);
+ deadline_queue.push(id, test);
+ let join_handle = spawn_test_thread(id, test, completion_tx.clone());
+ running_tests.insert(id, RunningTest { test, join_handle });
+ }
+
+ // If all running tests have finished, and there weren't any unstarted
+ // tests to spawn, then we're done.
+ if running_tests.is_empty() {
+ break;
+ }
+
+ let completion = deadline_queue
+ .read_channel_while_checking_deadlines(&completion_rx, |_id, test| {
+ listener.test_timed_out(test);
+ })
+ .expect("receive channel should never be closed early");
+
+ let RunningTest { test, join_handle } = running_tests.remove(&completion.id).unwrap();
+ if let Some(join_handle) = join_handle {
+ join_handle.join().unwrap_or_else(|_| {
+ panic!("thread for `{}` panicked after reporting completion", test.desc.name)
+ });
+ }
+
+ listener.test_finished(test, &completion);
+
+ if completion.outcome.is_failed() && config.fail_fast {
+ // Prevent any other in-flight threads from panicking when they
+ // write to the completion channel.
+ mem::forget(completion_rx);
+ break;
+ }
+ }
+
+ let suite_passed = listener.suite_finished();
+ suite_passed
+}
+
+/// Spawns a thread to run a single test, and returns the thread's join handle.
+///
+/// Returns `None` if the test was ignored, so no thread was spawned.
+fn spawn_test_thread(
+ id: TestId,
+ test: &CollectedTest,
+ completion_tx: mpsc::Sender<TestCompletion>,
+) -> Option<thread::JoinHandle<()>> {
+ if test.desc.ignore && !test.config.run_ignored {
+ completion_tx
+ .send(TestCompletion { id, outcome: TestOutcome::Ignored, stdout: None })
+ .unwrap();
+ return None;
+ }
+
+ let runnable_test = RunnableTest::new(test);
+ let should_panic = test.desc.should_panic;
+ let run_test = move || run_test_inner(id, should_panic, runnable_test, completion_tx);
+
+ let thread_builder = thread::Builder::new().name(test.desc.name.clone());
+ let join_handle = thread_builder.spawn(run_test).unwrap();
+ Some(join_handle)
+}
+
+/// Runs a single test, within the dedicated thread spawned by the caller.
+fn run_test_inner(
+ id: TestId,
+ should_panic: ShouldPanic,
+ runnable_test: RunnableTest,
+ completion_sender: mpsc::Sender<TestCompletion>,
+) {
+ let is_capture = !runnable_test.config.nocapture;
+ let capture_buf = is_capture.then(|| Arc::new(Mutex::new(vec![])));
+
+ if let Some(capture_buf) = &capture_buf {
+ io::set_output_capture(Some(Arc::clone(capture_buf)));
+ }
+
+ let panic_payload = panic::catch_unwind(move || runnable_test.run()).err();
+
+ if is_capture {
+ io::set_output_capture(None);
+ }
+
+ let outcome = match (should_panic, panic_payload) {
+ (ShouldPanic::No, None) | (ShouldPanic::Yes, Some(_)) => TestOutcome::Succeeded,
+ (ShouldPanic::No, Some(_)) => TestOutcome::Failed { message: None },
+ (ShouldPanic::Yes, None) => {
+ TestOutcome::Failed { message: Some("test did not panic as expected") }
+ }
+ };
+ let stdout = capture_buf.map(|mutex| mutex.lock().unwrap_or_else(|e| e.into_inner()).to_vec());
+
+ completion_sender.send(TestCompletion { id, outcome, stdout }).unwrap();
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+struct TestId(usize);
+
+struct RunnableTest {
+ config: Arc<Config>,
+ testpaths: TestPaths,
+ revision: Option<String>,
+}
+
+impl RunnableTest {
+ fn new(test: &CollectedTest) -> Self {
+ let config = Arc::clone(&test.config);
+ let testpaths = test.testpaths.clone();
+ let revision = test.revision.clone();
+ Self { config, testpaths, revision }
+ }
+
+ fn run(&self) {
+ __rust_begin_short_backtrace(|| {
+ crate::runtest::run(
+ Arc::clone(&self.config),
+ &self.testpaths,
+ self.revision.as_deref(),
+ );
+ });
+ }
+}
+
+/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
+#[inline(never)]
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+ let result = f();
+
+ // prevent this frame from being tail-call optimised away
+ hint::black_box(result)
+}
+
+struct RunningTest<'a> {
+ test: &'a CollectedTest,
+ join_handle: Option<thread::JoinHandle<()>>,
+}
+
+/// Test completion message sent by individual test threads when their test
+/// finishes (successfully or unsuccessfully).
+struct TestCompletion {
+ id: TestId,
+ outcome: TestOutcome,
+ stdout: Option<Vec<u8>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+enum TestOutcome {
+ Succeeded,
+ Failed { message: Option<&'static str> },
+ Ignored,
+}
+
+impl TestOutcome {
+ fn is_failed(&self) -> bool {
+ matches!(self, Self::Failed { .. })
+ }
+}
+
+/// Applies command-line arguments for filtering/skipping tests by name.
+///
+/// Adapted from `filter_tests` in libtest.
+///
+/// FIXME(#139660): After the libtest dependency is removed, redesign the whole
+/// filtering system to do a better job of understanding and filtering _paths_,
+/// instead of being tied to libtest's substring/exact matching behaviour.
+fn filter_tests(opts: &Config, tests: Vec<CollectedTest>) -> Vec<CollectedTest> {
+ let mut filtered = tests;
+
+ let matches_filter = |test: &CollectedTest, filter_str: &str| {
+ let test_name = &test.desc.name;
+ if opts.filter_exact { test_name == filter_str } else { test_name.contains(filter_str) }
+ };
+
+ // Remove tests that don't match the test filter
+ if !opts.filters.is_empty() {
+ filtered.retain(|test| opts.filters.iter().any(|filter| matches_filter(test, filter)));
+ }
+
+ // Skip tests that match any of the skip filters
+ if !opts.skip.is_empty() {
+ filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
+ }
+
+ filtered
+}
+
+/// Determines the number of tests to run concurrently.
+///
+/// Copied from `get_concurrency` in libtest.
+///
+/// FIXME(#139660): After the libtest dependency is removed, consider making
+/// bootstrap specify the number of threads on the command-line, instead of
+/// propagating the `RUST_TEST_THREADS` environment variable.
+fn get_concurrency() -> usize {
+ if let Ok(value) = env::var("RUST_TEST_THREADS") {
+ match value.parse::<NonZero<usize>>().ok() {
+ Some(n) => n.get(),
+ _ => panic!("RUST_TEST_THREADS is `{value}`, should be a positive integer."),
+ }
+ } else {
+ thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
+ }
}
/// Information needed to create a `test::TestDescAndFn`.
@@ -35,45 +264,6 @@ pub(crate) struct CollectedTestDesc {
pub(crate) should_panic: ShouldPanic,
}
-impl CollectedTest {
- fn into_libtest(self) -> test::TestDescAndFn {
- let Self { desc, config, testpaths, revision } = self;
- let CollectedTestDesc { name, ignore, ignore_message, should_panic } = desc;
-
- // Libtest requires the ignore message to be a &'static str, so we might
- // have to leak memory to create it. This is fine, as we only do so once
- // per test, so the leak won't grow indefinitely.
- let ignore_message = ignore_message.map(|msg| match msg {
- Cow::Borrowed(s) => s,
- Cow::Owned(s) => &*String::leak(s),
- });
-
- let desc = test::TestDesc {
- name: test::DynTestName(name),
- ignore,
- ignore_message,
- source_file: "",
- start_line: 0,
- start_col: 0,
- end_line: 0,
- end_col: 0,
- should_panic: should_panic.to_libtest(),
- compile_fail: false,
- no_run: false,
- test_type: test::TestType::Unknown,
- };
-
- // This closure is invoked when libtest returns control to compiletest
- // to execute the test.
- let testfn = test::DynTestFn(Box::new(move || {
- crate::runtest::run(config, &testpaths, revision.as_deref());
- Ok(())
- }));
-
- test::TestDescAndFn { desc, testfn }
- }
-}
-
/// Whether console output should be colored or not.
#[derive(Copy, Clone, Default, Debug)]
pub enum ColorConfig {
@@ -83,16 +273,6 @@ pub enum ColorConfig {
NeverColor,
}
-impl ColorConfig {
- fn to_libtest(self) -> test::ColorConfig {
- match self {
- Self::AutoColor => test::ColorConfig::AutoColor,
- Self::AlwaysColor => test::ColorConfig::AlwaysColor,
- Self::NeverColor => test::ColorConfig::NeverColor,
- }
- }
-}
-
/// Format of the test results output.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum OutputFormat {
@@ -105,52 +285,9 @@ pub enum OutputFormat {
Json,
}
-impl OutputFormat {
- fn to_libtest(self) -> test::OutputFormat {
- match self {
- Self::Pretty => test::OutputFormat::Pretty,
- Self::Terse => test::OutputFormat::Terse,
- Self::Json => test::OutputFormat::Json,
- }
- }
-}
-
/// Whether test is expected to panic or not.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) enum ShouldPanic {
No,
Yes,
}
-
-impl ShouldPanic {
- fn to_libtest(self) -> test::ShouldPanic {
- match self {
- Self::No => test::ShouldPanic::No,
- Self::Yes => test::ShouldPanic::Yes,
- }
- }
-}
-
-fn test_opts(config: &Config) -> test::TestOpts {
- test::TestOpts {
- exclude_should_panic: false,
- filters: config.filters.clone(),
- filter_exact: config.filter_exact,
- run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
- format: config.format.to_libtest(),
- logfile: None,
- run_tests: true,
- bench_benchmarks: true,
- nocapture: config.nocapture,
- color: config.color.to_libtest(),
- shuffle: false,
- shuffle_seed: None,
- test_threads: None,
- skip: config.skip.clone(),
- list: false,
- options: test::Options::new(),
- time_options: None,
- force_run_in_process: false,
- fail_fast: config.fail_fast,
- }
-}
diff --git a/src/tools/compiletest/src/executor/deadline.rs b/src/tools/compiletest/src/executor/deadline.rs
new file mode 100644
index 0000000..83b8591
--- /dev/null
+++ b/src/tools/compiletest/src/executor/deadline.rs
@@ -0,0 +1,78 @@
+use std::collections::VecDeque;
+use std::sync::mpsc::{self, RecvError, RecvTimeoutError};
+use std::time::{Duration, Instant};
+
+use crate::executor::{CollectedTest, TestId};
+
+const TEST_WARN_TIMEOUT_S: u64 = 60;
+
+struct DeadlineEntry<'a> {
+ id: TestId,
+ test: &'a CollectedTest,
+ deadline: Instant,
+}
+
+pub(crate) struct DeadlineQueue<'a> {
+ queue: VecDeque<DeadlineEntry<'a>>,
+}
+
+impl<'a> DeadlineQueue<'a> {
+ pub(crate) fn with_capacity(capacity: usize) -> Self {
+ Self { queue: VecDeque::with_capacity(capacity) }
+ }
+
+ pub(crate) fn push(&mut self, id: TestId, test: &'a CollectedTest) {
+ let deadline = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
+ self.queue.push_back(DeadlineEntry { id, test, deadline });
+ }
+
+ /// Equivalent to `rx.read()`, except that if any test exceeds its deadline
+ /// during the wait, the given callback will also be called for that test.
+ pub(crate) fn read_channel_while_checking_deadlines<T>(
+ &mut self,
+ rx: &mpsc::Receiver<T>,
+ mut on_deadline_passed: impl FnMut(TestId, &CollectedTest),
+ ) -> Result<T, RecvError> {
+ loop {
+ let Some(next_deadline) = self.next_deadline() else {
+ // All currently-running tests have already exceeded their
+ // deadline, so do a normal receive.
+ return rx.recv();
+ };
+ let wait_duration = next_deadline.saturating_duration_since(Instant::now());
+
+ let recv_result = rx.recv_timeout(wait_duration);
+ match recv_result {
+ Ok(value) => return Ok(value),
+ Err(RecvTimeoutError::Timeout) => {
+ // Notify the callback of tests that have exceeded their
+ // deadline, then loop and do annother channel read.
+ for DeadlineEntry { id, test, .. } in self.remove_tests_past_deadline() {
+ on_deadline_passed(id, test);
+ }
+ }
+ Err(RecvTimeoutError::Disconnected) => return Err(RecvError),
+ }
+ }
+ }
+
+ fn next_deadline(&self) -> Option<Instant> {
+ Some(self.queue.front()?.deadline)
+ }
+
+ fn remove_tests_past_deadline(&mut self) -> Vec<DeadlineEntry<'a>> {
+ let now = Instant::now();
+ let mut timed_out = vec![];
+ while let Some(deadline_entry) = pop_front_if(&mut self.queue, |entry| now < entry.deadline)
+ {
+ timed_out.push(deadline_entry);
+ }
+ timed_out
+ }
+}
+
+/// FIXME(vec_deque_pop_if): Use `VecDeque::pop_front_if` when it is stable in bootstrap.
+fn pop_front_if<T>(queue: &mut VecDeque<T>, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
+ let first = queue.front()?;
+ if predicate(first) { queue.pop_front() } else { None }
+}
diff --git a/src/tools/compiletest/src/executor/json.rs b/src/tools/compiletest/src/executor/json.rs
new file mode 100644
index 0000000..c74ed81
--- /dev/null
+++ b/src/tools/compiletest/src/executor/json.rs
@@ -0,0 +1,111 @@
+//! Collects statistics and emits suite/test events as JSON messages, using
+//! the same JSON format as libtest's JSON formatter.
+//!
+//! These messages are then parsed by bootstrap, which replaces them with
+//! user-friendly terminal output.
+
+use std::time::Instant;
+
+use serde_json::json;
+
+use crate::executor::{CollectedTest, TestCompletion, TestOutcome};
+
+pub(crate) struct Listener {
+ suite_start: Option<Instant>,
+ passed: usize,
+ failed: usize,
+ ignored: usize,
+ filtered_out: usize,
+}
+
+impl Listener {
+ pub(crate) fn new() -> Self {
+ Self { suite_start: None, passed: 0, failed: 0, ignored: 0, filtered_out: 0 }
+ }
+
+ fn print_message(&self, message: &serde_json::Value) {
+ println!("{message}");
+ }
+
+ fn now(&self) -> Instant {
+ Instant::now()
+ }
+
+ pub(crate) fn suite_started(&mut self, test_count: usize, filtered_out: usize) {
+ self.suite_start = Some(self.now());
+ self.filtered_out = filtered_out;
+ let message = json!({ "type": "suite", "event": "started", "test_count": test_count });
+ self.print_message(&message);
+ }
+
+ pub(crate) fn test_started(&mut self, test: &CollectedTest) {
+ let name = test.desc.name.as_str();
+ let message = json!({ "type": "test", "event": "started", "name": name });
+ self.print_message(&message);
+ }
+
+ pub(crate) fn test_timed_out(&mut self, test: &CollectedTest) {
+ let name = test.desc.name.as_str();
+ let message = json!({ "type": "test", "event": "timeout", "name": name });
+ self.print_message(&message);
+ }
+
+ pub(crate) fn test_finished(&mut self, test: &CollectedTest, completion: &TestCompletion) {
+ let event;
+ let name = test.desc.name.as_str();
+ let mut maybe_message = None;
+ let maybe_stdout = completion.stdout.as_deref().map(String::from_utf8_lossy);
+
+ match completion.outcome {
+ TestOutcome::Succeeded => {
+ self.passed += 1;
+ event = "ok";
+ }
+ TestOutcome::Failed { message } => {
+ self.failed += 1;
+ maybe_message = message;
+ event = "failed";
+ }
+ TestOutcome::Ignored => {
+ self.ignored += 1;
+ maybe_message = test.desc.ignore_message.as_deref();
+ event = "ignored";
+ }
+ };
+
+ // This emits optional fields as `null`, instead of omitting them
+ // completely as libtest does, but bootstrap can parse the result
+ // either way.
+ let json = json!({
+ "type": "test",
+ "event": event,
+ "name": name,
+ "message": maybe_message,
+ "stdout": maybe_stdout,
+ });
+
+ self.print_message(&json);
+ }
+
+ pub(crate) fn suite_finished(&mut self) -> bool {
+ let exec_time = self.suite_start.map(|start| (self.now() - start).as_secs_f64());
+ let suite_passed = self.failed == 0;
+
+ let event = if suite_passed { "ok" } else { "failed" };
+ let message = json!({
+ "type": "suite",
+ "event": event,
+ "passed": self.passed,
+ "failed": self.failed,
+ "ignored": self.ignored,
+ // Compiletest doesn't run any benchmarks, but we still need to set this
+ // field to 0 so that bootstrap's JSON parser can read our message.
+ "measured": 0,
+ "filtered_out": self.filtered_out,
+ "exec_time": exec_time,
+ });
+
+ self.print_message(&message);
+ suite_passed
+ }
+}
diff --git a/src/tools/compiletest/src/executor/libtest.rs b/src/tools/compiletest/src/executor/libtest.rs
new file mode 100644
index 0000000..032b3f4
--- /dev/null
+++ b/src/tools/compiletest/src/executor/libtest.rs
@@ -0,0 +1,111 @@
+//! This submodule encapsulates all of the code that actually interacts with
+//! libtest, so that it can be easily removed after the new executor becomes
+//! the default.
+
+use std::borrow::Cow;
+use std::io;
+
+use crate::common::Config;
+use crate::executor::{CollectedTest, CollectedTestDesc, ColorConfig, OutputFormat, ShouldPanic};
+
+/// Delegates to libtest to run the list of collected tests.
+///
+/// Returns `Ok(true)` if all tests passed, or `Ok(false)` if one or more tests failed.
+pub(crate) fn execute_tests(config: &Config, tests: Vec<CollectedTest>) -> io::Result<bool> {
+ let opts = test_opts(config);
+ let tests = tests.into_iter().map(|t| t.into_libtest()).collect::<Vec<_>>();
+
+ test::run_tests_console(&opts, tests)
+}
+
+impl CollectedTest {
+ fn into_libtest(self) -> test::TestDescAndFn {
+ let Self { desc, config, testpaths, revision } = self;
+ let CollectedTestDesc { name, ignore, ignore_message, should_panic } = desc;
+
+ // Libtest requires the ignore message to be a &'static str, so we might
+ // have to leak memory to create it. This is fine, as we only do so once
+ // per test, so the leak won't grow indefinitely.
+ let ignore_message = ignore_message.map(|msg| match msg {
+ Cow::Borrowed(s) => s,
+ Cow::Owned(s) => &*String::leak(s),
+ });
+
+ let desc = test::TestDesc {
+ name: test::DynTestName(name),
+ ignore,
+ ignore_message,
+ source_file: "",
+ start_line: 0,
+ start_col: 0,
+ end_line: 0,
+ end_col: 0,
+ should_panic: should_panic.to_libtest(),
+ compile_fail: false,
+ no_run: false,
+ test_type: test::TestType::Unknown,
+ };
+
+ // This closure is invoked when libtest returns control to compiletest
+ // to execute the test.
+ let testfn = test::DynTestFn(Box::new(move || {
+ crate::runtest::run(config, &testpaths, revision.as_deref());
+ Ok(())
+ }));
+
+ test::TestDescAndFn { desc, testfn }
+ }
+}
+
+impl ColorConfig {
+ fn to_libtest(self) -> test::ColorConfig {
+ match self {
+ Self::AutoColor => test::ColorConfig::AutoColor,
+ Self::AlwaysColor => test::ColorConfig::AlwaysColor,
+ Self::NeverColor => test::ColorConfig::NeverColor,
+ }
+ }
+}
+
+impl OutputFormat {
+ fn to_libtest(self) -> test::OutputFormat {
+ match self {
+ Self::Pretty => test::OutputFormat::Pretty,
+ Self::Terse => test::OutputFormat::Terse,
+ Self::Json => test::OutputFormat::Json,
+ }
+ }
+}
+
+impl ShouldPanic {
+ fn to_libtest(self) -> test::ShouldPanic {
+ match self {
+ Self::No => test::ShouldPanic::No,
+ Self::Yes => test::ShouldPanic::Yes,
+ }
+ }
+}
+
+fn test_opts(config: &Config) -> test::TestOpts {
+ test::TestOpts {
+ exclude_should_panic: false,
+ filters: config.filters.clone(),
+ filter_exact: config.filter_exact,
+ run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No },
+ format: config.format.to_libtest(),
+ logfile: None,
+ run_tests: true,
+ bench_benchmarks: true,
+ nocapture: config.nocapture,
+ color: config.color.to_libtest(),
+ shuffle: false,
+ shuffle_seed: None,
+ test_threads: None,
+ skip: config.skip.clone(),
+ list: false,
+ options: test::Options::new(),
+ time_options: None,
+ force_run_in_process: false,
+ fail_fast: config.fail_fast,
+ }
+}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 01a6ae0..2b203bb 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -1,11 +1,11 @@
-use std::collections::{HashMap, HashSet};
+use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
-use std::path::{Path, PathBuf};
use std::process::Command;
+use camino::{Utf8Path, Utf8PathBuf};
use semver::Version;
use tracing::*;
@@ -45,12 +45,12 @@ pub struct EarlyProps {
}
impl EarlyProps {
- pub fn from_file(config: &Config, testfile: &Path) -> Self {
- let file = File::open(testfile).expect("open test file to parse earlyprops");
+ pub fn from_file(config: &Config, testfile: &Utf8Path) -> Self {
+ let file = File::open(testfile.as_std_path()).expect("open test file to parse earlyprops");
Self::from_reader(config, testfile, file)
}
- pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
+ pub fn from_reader<R: Read>(config: &Config, testfile: &Utf8Path, rdr: R) -> Self {
let mut props = EarlyProps::default();
let mut poisoned = false;
iter_header(
@@ -66,7 +66,7 @@ pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
);
if poisoned {
- eprintln!("errors encountered during EarlyProps parsing: {}", testfile.display());
+ eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
panic!("errors encountered during EarlyProps parsing");
}
@@ -88,7 +88,7 @@ pub struct TestProps {
pub doc_flags: Vec<String>,
// If present, the name of a file that this test should match when
// pretty-printed
- pub pp_exact: Option<PathBuf>,
+ pub pp_exact: Option<Utf8PathBuf>,
/// Auxiliary crates that should be built and made available to this test.
pub(crate) aux: AuxProps,
// Environment settings to use for compiling
@@ -134,7 +134,7 @@ pub struct TestProps {
// not set by end-users; rather it is set by the incremental
// testing harness and used when generating compilation
// arguments. (In particular, it propagates to the aux-builds.)
- pub incremental_dir: Option<PathBuf>,
+ pub incremental_dir: Option<Utf8PathBuf>,
// If `true`, this test will use incremental compilation.
//
// This can be set manually with the `incremental` header, or implicitly
@@ -198,7 +198,7 @@ pub struct TestProps {
/// that don't otherwise want/need `-Z build-std`.
pub add_core_stubs: bool,
/// Whether line annotatins are required for the given error kind.
- pub require_annotations: HashMap<ErrorKind, bool>,
+ pub dont_require_annotations: HashSet<ErrorKind>,
}
mod directives {
@@ -301,17 +301,16 @@ pub fn new() -> Self {
no_auto_check_cfg: false,
has_enzyme: false,
add_core_stubs: false,
- require_annotations: HashMap::from([
- (ErrorKind::Help, true),
- (ErrorKind::Note, true),
- (ErrorKind::Error, true),
- (ErrorKind::Warning, true),
- (ErrorKind::Suggestion, false),
- ]),
+ dont_require_annotations: Default::default(),
}
}
- pub fn from_aux_file(&self, testfile: &Path, revision: Option<&str>, config: &Config) -> Self {
+ pub fn from_aux_file(
+ &self,
+ testfile: &Utf8Path,
+ revision: Option<&str>,
+ config: &Config,
+ ) -> Self {
let mut props = TestProps::new();
// copy over select properties to the aux build:
@@ -322,10 +321,10 @@ pub fn from_aux_file(&self, testfile: &Path, revision: Option<&str>, config: &Co
props
}
- pub fn from_file(testfile: &Path, revision: Option<&str>, config: &Config) -> Self {
+ pub fn from_file(testfile: &Utf8Path, revision: Option<&str>, config: &Config) -> Self {
let mut props = TestProps::new();
props.load_from(testfile, revision, config);
- props.exec_env.push(("RUSTC".to_string(), config.rustc_path.display().to_string()));
+ props.exec_env.push(("RUSTC".to_string(), config.rustc_path.to_string()));
match (props.pass_mode, props.fail_mode) {
(None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check),
@@ -340,10 +339,10 @@ pub fn from_file(testfile: &Path, revision: Option<&str>, config: &Config) -> Se
/// tied to a particular revision `foo` (indicated by writing
/// `//@[foo]`), then the property is ignored unless `test_revision` is
/// `Some("foo")`.
- fn load_from(&mut self, testfile: &Path, test_revision: Option<&str>, config: &Config) {
+ fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config: &Config) {
let mut has_edition = false;
if !testfile.is_dir() {
- let file = File::open(testfile).unwrap();
+ let file = File::open(testfile.as_std_path()).unwrap();
let mut poisoned = false;
@@ -389,14 +388,22 @@ fn split_flags(flags: &str) -> Vec<String> {
}
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
- self.compile_flags.extend(split_flags(&flags));
+ let flags = split_flags(&flags);
+ for flag in &flags {
+ if flag == "--edition" || flag.starts_with("--edition=") {
+ panic!("you must use `//@ edition` to configure the edition");
+ }
+ }
+ self.compile_flags.extend(flags);
}
if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
panic!("`compiler-flags` directive should be spelled `compile-flags`");
}
if let Some(edition) = config.parse_edition(ln) {
- self.compile_flags.push(format!("--edition={}", edition.trim()));
+ // The edition is added at the start, since flags from //@compile-flags must
+ // be passed to rustc last.
+ self.compile_flags.insert(0, format!("--edition={}", edition.trim()));
has_edition = true;
}
@@ -585,14 +592,14 @@ fn split_flags(flags: &str) -> Vec<String> {
if let Some(err_kind) =
config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS)
{
- self.require_annotations
- .insert(ErrorKind::expect_from_user_str(&err_kind), false);
+ self.dont_require_annotations
+ .insert(ErrorKind::expect_from_user_str(err_kind.trim()));
}
},
);
if poisoned {
- eprintln!("errors encountered during TestProps parsing: {}", testfile.display());
+ eprintln!("errors encountered during TestProps parsing: {}", testfile);
panic!("errors encountered during TestProps parsing");
}
}
@@ -624,7 +631,9 @@ fn split_flags(flags: &str) -> Vec<String> {
}
if let (Some(edition), false) = (&config.edition, has_edition) {
- self.compile_flags.push(format!("--edition={}", edition));
+ // The edition is added at the start, since flags from //@compile-flags must be passed
+ // to rustc last.
+ self.compile_flags.insert(0, format!("--edition={}", edition));
}
}
@@ -861,7 +870,7 @@ fn iter_header(
mode: Mode,
_suite: &str,
poisoned: &mut bool,
- testfile: &Path,
+ testfile: &Utf8Path,
rdr: impl Read,
it: &mut dyn FnMut(DirectiveLine<'_>),
) {
@@ -913,9 +922,7 @@ fn iter_header(
eprintln!(
"error: detected unknown compiletest test directive `{}` in {}:{}",
- directive_line.raw_directive,
- testfile.display(),
- line_number,
+ directive_line.raw_directive, testfile, line_number,
);
return;
@@ -927,10 +934,7 @@ fn iter_header(
eprintln!(
"error: detected trailing compiletest test directive `{}` in {}:{}\n \
help: put the trailing directive in it's own line: `//@ {}`",
- trailing_directive,
- testfile.display(),
- line_number,
- trailing_directive,
+ trailing_directive, testfile, line_number, trailing_directive,
);
return;
@@ -942,7 +946,12 @@ fn iter_header(
}
impl Config {
- fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec<String>) {
+ fn parse_and_update_revisions(
+ &self,
+ testfile: &Utf8Path,
+ line: &str,
+ existing: &mut Vec<String>,
+ ) {
const FORBIDDEN_REVISION_NAMES: [&str; 2] = [
// `//@ revisions: true false` Implying `--cfg=true` and `--cfg=false` makes it very
// weird for the test, since if the test writer wants a cfg of the same revision name
@@ -955,26 +964,19 @@ fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut
if let Some(raw) = self.parse_name_value_directive(line, "revisions") {
if self.mode == Mode::RunMake {
- panic!("`run-make` tests do not support revisions: {}", testfile.display());
+ panic!("`run-make` tests do not support revisions: {}", testfile);
}
let mut duplicates: HashSet<_> = existing.iter().cloned().collect();
for revision in raw.split_whitespace() {
if !duplicates.insert(revision.to_string()) {
- panic!(
- "duplicate revision: `{}` in line `{}`: {}",
- revision,
- raw,
- testfile.display()
- );
+ panic!("duplicate revision: `{}` in line `{}`: {}", revision, raw, testfile);
}
if FORBIDDEN_REVISION_NAMES.contains(&revision) {
panic!(
"revision name `{revision}` is not permitted: `{}` in line `{}`: {}",
- revision,
- raw,
- testfile.display()
+ revision, raw, testfile
);
}
@@ -985,8 +987,7 @@ fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut
"revision name `{revision}` is not permitted in a test suite that uses \
`FileCheck` annotations as it is confusing when used as custom `FileCheck` \
prefix: `{revision}` in line `{}`: {}",
- raw,
- testfile.display()
+ raw, testfile
);
}
@@ -1006,11 +1007,11 @@ fn parse_env(nv: String) -> (String, String) {
(name.to_owned(), value.to_owned())
}
- fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {
+ fn parse_pp_exact(&self, line: &str, testfile: &Utf8Path) -> Option<Utf8PathBuf> {
if let Some(s) = self.parse_name_value_directive(line, "pp-exact") {
- Some(PathBuf::from(&s))
+ Some(Utf8PathBuf::from(&s))
} else if self.parse_name_directive(line, "pp-exact") {
- testfile.file_name().map(PathBuf::from)
+ testfile.file_name().map(Utf8PathBuf::from)
} else {
None
}
@@ -1116,20 +1117,19 @@ fn expand_variables(mut value: String, config: &Config) -> String {
if value.contains(CWD) {
let cwd = env::current_dir().unwrap();
- value = value.replace(CWD, &cwd.to_string_lossy());
+ value = value.replace(CWD, &cwd.to_str().unwrap());
}
if value.contains(SRC_BASE) {
- value = value.replace(SRC_BASE, &config.src_test_suite_root.to_str().unwrap());
+ value = value.replace(SRC_BASE, &config.src_test_suite_root.as_str());
}
if value.contains(TEST_SUITE_BUILD_BASE) {
- value =
- value.replace(TEST_SUITE_BUILD_BASE, &config.build_test_suite_root.to_str().unwrap());
+ value = value.replace(TEST_SUITE_BUILD_BASE, &config.build_test_suite_root.as_str());
}
if value.contains(SYSROOT_BASE) {
- value = value.replace(SYSROOT_BASE, &config.sysroot_base.to_str().unwrap());
+ value = value.replace(SYSROOT_BASE, &config.sysroot_base.as_str());
}
if value.contains(TARGET_LINKER) {
@@ -1142,9 +1142,9 @@ fn expand_variables(mut value: String, config: &Config) -> String {
if value.contains(RUST_SRC_BASE) {
let src_base = config.sysroot_base.join("lib/rustlib/src/rust");
- src_base.try_exists().expect(&*format!("{} should exists", src_base.display()));
- let src_base = src_base.read_link().unwrap_or(src_base);
- value = value.replace(RUST_SRC_BASE, &src_base.to_string_lossy());
+ src_base.try_exists().expect(&*format!("{} should exists", src_base));
+ let src_base = src_base.read_link_utf8().unwrap_or(src_base);
+ value = value.replace(RUST_SRC_BASE, &src_base.as_str());
}
value
@@ -1247,14 +1247,14 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
// contains a path to that static lib, and that it exists.
//
// See compiler/rustc_llvm/build.rs for more details and similar expectations.
- fn is_zstd_in_config(llvm_bin_dir: &Path) -> Option<()> {
+ fn is_zstd_in_config(llvm_bin_dir: &Utf8Path) -> Option<()> {
let llvm_config_path = llvm_bin_dir.join("llvm-config");
let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?;
assert!(output.status.success(), "running llvm-config --system-libs failed");
let libs = String::from_utf8(output.stdout).ok()?;
for lib in libs.split_whitespace() {
- if lib.ends_with("libzstd.a") && Path::new(lib).exists() {
+ if lib.ends_with("libzstd.a") && Utf8Path::new(lib).exists() {
return Some(());
}
}
@@ -1272,7 +1272,7 @@ fn is_zstd_in_config(llvm_bin_dir: &Path) -> Option<()> {
// `lld` supports it. If not, an error will be emitted: "LLVM was not built with
// LLVM_ENABLE_ZSTD or did not find zstd at build time".
#[cfg(unix)]
- fn is_lld_built_with_zstd(llvm_bin_dir: &Path) -> Option<()> {
+ fn is_lld_built_with_zstd(llvm_bin_dir: &Utf8Path) -> Option<()> {
let lld_path = llvm_bin_dir.join("lld");
if lld_path.exists() {
// We can't call `lld` as-is, it expects to be invoked by a compiler driver using a
@@ -1308,7 +1308,7 @@ fn is_lld_built_with_zstd(llvm_bin_dir: &Path) -> Option<()> {
}
#[cfg(not(unix))]
- fn is_lld_built_with_zstd(_llvm_bin_dir: &Path) -> Option<()> {
+ fn is_lld_built_with_zstd(_llvm_bin_dir: &Utf8Path) -> Option<()> {
None
}
@@ -1375,7 +1375,7 @@ pub(crate) fn make_test_description<R: Read>(
config: &Config,
cache: &HeadersCache,
name: String,
- path: &Path,
+ path: &Utf8Path,
src: R,
test_revision: Option<&str>,
poisoned: &mut bool,
@@ -1406,7 +1406,7 @@ macro_rules! decision {
ignore_message = Some(reason.into());
}
IgnoreDecision::Error { message } => {
- eprintln!("error: {}:{line_number}: {message}", path.display());
+ eprintln!("error: {}:{line_number}: {message}", path);
*poisoned = true;
return;
}
@@ -1436,7 +1436,7 @@ macro_rules! decision {
);
if local_poisoned {
- eprintln!("errors encountered when trying to make test description: {}", path.display());
+ eprintln!("errors encountered when trying to make test description: {}", path);
panic!("errors encountered when trying to make test description");
}
@@ -1545,7 +1545,7 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
IgnoreDecision::Continue
}
-fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision {
+fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(needed_components) =
config.parse_name_value_directive(line, "needs-llvm-components")
{
@@ -1557,8 +1557,7 @@ fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision {
if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() {
panic!(
"missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {}",
- missing_component,
- path.display()
+ missing_component, path
);
}
return IgnoreDecision::Ignore {
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index c369fff..f1f1384 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -101,6 +101,10 @@ macro_rules! condition {
message: "always"
}
condition! {
+ name: "auxiliary",
+ message: "used by another main test file"
+ }
+ condition! {
name: &config.target,
allowed_names: &target_cfgs.all_targets,
message: "when the target is {name}"
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index f3461f3..2525e0a 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -1,6 +1,6 @@
use std::io::Read;
-use std::path::Path;
+use camino::Utf8Path;
use semver::Version;
use super::{
@@ -13,7 +13,7 @@
fn make_test_description<R: Read>(
config: &Config,
name: String,
- path: &Path,
+ path: &Utf8Path,
src: R,
revision: Option<&str>,
) -> CollectedTestDesc {
@@ -230,12 +230,12 @@ fn cfg() -> ConfigBuilder {
fn parse_rs(config: &Config, contents: &str) -> EarlyProps {
let bytes = contents.as_bytes();
- EarlyProps::from_reader(config, Path::new("a.rs"), bytes)
+ EarlyProps::from_reader(config, Utf8Path::new("a.rs"), bytes)
}
fn check_ignore(config: &Config, contents: &str) -> bool {
let tn = String::new();
- let p = Path::new("a.rs");
+ let p = Utf8Path::new("a.rs");
let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None);
d.ignore
}
@@ -244,7 +244,7 @@ fn check_ignore(config: &Config, contents: &str) -> bool {
fn should_fail() {
let config: Config = cfg().build();
let tn = String::new();
- let p = Path::new("a.rs");
+ let p = Utf8Path::new("a.rs");
let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None);
assert_eq!(d.should_panic, ShouldPanic::No);
@@ -784,7 +784,7 @@ fn threads_support() {
}
}
-fn run_path(poisoned: &mut bool, path: &Path, buf: &[u8]) {
+fn run_path(poisoned: &mut bool, path: &Utf8Path, buf: &[u8]) {
let rdr = std::io::Cursor::new(&buf);
iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {});
}
@@ -794,7 +794,7 @@ fn test_unknown_directive_check() {
let mut poisoned = false;
run_path(
&mut poisoned,
- Path::new("a.rs"),
+ Utf8Path::new("a.rs"),
include_bytes!("./test-auxillary/unknown_directive.rs"),
);
assert!(poisoned);
@@ -805,7 +805,7 @@ fn test_known_directive_check_no_error() {
let mut poisoned = false;
run_path(
&mut poisoned,
- Path::new("a.rs"),
+ Utf8Path::new("a.rs"),
include_bytes!("./test-auxillary/known_directive.rs"),
);
assert!(!poisoned);
@@ -816,7 +816,7 @@ fn test_error_annotation_no_error() {
let mut poisoned = false;
run_path(
&mut poisoned,
- Path::new("a.rs"),
+ Utf8Path::new("a.rs"),
include_bytes!("./test-auxillary/error_annotation.rs"),
);
assert!(!poisoned);
@@ -827,7 +827,7 @@ fn test_non_rs_unknown_directive_not_checked() {
let mut poisoned = false;
run_path(
&mut poisoned,
- Path::new("a.Makefile"),
+ Utf8Path::new("a.Makefile"),
include_bytes!("./test-auxillary/not_rs.Makefile"),
);
assert!(!poisoned);
@@ -836,21 +836,21 @@ fn test_non_rs_unknown_directive_not_checked() {
#[test]
fn test_trailing_directive() {
let mut poisoned = false;
- run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm");
+ run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ only-x86 only-arm");
assert!(poisoned);
}
#[test]
fn test_trailing_directive_with_comment() {
let mut poisoned = false;
- run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm with comment");
+ run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ only-x86 only-arm with comment");
assert!(poisoned);
}
#[test]
fn test_not_trailing_directive() {
let mut poisoned = false;
- run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental");
+ run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ revisions: incremental");
assert!(!poisoned);
}
@@ -940,3 +940,9 @@ fn test_supported_crate_types() {
"//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib"
));
}
+
+#[test]
+fn test_ignore_auxiliary() {
+ let config = cfg().build();
+ assert!(check_ignore(&config, "//@ ignore-auxiliary"));
+}
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 720663b..4bbd4ab 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -1,7 +1,8 @@
#![crate_name = "compiletest"]
-// The `test` crate is the only unstable feature
-// allowed here, just to share similar code.
+// Needed by the libtest-based test executor.
#![feature(test)]
+// Needed by the "new" test executor that does not depend on libtest.
+#![feature(internal_output_capture)]
extern crate test;
@@ -22,16 +23,15 @@
use core::panic;
use std::collections::HashSet;
-use std::ffi::OsString;
use std::fmt::Write;
use std::io::{self, ErrorKind};
-use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::{Arc, OnceLock};
use std::time::SystemTime;
use std::{env, fs, vec};
use build_helper::git::{get_git_modified_files, get_git_untracked_files};
+use camino::{Utf8Path, Utf8PathBuf};
use getopts::Options;
use tracing::*;
use walkdir::WalkDir;
@@ -203,6 +203,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
"COMMAND",
)
.reqopt("", "minicore-path", "path to minicore aux library", "PATH")
+ .optflag("n", "new-executor", "enables the new test executor instead of using libtest")
.optopt(
"",
"debugger",
@@ -230,15 +231,19 @@ pub fn parse_config(args: Vec<String>) -> Config {
panic!()
}
- fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
- match m.opt_str(nm) {
- Some(s) => PathBuf::from(&s),
- None => panic!("no option (=path) found for {}", nm),
+ fn make_absolute(path: Utf8PathBuf) -> Utf8PathBuf {
+ if path.is_relative() {
+ Utf8PathBuf::try_from(env::current_dir().unwrap()).unwrap().join(path)
+ } else {
+ path
}
}
- fn make_absolute(path: PathBuf) -> PathBuf {
- if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
+ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
+ match m.opt_str(nm) {
+ Some(s) => Utf8PathBuf::from(&s),
+ None => panic!("no option (=path) found for {}", nm),
+ }
}
let target = opt_str2(matches.opt_str("target"));
@@ -279,12 +284,12 @@ fn make_absolute(path: PathBuf) -> PathBuf {
.free
.iter()
.map(|f| {
- let path = Path::new(f);
+ let path = Utf8Path::new(f);
let mut iter = path.iter().skip(1);
// We skip the test folder and check if the user passed `rmake.rs`.
if iter.next().is_some_and(|s| s == "rmake.rs") && iter.next().is_none() {
- path.parent().unwrap().to_str().unwrap().to_string()
+ path.parent().unwrap().to_string()
} else {
f.to_string()
}
@@ -316,8 +321,8 @@ fn make_absolute(path: PathBuf) -> PathBuf {
assert!(
src_test_suite_root.starts_with(&src_root),
"`src-root` must be a parent of `src-test-suite-root`: `src-root`=`{}`, `src-test-suite-root` = `{}`",
- src_root.display(),
- src_test_suite_root.display()
+ src_root,
+ src_test_suite_root
);
let build_root = opt_path(matches, "build-root");
@@ -332,16 +337,16 @@ fn make_absolute(path: PathBuf) -> PathBuf {
compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
rustc_path: opt_path(matches, "rustc-path"),
- cargo_path: matches.opt_str("cargo-path").map(PathBuf::from),
- stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(PathBuf::from),
- rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
- coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from),
+ cargo_path: matches.opt_str("cargo-path").map(Utf8PathBuf::from),
+ stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(Utf8PathBuf::from),
+ rustdoc_path: matches.opt_str("rustdoc-path").map(Utf8PathBuf::from),
+ coverage_dump_path: matches.opt_str("coverage-dump-path").map(Utf8PathBuf::from),
python: matches.opt_str("python").unwrap(),
jsondocck_path: matches.opt_str("jsondocck-path"),
jsondoclint_path: matches.opt_str("jsondoclint-path"),
run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
- llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
- llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
+ llvm_filecheck: matches.opt_str("llvm-filecheck").map(Utf8PathBuf::from),
+ llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(Utf8PathBuf::from),
src_root,
src_test_suite_root,
@@ -407,7 +412,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
},
only_modified: matches.opt_present("only-modified"),
color,
- remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
+ remote_test_client: matches.opt_str("remote-test-client").map(Utf8PathBuf::from),
compare_mode,
rustfix_coverage: matches.opt_present("rustfix-coverage"),
has_html_tidy,
@@ -444,25 +449,27 @@ fn make_absolute(path: PathBuf) -> PathBuf {
diff_command: matches.opt_str("compiletest-diff-tool"),
minicore_path: opt_path(matches, "minicore-path"),
+
+ new_executor: matches.opt_present("new-executor"),
}
}
pub fn log_config(config: &Config) {
let c = config;
logv(c, "configuration:".to_string());
- logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
- logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
- logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
+ logv(c, format!("compile_lib_path: {}", config.compile_lib_path));
+ logv(c, format!("run_lib_path: {}", config.run_lib_path));
+ logv(c, format!("rustc_path: {}", config.rustc_path));
logv(c, format!("cargo_path: {:?}", config.cargo_path));
logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
- logv(c, format!("src_root: {}", config.src_root.display()));
- logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root.display()));
+ logv(c, format!("src_root: {}", config.src_root));
+ logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root));
- logv(c, format!("build_root: {}", config.build_root.display()));
- logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root.display()));
+ logv(c, format!("build_root: {}", config.build_root));
+ logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root));
- logv(c, format!("sysroot_base: {}", config.sysroot_base.display()));
+ logv(c, format!("sysroot_base: {}", config.sysroot_base));
logv(c, format!("stage: {}", config.stage));
logv(c, format!("stage_id: {}", config.stage_id));
@@ -480,16 +487,16 @@ pub fn log_config(config: &Config) {
logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
logv(c, format!("target: {}", config.target));
logv(c, format!("host: {}", config.host));
- logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
- logv(c, format!("adb_path: {:?}", config.adb_path));
- logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
+ logv(c, format!("android-cross-path: {}", config.android_cross_path));
+ logv(c, format!("adb_path: {}", config.adb_path));
+ logv(c, format!("adb_test_dir: {}", config.adb_test_dir));
logv(c, format!("adb_device_status: {}", config.adb_device_status));
logv(c, format!("ar: {}", config.ar));
logv(c, format!("target-linker: {:?}", config.target_linker));
logv(c, format!("host-linker: {:?}", config.host_linker));
logv(c, format!("verbose: {}", config.verbose));
logv(c, format!("format: {:?}", config.format));
- logv(c, format!("minicore_path: {:?}", config.minicore_path.display()));
+ logv(c, format!("minicore_path: {}", config.minicore_path));
logv(c, "\n".to_string());
}
@@ -517,7 +524,7 @@ pub fn run_tests(config: Arc<Config>) {
coverage_file_path.push("rustfix_missing_coverage.txt");
if coverage_file_path.exists() {
if let Err(e) = fs::remove_file(&coverage_file_path) {
- panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
+ panic!("Could not delete {} due to {}", coverage_file_path, e)
}
}
}
@@ -567,10 +574,14 @@ pub fn run_tests(config: Arc<Config>) {
tests.sort_by(|a, b| Ord::cmp(&a.desc.name, &b.desc.name));
- // Delegate to libtest to filter and run the big list of structures created
- // during test discovery. When libtest decides to run a test, it will
- // return control to compiletest by invoking a closure.
- let res = crate::executor::execute_tests(&config, tests);
+ // Delegate to the executor to filter and run the big list of test structures
+ // created during test discovery. When the executor decides to run a test,
+ // it will return control to the rest of compiletest by calling `runtest::run`.
+ let res = if config.new_executor {
+ Ok(executor::run_tests(&config, tests))
+ } else {
+ crate::executor::libtest::execute_tests(&config, tests)
+ };
// Check the outcome reported by libtest.
match res {
@@ -619,13 +630,13 @@ struct TestCollectorCx {
config: Arc<Config>,
cache: HeadersCache,
common_inputs_stamp: Stamp,
- modified_tests: Vec<PathBuf>,
+ modified_tests: Vec<Utf8PathBuf>,
}
/// Mutable state used during test collection.
struct TestCollector {
tests: Vec<CollectedTest>,
- found_path_stems: HashSet<PathBuf>,
+ found_path_stems: HashSet<Utf8PathBuf>,
poisoned: bool,
}
@@ -635,14 +646,13 @@ struct TestCollector {
/// regardless of whether any filters/tests were specified on the command-line,
/// because filtering is handled later by libtest.
pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest> {
- debug!("making tests from {}", config.src_test_suite_root.display());
+ debug!("making tests from {}", config.src_test_suite_root);
let common_inputs_stamp = common_inputs_stamp(&config);
let modified_tests =
modified_tests(&config, &config.src_test_suite_root).unwrap_or_else(|err| {
panic!(
"modified_tests got error from dir: {}, error: {}",
- config.src_test_suite_root.display(),
- err
+ config.src_test_suite_root, err
)
});
let cache = HeadersCache::load(&config);
@@ -651,12 +661,9 @@ pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest>
let mut collector =
TestCollector { tests: vec![], found_path_stems: HashSet::new(), poisoned: false };
- collect_tests_from_dir(&cx, &mut collector, &cx.config.src_test_suite_root, Path::new(""))
+ collect_tests_from_dir(&cx, &mut collector, &cx.config.src_test_suite_root, Utf8Path::new(""))
.unwrap_or_else(|reason| {
- panic!(
- "Could not read tests from {}: {reason}",
- cx.config.src_test_suite_root.display()
- )
+ panic!("Could not read tests from {}: {reason}", cx.config.src_test_suite_root)
});
let TestCollector { tests, found_path_stems, poisoned } = collector;
@@ -725,24 +732,29 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
/// the `--only-modified` flag is in use.
///
/// (Might be inaccurate in some cases.)
-fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
+fn modified_tests(config: &Config, dir: &Utf8Path) -> Result<Vec<Utf8PathBuf>, String> {
// If `--only-modified` wasn't passed, the list of modified tests won't be
// used for anything, so avoid some work and just return an empty list.
if !config.only_modified {
return Ok(vec![]);
}
- let files =
- get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?;
+ let files = get_git_modified_files(
+ &config.git_config(),
+ Some(dir.as_std_path()),
+ &vec!["rs", "stderr", "fixed"],
+ )?;
// Add new test cases to the list, it will be convenient in daily development.
let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]);
let all_paths = [&files[..], &untracked_files[..]].concat();
let full_paths = {
- let mut full_paths: Vec<PathBuf> = all_paths
+ let mut full_paths: Vec<Utf8PathBuf> = all_paths
.into_iter()
- .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
- .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
+ .map(|f| Utf8PathBuf::from(f).with_extension("").with_extension("rs"))
+ .filter_map(
+ |f| if Utf8Path::new(&f).exists() { f.canonicalize_utf8().ok() } else { None },
+ )
.collect();
full_paths.dedup();
full_paths.sort_unstable();
@@ -756,8 +768,8 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
fn collect_tests_from_dir(
cx: &TestCollectorCx,
collector: &mut TestCollector,
- dir: &Path,
- relative_dir_path: &Path,
+ dir: &Utf8Path,
+ relative_dir_path: &Utf8Path,
) -> io::Result<()> {
// Ignore directories that contain a file named `compiletest-ignore-dir`.
if dir.join("compiletest-ignore-dir").exists() {
@@ -790,16 +802,16 @@ fn collect_tests_from_dir(
// subdirectories we find, except for `auxiliary` directories.
// FIXME: this walks full tests tree, even if we have something to ignore
// use walkdir/ignore like in tidy?
- for file in fs::read_dir(dir)? {
+ for file in fs::read_dir(dir.as_std_path())? {
let file = file?;
- let file_path = file.path();
- let file_name = file.file_name();
+ let file_path = Utf8PathBuf::try_from(file.path()).unwrap();
+ let file_name = file_path.file_name().unwrap();
- if is_test(&file_name)
+ if is_test(file_name)
&& (!cx.config.only_modified || cx.modified_tests.contains(&file_path))
{
// We found a test file, so create the corresponding libtest structures.
- debug!("found test file: {:?}", file_path.display());
+ debug!(%file_path, "found test file");
// Record the stem of the test file, to check for overlaps later.
let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
@@ -810,22 +822,20 @@ fn collect_tests_from_dir(
make_test(cx, collector, &paths);
} else if file_path.is_dir() {
// Recurse to find more tests in a subdirectory.
- let relative_file_path = relative_dir_path.join(file.file_name());
- if &file_name != "auxiliary" {
- debug!("found directory: {:?}", file_path.display());
+ let relative_file_path = relative_dir_path.join(file_name);
+ if file_name != "auxiliary" {
+ debug!(%file_path, "found directory");
collect_tests_from_dir(cx, collector, &file_path, &relative_file_path)?;
}
} else {
- debug!("found other file/directory: {:?}", file_path.display());
+ debug!(%file_path, "found other file/directory");
}
}
Ok(())
}
/// Returns true if `file_name` looks like a proper test file name.
-pub fn is_test(file_name: &OsString) -> bool {
- let file_name = file_name.to_str().unwrap();
-
+pub fn is_test(file_name: &str) -> bool {
if !file_name.ends_with(".rs") {
return false;
}
@@ -844,7 +854,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
let test_path = if cx.config.mode == Mode::RunMake {
testpaths.file.join("rmake.rs")
} else {
- PathBuf::from(&testpaths.file)
+ testpaths.file.clone()
};
// Scan the test file to discover its revisions, if any.
@@ -899,7 +909,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
/// The path of the `stamp` file that gets created or updated whenever a
/// particular test completes successfully.
-fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> Utf8PathBuf {
output_base_dir(config, testpaths, revision).join("stamp")
}
@@ -912,7 +922,7 @@ fn files_related_to_test(
testpaths: &TestPaths,
props: &EarlyProps,
revision: Option<&str>,
-) -> Vec<PathBuf> {
+) -> Vec<Utf8PathBuf> {
let mut related = vec![];
if testpaths.file.is_dir() {
@@ -920,7 +930,7 @@ fn files_related_to_test(
for entry in WalkDir::new(&testpaths.file) {
let path = entry.unwrap().into_path();
if path.is_file() {
- related.push(path);
+ related.push(Utf8PathBuf::try_from(path).unwrap());
}
}
} else {
@@ -991,7 +1001,7 @@ struct Stamp {
impl Stamp {
/// Creates a timestamp holding the last-modified time of the specified file.
- fn from_path(path: &Path) -> Self {
+ fn from_path(path: &Utf8Path) -> Self {
let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH };
stamp.add_path(path);
stamp
@@ -999,8 +1009,8 @@ fn from_path(path: &Path) -> Self {
/// Updates this timestamp to the last-modified time of the specified file,
/// if it is later than the currently-stored timestamp.
- fn add_path(&mut self, path: &Path) {
- let modified = fs::metadata(path)
+ fn add_path(&mut self, path: &Utf8Path) {
+ let modified = fs::metadata(path.as_std_path())
.and_then(|metadata| metadata.modified())
.unwrap_or(SystemTime::UNIX_EPOCH);
self.time = self.time.max(modified);
@@ -1009,7 +1019,8 @@ fn add_path(&mut self, path: &Path) {
/// Updates this timestamp to the most recent last-modified time of all files
/// recursively contained in the given directory, if it is later than the
/// currently-stored timestamp.
- fn add_dir(&mut self, path: &Path) {
+ fn add_dir(&mut self, path: &Utf8Path) {
+ let path = path.as_std_path();
for entry in WalkDir::new(path) {
let entry = entry.unwrap();
if entry.file_type().is_file() {
@@ -1042,7 +1053,7 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>
config.mode,
debugger,
mode_suffix,
- path.display(),
+ path,
revision.map_or("".to_string(), |rev| format!("#{}", rev))
)
}
@@ -1064,7 +1075,7 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>
/// To avoid problems, we forbid test names from overlapping in this way.
///
/// See <https://github.com/rust-lang/rust/pull/109509> for more context.
-fn check_for_overlapping_test_paths(found_path_stems: &HashSet<PathBuf>) {
+fn check_for_overlapping_test_paths(found_path_stems: &HashSet<Utf8PathBuf>) {
let mut collisions = Vec::new();
for path in found_path_stems {
for ancestor in path.ancestors().skip(1) {
@@ -1077,7 +1088,7 @@ fn check_for_overlapping_test_paths(found_path_stems: &HashSet<PathBuf>) {
collisions.sort();
let collisions: String = collisions
.into_iter()
- .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
+ .map(|(path, check_parent)| format!("test {path} clashes with {check_parent}\n"))
.collect();
panic!(
"{collisions}\n\
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 9c03fa1..d11f5c1 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,15 +1,16 @@
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
-use std::ffi::{OsStr, OsString};
+use std::ffi::OsString;
use std::fs::{self, File, create_dir_all};
use std::hash::{DefaultHasher, Hash, Hasher};
use std::io::prelude::*;
use std::io::{self, BufReader};
-use std::path::{Path, PathBuf};
use std::process::{Child, Command, ExitStatus, Output, Stdio};
use std::sync::Arc;
use std::{env, iter, str};
+use build_helper::fs::remove_and_create_dir_all;
+use camino::{Utf8Path, Utf8PathBuf};
use colored::Colorize;
use regex::{Captures, Regex};
use tracing::*;
@@ -22,10 +23,10 @@
output_base_dir, output_base_name, output_testname_unique,
};
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
-use crate::errors::{self, Error, ErrorKind};
+use crate::errors::{Error, ErrorKind};
use crate::header::TestProps;
use crate::read2::{Truncated, read2_abbreviated};
-use crate::util::{PathBufExt, add_dylib_path, logv, static_regex};
+use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex};
use crate::{ColorConfig, json, stamp_file_path};
mod debugger;
@@ -131,7 +132,7 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
// We're going to be dumping a lot of info. Start on a new line.
print!("\n\n");
}
- debug!("running {:?}", testpaths.file.display());
+ debug!("running {}", testpaths.file);
let mut props = TestProps::from_file(&testpaths.file, revision, &config);
// For non-incremental (i.e. regular UI) tests, the incremental directory
@@ -144,7 +145,7 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
let cx = TestCx { config: &config, props: &props, testpaths, revision };
if let Err(e) = create_dir_all(&cx.output_base_dir()) {
- panic!("failed to create output base directory {}: {e}", cx.output_base_dir().display());
+ panic!("failed to create output base directory {}: {e}", cx.output_base_dir());
}
if props.incremental {
@@ -177,6 +178,7 @@ pub fn compute_stamp_hash(config: &Config) -> String {
let mut hash = DefaultHasher::new();
config.stage_id.hash(&mut hash);
config.run.hash(&mut hash);
+ config.edition.hash(&mut hash);
match config.debugger {
Some(Debugger::Cdb) => {
@@ -206,11 +208,6 @@ pub fn compute_stamp_hash(config: &Config) -> String {
format!("{:x}", hash.finish())
}
-fn remove_and_create_dir_all(path: &Path) {
- let _ = fs::remove_dir_all(path);
- fs::create_dir_all(path).unwrap();
-}
-
#[derive(Copy, Clone, Debug)]
struct TestCx<'test> {
config: &'test Config,
@@ -422,7 +419,7 @@ fn print_source(&self, read_from: ReadFrom, pretty_type: &str) -> ProcRes {
let aux_dir = self.aux_output_dir_name();
let input: &str = match read_from {
ReadFrom::Stdin(_) => "-",
- ReadFrom::Path => self.testpaths.file.to_str().unwrap(),
+ ReadFrom::Path => self.testpaths.file.as_str(),
};
let mut rustc = Command::new(&self.config.rustc_path);
@@ -521,7 +518,9 @@ fn typecheck_source(&self, src: String) -> ProcRes {
let mut rustc = Command::new(&self.config.rustc_path);
let out_dir = self.output_base_name().with_extension("pretty-out");
- remove_and_create_dir_all(&out_dir);
+ remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
+ });
let target = if self.props.force_host { &*self.config.host } else { &*self.config.target };
@@ -589,10 +588,7 @@ fn check_all_error_patterns(
// FIXME(#65865)
return;
} else {
- self.fatal(&format!(
- "no error pattern specified in {:?}",
- self.testpaths.file.display()
- ));
+ self.fatal(&format!("no error pattern specified in {}", self.testpaths.file));
}
}
@@ -674,7 +670,7 @@ fn check_forbid_output(&self, output_to_check: &str, proc_res: &ProcRes) {
}
}
- fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &ProcRes) {
+ fn check_expected_errors(&self, expected_errors: Vec<Error>, proc_res: &ProcRes) {
debug!(
"check_expected_errors: expected_errors={:?} proc_res.status={:?}",
expected_errors, proc_res.status
@@ -696,21 +692,25 @@ fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &
}
// On Windows, translate all '\' path separators to '/'
- let file_name = format!("{}", self.testpaths.file.display()).replace(r"\", "/");
+ let file_name = self.testpaths.file.to_string().replace(r"\", "/");
// On Windows, keep all '\' path separators to match the paths reported in the JSON output
// from the compiler
let diagnostic_file_name = if self.props.remap_src_base {
- let mut p = PathBuf::from(FAKE_SRC_BASE);
+ let mut p = Utf8PathBuf::from(FAKE_SRC_BASE);
p.push(&self.testpaths.relative_dir);
p.push(self.testpaths.file.file_name().unwrap());
- p.display().to_string()
+ p.to_string()
} else {
- self.testpaths.file.display().to_string()
+ self.testpaths.file.to_string()
};
- let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
- let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));
+ // Errors and warnings are always expected, other diagnostics are only expected
+ // if one of them actually occurs in the test.
+ let expected_kinds: HashSet<_> = [ErrorKind::Error, ErrorKind::Warning]
+ .into_iter()
+ .chain(expected_errors.iter().filter_map(|e| e.kind))
+ .collect();
// Parse the JSON output from the compiler and extract out the messages.
let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res);
@@ -736,8 +736,11 @@ fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &
}
None => {
- // If the test is a known bug, don't require that the error is annotated
- if self.is_unexpected_compiler_message(&actual_error, expect_help, expect_note)
+ if actual_error.require_annotation
+ && actual_error.kind.map_or(false, |kind| {
+ expected_kinds.contains(&kind)
+ && !self.props.dont_require_annotations.contains(&kind)
+ })
{
self.error(&format!(
"{}:{}: unexpected {}: '{}'",
@@ -795,27 +798,6 @@ fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &
}
}
- /// Returns `true` if we should report an error about `actual_error`,
- /// which did not match any of the expected error.
- fn is_unexpected_compiler_message(
- &self,
- actual_error: &Error,
- expect_help: bool,
- expect_note: bool,
- ) -> bool {
- actual_error.require_annotation
- && actual_error.kind.map_or(false, |err_kind| {
- // If the test being checked doesn't contain any "help" or "note" annotations, then
- // we don't require annotating "help" or "note" (respecively) diagnostics at all.
- let default_require_annotations = self.props.require_annotations[&err_kind];
- match err_kind {
- ErrorKind::Help => expect_help && default_require_annotations,
- ErrorKind::Note => expect_note && default_require_annotations,
- _ => default_require_annotations,
- }
- })
- }
-
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
match (pm, self.props.fail_mode, self.config.mode) {
(Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => Emit::Metadata,
@@ -886,7 +868,7 @@ fn compile_test_general(
/// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run.
/// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths.
- fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes {
+ fn document(&self, root_out_dir: &Utf8Path, root_testpaths: &TestPaths) -> ProcRes {
if self.props.build_aux_docs {
for rel_ab in &self.props.aux.builds {
let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab);
@@ -915,13 +897,13 @@ fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes {
// actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire
// test
- let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir {
+ let out_dir: Cow<'_, Utf8Path> = if self.props.unique_doc_out_dir {
let file_name = self.testpaths.file.file_stem().expect("file name should not be empty");
- let out_dir = PathBuf::from_iter([
+ let out_dir = Utf8PathBuf::from_iter([
root_out_dir,
- Path::new("docs"),
- Path::new(file_name),
- Path::new("doc"),
+ Utf8Path::new("docs"),
+ Utf8Path::new(file_name),
+ Utf8Path::new("doc"),
]);
create_dir_all(&out_dir).unwrap();
Cow::Owned(out_dir)
@@ -934,7 +916,7 @@ fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes {
rustdoc.current_dir(current_dir);
rustdoc
.arg("-L")
- .arg(self.config.run_lib_path.to_str().unwrap())
+ .arg(self.config.run_lib_path.as_path())
.arg("-L")
.arg(aux_dir)
.arg("-o")
@@ -1072,7 +1054,7 @@ fn compute_aux_test_paths(&self, of: &TestPaths, rel_ab: &str) -> TestPaths {
let test_ab =
of.file.parent().expect("test file path has no parent").join("auxiliary").join(rel_ab);
if !test_ab.exists() {
- self.fatal(&format!("aux-build `{}` source not found", test_ab.display()))
+ self.fatal(&format!("aux-build `{}` source not found", test_ab))
}
TestPaths {
@@ -1109,23 +1091,29 @@ fn has_aux_dir(&self) -> bool {
|| !self.props.aux.proc_macros.is_empty()
}
- fn aux_output_dir(&self) -> PathBuf {
+ fn aux_output_dir(&self) -> Utf8PathBuf {
let aux_dir = self.aux_output_dir_name();
if !self.props.aux.builds.is_empty() {
- remove_and_create_dir_all(&aux_dir);
+ remove_and_create_dir_all(&aux_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{aux_dir}`: {e}")
+ });
}
if !self.props.aux.bins.is_empty() {
let aux_bin_dir = self.aux_bin_output_dir_name();
- remove_and_create_dir_all(&aux_dir);
- remove_and_create_dir_all(&aux_bin_dir);
+ remove_and_create_dir_all(&aux_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{aux_dir}`: {e}")
+ });
+ remove_and_create_dir_all(&aux_bin_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{aux_bin_dir}`: {e}")
+ });
}
aux_dir
}
- fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
+ fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Utf8Path, rustc: &mut Command) {
for rel_ab in &self.props.aux.builds {
self.build_auxiliary(of, rel_ab, &aux_dir, None);
}
@@ -1145,12 +1133,7 @@ fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Comman
|rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| {
let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type);
if let Some(lib_name) = lib_name {
- rustc.arg("--extern").arg(format!(
- "{}={}/{}",
- aux_name,
- aux_dir.display(),
- lib_name
- ));
+ rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir, lib_name));
}
};
@@ -1171,7 +1154,7 @@ fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Comman
let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None);
if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) {
let lib_path = aux_dir.join(&lib_name);
- rustc.arg(format!("-Zcodegen-backend={}", lib_path.display()));
+ rustc.arg(format!("-Zcodegen-backend={}", lib_path));
}
}
}
@@ -1187,7 +1170,7 @@ fn compose_and_run_compiler(
if self.props.add_core_stubs {
let minicore_path = self.build_minicore();
rustc.arg("--extern");
- rustc.arg(&format!("minicore={}", minicore_path.to_str().unwrap()));
+ rustc.arg(&format!("minicore={}", minicore_path));
}
let aux_dir = self.aux_output_dir();
@@ -1205,7 +1188,7 @@ fn compose_and_run_compiler(
/// Builds `minicore`. Returns the path to the minicore rlib within the base test output
/// directory.
- fn build_minicore(&self) -> PathBuf {
+ fn build_minicore(&self) -> Utf8PathBuf {
let output_file_path = self.output_base_dir().join("libminicore.rlib");
let mut rustc = self.make_compile_args(
&self.config.minicore_path,
@@ -1222,10 +1205,7 @@ fn build_minicore(&self) -> PathBuf {
let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None);
if !res.status.success() {
self.fatal_proc_rec(
- &format!(
- "auxiliary build of {:?} failed to compile: ",
- self.config.minicore_path.display()
- ),
+ &format!("auxiliary build of {} failed to compile: ", self.config.minicore_path),
&res,
);
}
@@ -1240,7 +1220,7 @@ fn build_auxiliary(
&self,
of: &TestPaths,
source_path: &str,
- aux_dir: &Path,
+ aux_dir: &Utf8Path,
aux_type: Option<AuxType>,
) -> AuxType {
let aux_testpaths = self.compute_aux_test_paths(of, source_path);
@@ -1337,10 +1317,7 @@ fn build_auxiliary(
);
if !auxres.status.success() {
self.fatal_proc_rec(
- &format!(
- "auxiliary build of {:?} failed to compile: ",
- aux_testpaths.file.display()
- ),
+ &format!("auxiliary build of {} failed to compile: ", aux_testpaths.file),
&auxres,
);
}
@@ -1349,8 +1326,8 @@ fn build_auxiliary(
fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) {
let mut filter_paths_from_len = Vec::new();
- let mut add_path = |path: &Path| {
- let path = path.display().to_string();
+ let mut add_path = |path: &Utf8Path| {
+ let path = path.to_string();
let windows = path.replace("\\", "\\\\");
if windows != path {
filter_paths_from_len.push(windows);
@@ -1372,8 +1349,8 @@ fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) {
fn compose_and_run(
&self,
mut command: Command,
- lib_path: &Path,
- aux_path: Option<&Path>,
+ lib_path: &Utf8Path,
+ aux_path: Option<&Utf8Path>,
input: Option<String>,
) -> ProcRes {
let cmdline = {
@@ -1418,9 +1395,9 @@ fn is_rustdoc(&self) -> bool {
matches!(self.config.suite.as_str(), "rustdoc-ui" | "rustdoc-js" | "rustdoc-json")
}
- fn get_mir_dump_dir(&self) -> PathBuf {
+ fn get_mir_dump_dir(&self) -> Utf8PathBuf {
let mut mir_dump_dir = self.config.build_test_suite_root.clone();
- debug!("input_file: {:?}", self.testpaths.file);
+ debug!("input_file: {}", self.testpaths.file);
mir_dump_dir.push(&self.testpaths.relative_dir);
mir_dump_dir.push(self.testpaths.file.file_stem().unwrap());
mir_dump_dir
@@ -1428,7 +1405,7 @@ fn get_mir_dump_dir(&self) -> PathBuf {
fn make_compile_args(
&self,
- input_file: &Path,
+ input_file: &Utf8Path,
output_file: TargetLocation,
emit: Emit,
allow_unused: AllowUnused,
@@ -1469,7 +1446,7 @@ fn make_compile_args(
// Similarly, vendored sources shouldn't be shown when running from a dist tarball.
rustc.arg("-Z").arg(format!(
"ignore-directory-in-diagnostics-source-blocks={}",
- self.config.src_root.join("vendor").to_str().unwrap(),
+ self.config.src_root.join("vendor"),
));
// Optionally prevent default --sysroot if specified in test compile-flags.
@@ -1493,7 +1470,7 @@ fn make_compile_args(
if !is_rustdoc {
if let Some(ref incremental_dir) = self.props.incremental_dir {
- rustc.args(&["-C", &format!("incremental={}", incremental_dir.display())]);
+ rustc.args(&["-C", &format!("incremental={}", incremental_dir)]);
rustc.args(&["-Z", "incremental-verify-ich"]);
}
@@ -1535,9 +1512,11 @@ fn make_compile_args(
let set_mir_dump_dir = |rustc: &mut Command| {
let mir_dump_dir = self.get_mir_dump_dir();
- remove_and_create_dir_all(&mir_dump_dir);
+ remove_and_create_dir_all(&mir_dump_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{mir_dump_dir}`: {e}")
+ });
let mut dir_opt = "-Zdump-mir-dir=".to_string();
- dir_opt.push_str(mir_dump_dir.to_str().unwrap());
+ dir_opt.push_str(mir_dump_dir.as_str());
debug!("dir_opt: {:?}", dir_opt);
rustc.arg(dir_opt);
};
@@ -1630,8 +1609,7 @@ fn make_compile_args(
if self.props.remap_src_base {
rustc.arg(format!(
"--remap-path-prefix={}={}",
- self.config.src_test_suite_root.to_str().unwrap(),
- FAKE_SRC_BASE,
+ self.config.src_test_suite_root, FAKE_SRC_BASE,
));
}
@@ -1754,7 +1732,7 @@ fn make_compile_args(
rustc
}
- fn make_exe_name(&self) -> PathBuf {
+ fn make_exe_name(&self) -> Utf8PathBuf {
// Using a single letter here to keep the path length down for
// Windows. Some test names get very long. rustc creates `rcgu`
// files with the module name appended to it which can more than
@@ -1805,7 +1783,7 @@ fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<OsString> {
}
}
- fn make_cmdline(&self, command: &Command, libpath: &Path) -> String {
+ fn make_cmdline(&self, command: &Command, libpath: &Utf8Path) -> String {
use crate::util;
// Linux and mac don't require adjusting the library search path
@@ -1818,7 +1796,7 @@ fn lib_path_cmd_prefix(path: &str) -> String {
format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
}
- format!("{} {:?}", lib_path_cmd_prefix(libpath.to_str().unwrap()), command)
+ format!("{} {:?}", lib_path_cmd_prefix(libpath.as_str()), command)
}
}
@@ -1832,20 +1810,19 @@ fn dump_output(&self, print_output: bool, proc_name: &str, out: &str, err: &str)
return;
}
- let path = Path::new(proc_name);
+ let path = Utf8Path::new(proc_name);
let proc_name = if path.file_stem().is_some_and(|p| p == "rmake") {
- OsString::from_iter(
+ String::from_iter(
path.parent()
.unwrap()
.file_name()
.into_iter()
- .chain(Some(OsStr::new("/")))
+ .chain(Some("/"))
.chain(path.file_name()),
)
} else {
path.file_name().unwrap().into()
};
- let proc_name = proc_name.to_string_lossy();
println!("------{proc_name} stdout------------------------------");
println!("{}", out);
println!("------{proc_name} stderr------------------------------");
@@ -1855,18 +1832,18 @@ fn dump_output(&self, print_output: bool, proc_name: &str, out: &str, err: &str)
fn dump_output_file(&self, out: &str, extension: &str) {
let outfile = self.make_out_name(extension);
- fs::write(&outfile, out).unwrap();
+ fs::write(outfile.as_std_path(), out).unwrap();
}
/// Creates a filename for output with the given extension.
/// E.g., `/.../testname.revision.mode/testname.extension`.
- fn make_out_name(&self, extension: &str) -> PathBuf {
+ fn make_out_name(&self, extension: &str) -> Utf8PathBuf {
self.output_base_name().with_extension(extension)
}
/// Gets the directory where auxiliary files are written.
/// E.g., `/.../testname.revision.mode/auxiliary/`.
- fn aux_output_dir_name(&self) -> PathBuf {
+ fn aux_output_dir_name(&self) -> Utf8PathBuf {
self.output_base_dir()
.join("auxiliary")
.with_extra_extension(self.config.mode.aux_dir_disambiguator())
@@ -1874,12 +1851,12 @@ fn aux_output_dir_name(&self) -> PathBuf {
/// Gets the directory where auxiliary binaries are written.
/// E.g., `/.../testname.revision.mode/auxiliary/bin`.
- fn aux_bin_output_dir_name(&self) -> PathBuf {
+ fn aux_bin_output_dir_name(&self) -> Utf8PathBuf {
self.aux_output_dir_name().join("bin")
}
/// Generates a unique name for the test, such as `testname.revision.mode`.
- fn output_testname_unique(&self) -> PathBuf {
+ fn output_testname_unique(&self) -> Utf8PathBuf {
output_testname_unique(self.config, self.testpaths, self.safe_revision())
}
@@ -1892,14 +1869,14 @@ fn safe_revision(&self) -> Option<&str> {
/// Gets the absolute path to the directory where all output for the given
/// test/revision should reside.
/// E.g., `/path/to/build/host-tuple/test/ui/relative/testname.revision.mode/`.
- fn output_base_dir(&self) -> PathBuf {
+ fn output_base_dir(&self) -> Utf8PathBuf {
output_base_dir(self.config, self.testpaths, self.safe_revision())
}
/// Gets the absolute path to the base filename used as output for the given
/// test/revision.
/// E.g., `/.../relative/testname.revision.mode/testname`.
- fn output_base_name(&self) -> PathBuf {
+ fn output_base_name(&self) -> Utf8PathBuf {
output_base_name(self.config, self.testpaths, self.safe_revision())
}
@@ -1934,7 +1911,7 @@ fn fatal_proc_rec_with_ctx(
// codegen tests (using FileCheck)
- fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) {
+ fn compile_test_and_save_ir(&self) -> (ProcRes, Utf8PathBuf) {
let output_path = self.output_base_name().with_extension("ll");
let input_file = &self.testpaths.file;
let rustc = self.make_compile_args(
@@ -1950,7 +1927,7 @@ fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) {
(proc_res, output_path)
}
- fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
+ fn verify_with_filecheck(&self, output: &Utf8Path) -> ProcRes {
let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
filecheck.arg("--input-file").arg(output).arg(&self.testpaths.file);
@@ -1980,7 +1957,7 @@ fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
filecheck.args(&self.props.filecheck_flags);
// FIXME(jieyouxu): don't pass an empty Path
- self.compose_and_run(filecheck, Path::new(""), None, None)
+ self.compose_and_run(filecheck, Utf8Path::new(""), None, None)
}
fn charset() -> &'static str {
@@ -1988,7 +1965,7 @@ fn charset() -> &'static str {
if cfg!(target_os = "freebsd") { "ISO-8859-1" } else { "UTF-8" }
}
- fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
+ fn compare_to_default_rustdoc(&mut self, out_dir: &Utf8Path) {
if !self.config.has_html_tidy {
return;
}
@@ -1997,7 +1974,9 @@ fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
let suffix =
self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly");
let compare_dir = output_base_dir(self.config, self.testpaths, Some(&suffix));
- remove_and_create_dir_all(&compare_dir);
+ remove_and_create_dir_all(&compare_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{compare_dir}`: {e}")
+ });
// We need to create a new struct for the lifetimes on `config` to work.
let new_rustdoc = TestCx {
@@ -2140,12 +2119,8 @@ fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
};
}
- fn get_lines<P: AsRef<Path>>(
- &self,
- path: &P,
- mut other_files: Option<&mut Vec<String>>,
- ) -> Vec<usize> {
- let content = fs::read_to_string(&path).unwrap();
+ fn get_lines(&self, path: &Utf8Path, mut other_files: Option<&mut Vec<String>>) -> Vec<usize> {
+ let content = fs::read_to_string(path.as_std_path()).unwrap();
let mut ignore = false;
content
.lines()
@@ -2191,8 +2166,8 @@ fn check_rustdoc_test_option(&self, res: ProcRes) {
for other_file in other_files {
let mut path = self.testpaths.file.clone();
path.set_file_name(&format!("{}.rs", other_file));
- let path = fs::canonicalize(path).expect("failed to canonicalize");
- let normalized = path.to_str().unwrap().replace('\\', "/");
+ let path = path.canonicalize_utf8().expect("failed to canonicalize");
+ let normalized = path.as_str().replace('\\', "/");
files.insert(normalized, self.get_lines(&path, None));
}
@@ -2376,26 +2351,24 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
let mut normalized = output.to_string();
- let mut normalize_path = |from: &Path, to: &str| {
- let mut from = from.display().to_string();
- if json {
- from = from.replace("\\", "\\\\");
- }
- normalized = normalized.replace(&from, to);
+ let mut normalize_path = |from: &Utf8Path, to: &str| {
+ let from = if json { &from.as_str().replace("\\", "\\\\") } else { from.as_str() };
+
+ normalized = normalized.replace(from, to);
};
let parent_dir = self.testpaths.file.parent().unwrap();
normalize_path(parent_dir, "$DIR");
if self.props.remap_src_base {
- let mut remapped_parent_dir = PathBuf::from(FAKE_SRC_BASE);
- if self.testpaths.relative_dir != Path::new("") {
+ let mut remapped_parent_dir = Utf8PathBuf::from(FAKE_SRC_BASE);
+ if self.testpaths.relative_dir != Utf8Path::new("") {
remapped_parent_dir.push(&self.testpaths.relative_dir);
}
normalize_path(&remapped_parent_dir, "$DIR");
}
- let base_dir = Path::new("/rustc/FAKE_PREFIX");
+ let base_dir = Utf8Path::new("/rustc/FAKE_PREFIX");
// Fake paths into the libstd/libcore
normalize_path(&base_dir.join("library"), "$SRC_DIR");
// `ui-fulldeps` tests can show paths to the compiler source when testing macros from
@@ -2405,19 +2378,26 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
// Real paths into the libstd/libcore
let rust_src_dir = &self.config.sysroot_base.join("lib/rustlib/src/rust");
- rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir.display()));
- let rust_src_dir = rust_src_dir.read_link().unwrap_or(rust_src_dir.to_path_buf());
+ rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir));
+ let rust_src_dir = rust_src_dir.read_link_utf8().unwrap_or(rust_src_dir.to_path_buf());
normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL");
// eg.
// /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui/<test_dir>/$name.$revision.$mode/
normalize_path(&self.output_base_dir(), "$TEST_BUILD_DIR");
+ // Same as above, but with a canonicalized path.
+ // This is required because some tests print canonical paths inside test build directory,
+ // so if the build directory is a symlink, normalization doesn't help.
+ //
+ // NOTE: There are also tests which print the non-canonical name, so we need both this and
+ // the above normalizations.
+ normalize_path(&self.output_base_dir().canonicalize_utf8().unwrap(), "$TEST_BUILD_DIR");
// eg. /home/user/rust/build
normalize_path(&self.config.build_root, "$BUILD_DIR");
if json {
// escaped newlines in json strings should be readable
- // in the stderr files. There's no point int being correct,
+ // in the stderr files. There's no point in being correct,
// since only humans process the stderr files.
// Thus we just turn escaped newlines back into newlines.
normalized = normalized.replace("\\n", "\n");
@@ -2546,7 +2526,7 @@ fn normalize_platform_differences(output: &str) -> String {
.replace("\r\n", "\n")
}
- fn expected_output_path(&self, kind: &str) -> PathBuf {
+ fn expected_output_path(&self, kind: &str) -> Utf8PathBuf {
let mut path =
expected_output_path(&self.testpaths, self.revision, &self.config.compare_mode, kind);
@@ -2575,19 +2555,18 @@ fn load_expected_output(&self, kind: &str) -> String {
}
}
- fn load_expected_output_from_path(&self, path: &Path) -> Result<String, String> {
- fs::read_to_string(path).map_err(|err| {
- format!("failed to load expected output from `{}`: {}", path.display(), err)
- })
+ fn load_expected_output_from_path(&self, path: &Utf8Path) -> Result<String, String> {
+ fs::read_to_string(path)
+ .map_err(|err| format!("failed to load expected output from `{}`: {}", path, err))
}
- fn delete_file(&self, file: &Path) {
+ fn delete_file(&self, file: &Utf8Path) {
if !file.exists() {
// Deleting a nonexistent file would error.
return;
}
- if let Err(e) = fs::remove_file(file) {
- self.fatal(&format!("failed to delete `{}`: {}", file.display(), e,));
+ if let Err(e) = fs::remove_file(file.as_std_path()) {
+ self.fatal(&format!("failed to delete `{}`: {}", file, e,));
}
}
@@ -2693,8 +2672,8 @@ fn compare_output(
fn show_diff(
&self,
stream: &str,
- expected_path: &Path,
- actual_path: &Path,
+ expected_path: &Utf8Path,
+ actual_path: &Utf8Path,
expected: &str,
actual: &str,
actual_unnormalized: &str,
@@ -2833,7 +2812,7 @@ fn init_incremental_test(&self) {
fs::create_dir_all(&incremental_dir).unwrap();
if self.config.verbose {
- println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+ println!("init_incremental_test: incremental_dir={incremental_dir}");
}
}
}
@@ -2891,8 +2870,8 @@ pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
#[derive(Debug)]
enum TargetLocation {
- ThisFile(PathBuf),
- ThisDirectory(PathBuf),
+ ThisFile(Utf8PathBuf),
+ ThisDirectory(Utf8PathBuf),
}
enum AllowUnused {
diff --git a/src/tools/compiletest/src/runtest/assembly.rs b/src/tools/compiletest/src/runtest/assembly.rs
index 89d7de5..91d4f62 100644
--- a/src/tools/compiletest/src/runtest/assembly.rs
+++ b/src/tools/compiletest/src/runtest/assembly.rs
@@ -1,4 +1,4 @@
-use std::path::PathBuf;
+use camino::Utf8PathBuf;
use super::{AllowUnused, Emit, LinkToAux, ProcRes, TargetLocation, TestCx};
@@ -19,7 +19,7 @@ pub(super) fn run_assembly_test(&self) {
}
}
- fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
+ fn compile_test_and_save_assembly(&self) -> (ProcRes, Utf8PathBuf) {
// This works with both `--emit asm` (as default output name for the assembly)
// and `ptx-linker` because the latter can write output at requested location.
let output_path = self.output_base_name().with_extension("s");
diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs
index 6c866cb..8dfa8d1 100644
--- a/src/tools/compiletest/src/runtest/codegen_units.rs
+++ b/src/tools/compiletest/src/runtest/codegen_units.rs
@@ -26,9 +26,7 @@ pub(super) fn run_codegen_units_test(&self) {
.stdout
.lines()
.filter(|line| line.starts_with(PREFIX))
- .map(|line| {
- line.replace(&self.testpaths.file.display().to_string(), "TEST_PATH").to_string()
- })
+ .map(|line| line.replace(&self.testpaths.file.as_str(), "TEST_PATH").to_string())
.map(|line| str_to_mono_item(&line, true))
.collect();
diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs
index 56fc5ba..41cfeae 100644
--- a/src/tools/compiletest/src/runtest/coverage.rs
+++ b/src/tools/compiletest/src/runtest/coverage.rs
@@ -1,9 +1,9 @@
//! Code specific to the coverage test suites.
use std::ffi::OsStr;
-use std::path::{Path, PathBuf};
use std::process::Command;
+use camino::{Utf8Path, Utf8PathBuf};
use glob::glob;
use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP};
@@ -11,7 +11,7 @@
use crate::util::static_regex;
impl<'test> TestCx<'test> {
- fn coverage_dump_path(&self) -> &Path {
+ fn coverage_dump_path(&self) -> &Utf8Path {
self.config
.coverage_dump_path
.as_deref()
@@ -79,10 +79,8 @@ pub(super) fn run_coverage_run_test(&self) {
std::fs::remove_file(&profdata_path).unwrap();
}
- let proc_res = self.exec_compiled_test_general(
- &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())],
- false,
- );
+ let proc_res =
+ self.exec_compiled_test_general(&[("LLVM_PROFILE_FILE", profraw_path.as_str())], false);
if self.props.failure_status.is_some() {
self.check_correct_failure_status(&proc_res);
} else if !proc_res.status.success() {
@@ -158,8 +156,8 @@ pub(super) fn run_coverage_run_test(&self) {
/// `.profraw` files and doctest executables to the given vectors.
fn run_doctests_for_coverage(
&self,
- profraw_paths: &mut Vec<PathBuf>,
- bin_paths: &mut Vec<PathBuf>,
+ profraw_paths: &mut Vec<Utf8PathBuf>,
+ bin_paths: &mut Vec<Utf8PathBuf>,
) {
// Put .profraw files and doctest executables in dedicated directories,
// to make it easier to glob them all later.
@@ -204,10 +202,9 @@ fn run_doctests_for_coverage(
self.fatal_proc_rec("rustdoc --test failed!", &proc_res)
}
- fn glob_iter(path: impl AsRef<Path>) -> impl Iterator<Item = PathBuf> {
- let path_str = path.as_ref().to_str().unwrap();
- let iter = glob(path_str).unwrap();
- iter.map(Result::unwrap)
+ fn glob_iter(path: impl AsRef<Utf8Path>) -> impl Iterator<Item = Utf8PathBuf> {
+ let iter = glob(path.as_ref().as_str()).unwrap();
+ iter.map(Result::unwrap).map(Utf8PathBuf::try_from).map(Result::unwrap)
}
// Find all profraw files in the profraw directory.
diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs
index d9e5c3f..a4103c5 100644
--- a/src/tools/compiletest/src/runtest/debugger.rs
+++ b/src/tools/compiletest/src/runtest/debugger.rs
@@ -1,7 +1,8 @@
use std::fmt::Write;
use std::fs::File;
use std::io::{BufRead, BufReader};
-use std::path::{Path, PathBuf};
+
+use camino::{Utf8Path, Utf8PathBuf};
use crate::common::Config;
use crate::runtest::ProcRes;
@@ -15,11 +16,15 @@ pub(super) struct DebuggerCommands {
/// Contains the source line number to check and the line itself
check_lines: Vec<(usize, String)>,
/// Source file name
- file: PathBuf,
+ file: Utf8PathBuf,
}
impl DebuggerCommands {
- pub fn parse_from(file: &Path, config: &Config, debugger_prefix: &str) -> Result<Self, String> {
+ pub fn parse_from(
+ file: &Utf8Path,
+ config: &Config,
+ debugger_prefix: &str,
+ ) -> Result<Self, String> {
let command_directive = format!("{debugger_prefix}-command");
let check_directive = format!("{debugger_prefix}-check");
@@ -27,7 +32,7 @@ pub fn parse_from(file: &Path, config: &Config, debugger_prefix: &str) -> Result
let mut commands = vec![];
let mut check_lines = vec![];
let mut counter = 0;
- let reader = BufReader::new(File::open(file).unwrap());
+ let reader = BufReader::new(File::open(file.as_std_path()).unwrap());
for (line_no, line) in reader.lines().enumerate() {
counter += 1;
let line = line.map_err(|e| format!("Error while parsing debugger commands: {}", e))?;
@@ -50,7 +55,7 @@ pub fn parse_from(file: &Path, config: &Config, debugger_prefix: &str) -> Result
}
}
- Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_owned() })
+ Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_path_buf() })
}
/// Given debugger output and lines to check, ensure that every line is
@@ -81,10 +86,10 @@ pub fn check_output(&self, debugger_run_result: &ProcRes) -> Result<(), String>
if missing.is_empty() {
Ok(())
} else {
- let fname = self.file.file_name().unwrap().to_string_lossy();
+ let fname = self.file.file_name().unwrap();
let mut msg = format!(
"check directive(s) from `{}` not found in debugger output. errors:",
- self.file.display()
+ self.file
);
for (src_lineno, err_line) in missing {
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index 50e733c..31240df 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -1,9 +1,9 @@
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
-use std::path::Path;
use std::process::{Command, Output, Stdio};
+use camino::Utf8Path;
use tracing::debug;
use super::debugger::DebuggerCommands;
@@ -73,11 +73,11 @@ fn run_debuginfo_cdb_test_no_opt(&self) {
let mut js_extension = self.testpaths.file.clone();
js_extension.set_extension("cdb.js");
if js_extension.exists() {
- script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy()));
+ script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension));
}
// Set breakpoints on every line that contains the string "#break"
- let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
+ let source_file_name = self.testpaths.file.file_name().unwrap();
for line in &dbg_cmds.breakpoint_lines {
script_str.push_str(&format!("bp `{}:{}`\n", source_file_name, line));
}
@@ -151,16 +151,11 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
if is_android_gdb_target(&self.config.target) {
cmds = cmds.replace("run", "continue");
- let tool_path = match self.config.android_cross_path.to_str() {
- Some(x) => x.to_owned(),
- None => self.fatal("cannot find android cross path"),
- };
-
// write debugger script
let mut script_str = String::with_capacity(2048);
script_str.push_str(&format!("set charset {}\n", Self::charset()));
- script_str.push_str(&format!("set sysroot {}\n", tool_path));
- script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
+ script_str.push_str(&format!("set sysroot {}\n", &self.config.android_cross_path));
+ script_str.push_str(&format!("file {}\n", exe_file));
script_str.push_str("target remote :5039\n");
script_str.push_str(&format!(
"set solib-search-path \
@@ -169,12 +164,8 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
));
for line in &dbg_cmds.breakpoint_lines {
script_str.push_str(
- format!(
- "break {:?}:{}\n",
- self.testpaths.file.file_name().unwrap().to_string_lossy(),
- *line
- )
- .as_str(),
+ format!("break {}:{}\n", self.testpaths.file.file_name().unwrap(), *line)
+ .as_str(),
);
}
script_str.push_str(&cmds);
@@ -203,7 +194,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
self.config.adb_test_dir.clone(),
if self.config.target.contains("aarch64") { "64" } else { "" },
self.config.adb_test_dir.clone(),
- exe_file.file_name().unwrap().to_str().unwrap()
+ exe_file.file_name().unwrap()
);
debug!("adb arg: {}", adb_arg);
@@ -242,7 +233,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
gdb.args(debugger_opts);
// FIXME(jieyouxu): don't pass an empty Path
- let cmdline = self.make_cmdline(&gdb, Path::new(""));
+ let cmdline = self.make_cmdline(&gdb, Utf8Path::new(""));
logv(self.config, format!("executing {}", cmdline));
cmdline
};
@@ -259,7 +250,6 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
}
} else {
let rust_pp_module_abs_path = self.config.src_root.join("src").join("etc");
- let rust_pp_module_abs_path = rust_pp_module_abs_path.to_str().unwrap();
// write debugger script
let mut script_str = String::with_capacity(2048);
script_str.push_str(&format!("set charset {}\n", Self::charset()));
@@ -274,17 +264,15 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
// GDB's script auto loading safe path
script_str.push_str(&format!(
"add-auto-load-safe-path {}\n",
- rust_pp_module_abs_path.replace(r"\", r"\\")
+ rust_pp_module_abs_path.as_str().replace(r"\", r"\\")
));
- let output_base_dir = self.output_base_dir().to_str().unwrap().to_owned();
-
// Add the directory containing the output binary to
// include embedded pretty printers to GDB's script
// auto loading safe path
script_str.push_str(&format!(
"add-auto-load-safe-path {}\n",
- output_base_dir.replace(r"\", r"\\")
+ self.output_base_dir().as_str().replace(r"\", r"\\")
));
}
}
@@ -301,12 +289,13 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
script_str.push_str("set print pretty off\n");
// Add the pretty printer directory to GDB's source-file search path
- script_str
- .push_str(&format!("directory {}\n", rust_pp_module_abs_path.replace(r"\", r"\\")));
+ script_str.push_str(&format!(
+ "directory {}\n",
+ rust_pp_module_abs_path.as_str().replace(r"\", r"\\")
+ ));
// Load the target executable
- script_str
- .push_str(&format!("file {}\n", exe_file.to_str().unwrap().replace(r"\", r"\\")));
+ script_str.push_str(&format!("file {}\n", exe_file.as_str().replace(r"\", r"\\")));
// Force GDB to print values in the Rust format.
script_str.push_str("set language rust\n");
@@ -315,7 +304,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
for line in &dbg_cmds.breakpoint_lines {
script_str.push_str(&format!(
"break '{}':{}\n",
- self.testpaths.file.file_name().unwrap().to_string_lossy(),
+ self.testpaths.file.file_name().unwrap(),
*line
));
}
@@ -410,14 +399,14 @@ fn run_debuginfo_lldb_test_no_opt(&self) {
script_str.push_str(&format!(
"command script import {}/lldb_lookup.py\n",
- rust_pp_module_abs_path.to_str().unwrap()
+ rust_pp_module_abs_path
));
File::open(rust_pp_module_abs_path.join("lldb_commands"))
.and_then(|mut file| file.read_to_string(&mut script_str))
.expect("Failed to read lldb_commands");
// Set breakpoints on every line that contains the string "#break"
- let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
+ let source_file_name = self.testpaths.file.file_name().unwrap();
for line in &dbg_cmds.breakpoint_lines {
script_str.push_str(&format!(
"breakpoint set --file '{}' --line {}\n",
@@ -451,7 +440,7 @@ fn run_debuginfo_lldb_test_no_opt(&self) {
}
}
- fn run_lldb(&self, test_executable: &Path, debugger_script: &Path) -> ProcRes {
+ fn run_lldb(&self, test_executable: &Utf8Path, debugger_script: &Utf8Path) -> ProcRes {
// Prepare the lldb_batchmode which executes the debugger script
let lldb_script_path = self.config.src_root.join("src/etc/lldb_batchmode.py");
let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
diff --git a/src/tools/compiletest/src/runtest/js_doc.rs b/src/tools/compiletest/src/runtest/js_doc.rs
index d630aff..fd53f01 100644
--- a/src/tools/compiletest/src/runtest/js_doc.rs
+++ b/src/tools/compiletest/src/runtest/js_doc.rs
@@ -9,8 +9,7 @@ pub(super) fn run_rustdoc_js_test(&self) {
self.document(&out_dir, &self.testpaths);
- let file_stem =
- self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem");
+ let file_stem = self.testpaths.file.file_stem().expect("no file stem");
let res = self.run_command_to_procres(
Command::new(&nodejs)
.arg(self.config.src_root.join("src/tools/rustdoc-js/tester.js"))
diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs
index d1ec003..ded6a68 100644
--- a/src/tools/compiletest/src/runtest/mir_opt.rs
+++ b/src/tools/compiletest/src/runtest/mir_opt.rs
@@ -1,6 +1,6 @@
use std::fs;
-use std::path::{Path, PathBuf};
+use camino::{Utf8Path, Utf8PathBuf};
use glob::glob;
use miropt_test_tools::{MiroptTest, MiroptTestFile, files_for_miropt_test};
use tracing::debug;
@@ -14,7 +14,7 @@ pub(super) fn run_mir_opt_test(&self) {
let should_run = self.should_run(pm);
let mut test_info = files_for_miropt_test(
- &self.testpaths.file,
+ &self.testpaths.file.as_std_path(),
self.config.get_pointer_width(),
self.config.target_cfg().panic.for_miropt_test_tools(),
);
@@ -38,20 +38,15 @@ pub(super) fn run_mir_opt_test(&self) {
fn check_mir_dump(&self, test_info: MiroptTest) {
let test_dir = self.testpaths.file.parent().unwrap();
- let test_crate =
- self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace('-', "_");
+ let test_crate = self.testpaths.file.file_stem().unwrap().replace('-', "_");
let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info;
if self.config.bless {
- for e in
- glob(&format!("{}/{}.*{}.mir", test_dir.display(), test_crate, suffix)).unwrap()
- {
+ for e in glob(&format!("{}/{}.*{}.mir", test_dir, test_crate, suffix)).unwrap() {
fs::remove_file(e.unwrap()).unwrap();
}
- for e in
- glob(&format!("{}/{}.*{}.diff", test_dir.display(), test_crate, suffix)).unwrap()
- {
+ for e in glob(&format!("{}/{}.*{}.diff", test_dir, test_crate, suffix)).unwrap() {
fs::remove_file(e.unwrap()).unwrap();
}
}
@@ -60,19 +55,15 @@ fn check_mir_dump(&self, test_info: MiroptTest) {
let dumped_string = if let Some(after) = to_file {
self.diff_mir_files(from_file.into(), after.into())
} else {
- let mut output_file = PathBuf::new();
+ let mut output_file = Utf8PathBuf::new();
output_file.push(self.get_mir_dump_dir());
output_file.push(&from_file);
- debug!(
- "comparing the contents of: {} with {}",
- output_file.display(),
- expected_file.display()
- );
+ debug!("comparing the contents of: {} with {:?}", output_file, expected_file);
if !output_file.exists() {
panic!(
"Output file `{}` from test does not exist, available files are in `{}`",
- output_file.display(),
- output_file.parent().unwrap().display()
+ output_file,
+ output_file.parent().unwrap()
);
}
self.check_mir_test_timestamp(&from_file, &output_file);
@@ -107,21 +98,20 @@ fn check_mir_dump(&self, test_info: MiroptTest) {
}
}
- fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String {
- let to_full_path = |path: PathBuf| {
+ fn diff_mir_files(&self, before: Utf8PathBuf, after: Utf8PathBuf) -> String {
+ let to_full_path = |path: Utf8PathBuf| {
let full = self.get_mir_dump_dir().join(&path);
if !full.exists() {
panic!(
"the mir dump file for {} does not exist (requested in {})",
- path.display(),
- self.testpaths.file.display(),
+ path, self.testpaths.file,
);
}
full
};
let before = to_full_path(before);
let after = to_full_path(after);
- debug!("comparing the contents of: {} with {}", before.display(), after.display());
+ debug!("comparing the contents of: {} with {}", before, after);
let before = fs::read_to_string(before).unwrap();
let after = fs::read_to_string(after).unwrap();
let before = self.normalize_output(&before, &[]);
@@ -138,8 +128,8 @@ fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String {
dumped_string
}
- fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) {
- let t = |file| fs::metadata(file).unwrap().modified().unwrap();
+ fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Utf8Path) {
+ let t = |file: &Utf8Path| fs::metadata(file.as_std_path()).unwrap().modified().unwrap();
let source_file = &self.testpaths.file;
let output_time = t(output_file);
let source_time = t(source_file);
@@ -147,8 +137,7 @@ fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) {
debug!("source file time: {:?} output file time: {:?}", source_time, output_time);
panic!(
"test source file `{}` is newer than potentially stale output file `{}`.",
- source_file.display(),
- test_name
+ source_file, test_name
);
}
}
diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
index 0731169..a5ce929 100644
--- a/src/tools/compiletest/src/runtest/run_make.rs
+++ b/src/tools/compiletest/src/runtest/run_make.rs
@@ -1,8 +1,8 @@
-use std::path::Path;
use std::process::{Command, Output, Stdio};
use std::{env, fs};
use build_helper::fs::{ignore_not_found, recursive_remove};
+use camino::{Utf8Path, Utf8PathBuf};
use super::{ProcRes, TestCx, disable_error_reporting};
use crate::util::{copy_dir_all, dylib_env_var};
@@ -39,14 +39,16 @@ pub(super) fn run_rmake_test(&self) {
// Copy all input files (apart from rmake.rs) to the temporary directory,
// so that the input directory structure from `tests/run-make/<test>` is mirrored
// to the `rmake_out` directory.
- for path in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) {
- let path = path.unwrap().path().to_path_buf();
+ for entry in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) {
+ let entry = entry.unwrap();
+ let path = entry.path();
+ let path = <&Utf8Path>::try_from(path).unwrap();
if path.file_name().is_some_and(|s| s != "rmake.rs") {
let target = rmake_out_dir.join(path.strip_prefix(&self.testpaths.file).unwrap());
if path.is_dir() {
- copy_dir_all(&path, target).unwrap();
+ copy_dir_all(&path, &target).unwrap();
} else {
- fs::copy(&path, target).unwrap();
+ fs::copy(path.as_std_path(), target).unwrap();
}
}
}
@@ -83,8 +85,10 @@ pub(super) fn run_rmake_test(&self) {
// on some linux distros.
// 2. Specific library paths in `self.config.compile_lib_path` needed for running rustc.
- let base_dylib_search_paths =
- Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));
+ let base_dylib_search_paths = Vec::from_iter(
+ env::split_paths(&env::var(dylib_env_var()).unwrap())
+ .map(|p| Utf8PathBuf::try_from(p).expect("dylib env var contains non-UTF8 paths")),
+ );
// Calculate the paths of the recipe binary. As previously discussed, this is placed at
// `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
@@ -113,13 +117,13 @@ pub(super) fn run_rmake_test(&self) {
.arg("-o")
.arg(&recipe_bin)
// Specify library search paths for `run_make_support`.
- .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy()))
- .arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
- .arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
+ .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap()))
+ .arg(format!("-Ldependency={}", &support_lib_deps))
+ .arg(format!("-Ldependency={}", &support_lib_deps_deps))
// Provide `run_make_support` as extern prelude, so test writers don't need to write
// `extern run_make_support;`.
.arg("--extern")
- .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
+ .arg(format!("run_make_support={}", &support_lib_path))
.arg("--edition=2021")
.arg(&self.testpaths.file.join("rmake.rs"))
.arg("-Cprefer-dynamic");
@@ -240,7 +244,7 @@ pub(super) fn run_rmake_test(&self) {
if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
// We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
// and that `lib.exe` lives next to it.
- let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
+ let lib = Utf8Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
// MSYS doesn't like passing flags of the form `/foo` as it thinks it's
// a path and instead passes `C:\msys64\foo`, so convert all
@@ -262,8 +266,8 @@ pub(super) fn run_rmake_test(&self) {
cmd.env("IS_MSVC", "1")
.env("IS_WINDOWS", "1")
- .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
- .env("MSVC_LIB_PATH", format!("{}", lib.display()))
+ .env("MSVC_LIB", format!("'{}' -nologo", lib))
+ .env("MSVC_LIB_PATH", &lib)
// Note: we diverge from legacy run_make and don't lump `CC` the compiler and
// default flags together.
.env("CC_DEFAULT_FLAGS", &cflags)
diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs
index 2583ae9..637ea83 100644
--- a/src/tools/compiletest/src/runtest/rustdoc.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc.rs
@@ -7,7 +7,9 @@ pub(super) fn run_rustdoc_test(&self) {
assert!(self.revision.is_none(), "revisions not relevant here");
let out_dir = self.output_base_dir();
- remove_and_create_dir_all(&out_dir);
+ remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
+ });
let proc_res = self.document(&out_dir, &self.testpaths);
if !proc_res.status.success() {
diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs
index bf7eb2e..9f88fac 100644
--- a/src/tools/compiletest/src/runtest/rustdoc_json.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs
@@ -9,7 +9,9 @@ pub(super) fn run_rustdoc_json_test(&self) {
assert!(self.revision.is_none(), "revisions not relevant here");
let out_dir = self.output_base_dir();
- remove_and_create_dir_all(&out_dir);
+ remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| {
+ panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
+ });
let proc_res = self.document(&out_dir, &self.testpaths);
if !proc_res.status.success() {
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index 974e517..e87b037 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -68,7 +68,7 @@ pub(super) fn run_ui_test(&self) {
{
let mut coverage_file_path = self.config.build_test_suite_root.clone();
coverage_file_path.push("rustfix_missing_coverage.txt");
- debug!("coverage_file_path: {}", coverage_file_path.display());
+ debug!("coverage_file_path: {}", coverage_file_path);
let mut file = OpenOptions::new()
.create(true)
@@ -76,8 +76,8 @@ pub(super) fn run_ui_test(&self) {
.open(coverage_file_path.as_path())
.expect("could not create or open file");
- if let Err(e) = writeln!(file, "{}", self.testpaths.file.display()) {
- panic!("couldn't write to {}: {e:?}", coverage_file_path.display());
+ if let Err(e) = writeln!(file, "{}", self.testpaths.file) {
+ panic!("couldn't write to {}: {e:?}", coverage_file_path);
}
}
} else if self.props.run_rustfix {
@@ -119,7 +119,7 @@ pub(super) fn run_ui_test(&self) {
self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
println!(
"To only update this specific test, also pass `--test-args {}`",
- relative_path_to_file.display(),
+ relative_path_to_file,
);
self.fatal_proc_rec(
&format!("{} errors occurred comparing output.", errors),
@@ -211,8 +211,6 @@ pub(super) fn run_ui_test(&self) {
let crate_name =
self.testpaths.file.file_stem().expect("test must have a file stem");
// crate name must be alphanumeric or `_`.
- let crate_name =
- crate_name.to_str().expect("crate name implies file name must be valid UTF-8");
// replace `a.foo` -> `a__foo` for crate name purposes.
// replace `revision-name-with-dashes` -> `revision_name_with_underscore`
let crate_name = crate_name.replace('.', "__");
diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs
index 43c6dc0..e3e4a81 100644
--- a/src/tools/compiletest/src/tests.rs
+++ b/src/tools/compiletest/src/tests.rs
@@ -1,5 +1,3 @@
-use std::ffi::OsString;
-
use crate::debuggers::{extract_gdb_version, extract_lldb_version};
use crate::is_test;
@@ -60,11 +58,11 @@ fn test_extract_lldb_version() {
#[test]
fn is_test_test() {
- assert!(is_test(&OsString::from("a_test.rs")));
- assert!(!is_test(&OsString::from(".a_test.rs")));
- assert!(!is_test(&OsString::from("a_cat.gif")));
- assert!(!is_test(&OsString::from("#a_dog_gif")));
- assert!(!is_test(&OsString::from("~a_temp_file")));
+ assert!(is_test("a_test.rs"));
+ assert!(!is_test(".a_test.rs"));
+ assert!(!is_test("a_cat.gif"));
+ assert!(!is_test("#a_dog_gif"));
+ assert!(!is_test("~a_temp_file"));
}
#[test]
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index bff02f1..81f5679 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -1,8 +1,7 @@
use std::env;
-use std::ffi::OsStr;
-use std::path::{Path, PathBuf};
use std::process::Command;
+use camino::{Utf8Path, Utf8PathBuf};
use tracing::*;
use crate::common::Config;
@@ -34,21 +33,21 @@ pub fn logv(config: &Config, s: String) {
}
}
-pub trait PathBufExt {
+pub trait Utf8PathBufExt {
/// Append an extension to the path, even if it already has one.
- fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf;
+ fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf;
}
-impl PathBufExt for PathBuf {
- fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
- if extension.as_ref().is_empty() {
+impl Utf8PathBufExt for Utf8PathBuf {
+ fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf {
+ if extension.is_empty() {
self.clone()
} else {
- let mut fname = self.file_name().unwrap().to_os_string();
- if !extension.as_ref().to_str().unwrap().starts_with('.') {
- fname.push(".");
+ let mut fname = self.file_name().unwrap().to_string();
+ if !extension.starts_with('.') {
+ fname.push_str(".");
}
- fname.push(extension);
+ fname.push_str(extension);
self.with_file_name(fname)
}
}
@@ -71,22 +70,27 @@ pub fn dylib_env_var() -> &'static str {
/// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.
/// If the dylib_path_var is already set for this cmd, the old value will be overwritten!
-pub fn add_dylib_path(cmd: &mut Command, paths: impl Iterator<Item = impl Into<PathBuf>>) {
+pub fn add_dylib_path(
+ cmd: &mut Command,
+ paths: impl Iterator<Item = impl Into<std::path::PathBuf>>,
+) {
let path_env = env::var_os(dylib_env_var());
let old_paths = path_env.as_ref().map(env::split_paths);
let new_paths = paths.map(Into::into).chain(old_paths.into_iter().flatten());
cmd.env(dylib_env_var(), env::join_paths(new_paths).unwrap());
}
-pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Result<()> {
- std::fs::create_dir_all(&dst)?;
- for entry in std::fs::read_dir(src)? {
+pub fn copy_dir_all(src: &Utf8Path, dst: &Utf8Path) -> std::io::Result<()> {
+ std::fs::create_dir_all(dst.as_std_path())?;
+ for entry in std::fs::read_dir(src.as_std_path())? {
let entry = entry?;
+ let path = Utf8PathBuf::try_from(entry.path()).unwrap();
+ let file_name = path.file_name().unwrap();
let ty = entry.file_type()?;
if ty.is_dir() {
- copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
+ copy_dir_all(&path, &dst.join(file_name))?;
} else {
- std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
+ std::fs::copy(path.as_std_path(), dst.join(file_name).as_std_path())?;
}
}
Ok(())
diff --git a/src/tools/compiletest/src/util/tests.rs b/src/tools/compiletest/src/util/tests.rs
index b09a183..5bcae0d 100644
--- a/src/tools/compiletest/src/util/tests.rs
+++ b/src/tools/compiletest/src/util/tests.rs
@@ -3,12 +3,12 @@
#[test]
fn path_buf_with_extra_extension_test() {
assert_eq!(
- PathBuf::from("foo.rs.stderr"),
- PathBuf::from("foo.rs").with_extra_extension("stderr")
+ Utf8PathBuf::from("foo.rs.stderr"),
+ Utf8PathBuf::from("foo.rs").with_extra_extension("stderr")
);
assert_eq!(
- PathBuf::from("foo.rs.stderr"),
- PathBuf::from("foo.rs").with_extra_extension(".stderr")
+ Utf8PathBuf::from("foo.rs.stderr"),
+ Utf8PathBuf::from("foo.rs").with_extra_extension(".stderr")
);
- assert_eq!(PathBuf::from("foo.rs"), PathBuf::from("foo.rs").with_extra_extension(""));
+ assert_eq!(Utf8PathBuf::from("foo.rs"), Utf8PathBuf::from("foo.rs").with_extra_extension(""));
}
diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml
index f5c0e56..152cd50 100644
--- a/src/tools/generate-windows-sys/Cargo.toml
+++ b/src/tools/generate-windows-sys/Cargo.toml
@@ -4,4 +4,4 @@
edition = "2021"
[dependencies.windows-bindgen]
-version = "0.59.0"
+version = "0.61.0"
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index 54249fb..79e4198 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -156,7 +156,7 @@ fn parse<'a>(command_name: &str, negated: bool, args: &'a [String]) -> Option<(S
r#"
//@\s+
(?P<negated>!?)
- (?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*)
+ (?P<cmd>[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)
(?P<args>.*)$
"#,
)
diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs
index 28deb7e..dd0b4ac 100644
--- a/src/tools/jsondoclint/src/validator/tests.rs
+++ b/src/tools/jsondoclint/src/validator/tests.rs
@@ -42,6 +42,7 @@ fn errors_on_missing_links() {
)]),
paths: FxHashMap::default(),
external_crates: FxHashMap::default(),
+ target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] },
format_version: rustdoc_json_types::FORMAT_VERSION,
};
@@ -112,6 +113,7 @@ fn errors_on_local_in_paths_and_not_index() {
},
)]),
external_crates: FxHashMap::default(),
+ target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] },
format_version: rustdoc_json_types::FORMAT_VERSION,
};
@@ -216,6 +218,7 @@ fn errors_on_missing_path() {
ItemSummary { crate_id: 0, path: vec!["foo".to_owned()], kind: ItemKind::Module },
)]),
external_crates: FxHashMap::default(),
+ target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] },
format_version: rustdoc_json_types::FORMAT_VERSION,
};
@@ -259,6 +262,7 @@ fn checks_local_crate_id_is_correct() {
)]),
paths: FxHashMap::default(),
external_crates: FxHashMap::default(),
+ target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] },
format_version: FORMAT_VERSION,
};
check(&krate, &[]);
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 0c6f4a3..6f4bd3e 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -257,9 +257,9 @@
[[package]]
name = "crossbeam-channel"
-version = "0.5.14"
+version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471"
+checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
dependencies = [
"crossbeam-utils",
]
@@ -436,9 +436,9 @@
[[package]]
name = "libffi"
-version = "3.2.0"
+version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
+checksum = "4a9434b6fc77375fb624698d5f8c49d7e80b10d59eb1219afda27d1f824d4074"
dependencies = [
"libc",
"libffi-sys",
@@ -446,9 +446,9 @@
[[package]]
name = "libffi-sys"
-version = "2.3.0"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c"
+checksum = "ead36a2496acfc8edd6cc32352110e9478ac5b9b5f5b9856ebd3d28019addb84"
dependencies = [
"cc",
]
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index e9ee19b..bb24e70 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -37,7 +37,7 @@
[target.'cfg(unix)'.dependencies]
libc = "0.2"
-libffi = "3.2.0"
+libffi = "4.0.0"
libloading = "0.8"
[target.'cfg(target_family = "windows")'.dependencies]
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index b690bd9..755e02d 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -164,9 +164,9 @@
# Partially supported targets (tier 2)
BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator
UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
- TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe concurrency sync
- TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
- TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync concurrency thread epoll eventfd
+ TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency fs libc-pipe
+ TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency fs libc-pipe
+ TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency epoll eventfd
TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index d2b8b51..d1107e5 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-7d7de5bf3c3cbf9c2c5bbc5cbfb9197a8a427d35
+1bc56185ee257ed829a0aea7abdc3b03c5fed887
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 56ee965..4e8fe0c 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -185,7 +185,7 @@ fn after_analysis<'tcx>(
let num_failed = sync::IntoDynSyncSend(AtomicU32::new(0));
sync::par_for_each_in(many_seeds.seeds.clone(), |seed| {
let mut config = config.clone();
- config.seed = Some(seed.into());
+ config.seed = Some((*seed).into());
eprintln!("Trying seed: {seed}");
let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, config)
.unwrap_or(rustc_driver::EXIT_FAILURE);
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 7d97e33..8dcadbe 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -65,7 +65,7 @@ fn win_get_full_path_name<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result<Pa
}
// Otherwise we try to do something kind of close to what Windows does, but this is probably not
// right in all cases.
- let mut result: Vec<&[u8]> = vec![]; // will be a vecot of components, joined by `/`.
+ let mut result: Vec<&[u8]> = vec![]; // will be a vector of components, joined by `/`.
let mut bytes = bytes; // the remaining bytes to process
let mut stop = false;
while !stop {
@@ -396,6 +396,25 @@ fn emulate_foreign_item_inner(
let last_error = this.get_last_error()?;
this.write_scalar(last_error, dest)?;
}
+ "RtlNtStatusToDosError" => {
+ let [status] = this.check_shim(abi, sys_conv, link_name, args)?;
+ let status = this.read_scalar(status)?.to_u32()?;
+ let err = match status {
+ // STATUS_MEDIA_WRITE_PROTECTED => ERROR_WRITE_PROTECT
+ 0xC00000A2 => 19,
+ // STATUS_FILE_INVALID => ERROR_FILE_INVALID
+ 0xC0000098 => 1006,
+ // STATUS_DISK_FULL => ERROR_DISK_FULL
+ 0xC000007F => 112,
+ // STATUS_IO_DEVICE_ERROR => ERROR_IO_DEVICE
+ 0xC0000185 => 1117,
+ // STATUS_ACCESS_DENIED => ERROR_ACCESS_DENIED
+ 0xC0000022 => 5,
+ // Anything without an error code => ERROR_MR_MID_NOT_FOUND
+ _ => 317,
+ };
+ this.write_scalar(Scalar::from_i32(err), dest)?;
+ }
// Querying system information
"GetSystemInfo" => {
diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock
index 24a8efc..276c518 100644
--- a/src/tools/miri/test_dependencies/Cargo.lock
+++ b/src/tools/miri/test_dependencies/Cargo.lock
@@ -156,9 +156,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs
index 312df9e..a015464 100644
--- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs
+++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs
@@ -10,7 +10,9 @@
mod utils;
use windows_sys::Win32::Foundation::{
- CloseHandle, ERROR_ALREADY_EXISTS, GENERIC_READ, GENERIC_WRITE, GetLastError,
+ CloseHandle, ERROR_ACCESS_DENIED, ERROR_ALREADY_EXISTS, ERROR_IO_DEVICE, GENERIC_READ,
+ GENERIC_WRITE, GetLastError, RtlNtStatusToDosError, STATUS_ACCESS_DENIED,
+ STATUS_IO_DEVICE_ERROR,
};
use windows_sys::Win32::Storage::FileSystem::{
BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, FILE_ATTRIBUTE_DIRECTORY,
@@ -26,6 +28,7 @@ fn main() {
test_create_always_twice();
test_open_always_twice();
test_open_dir_reparse();
+ test_ntstatus_to_dos();
}
}
@@ -191,6 +194,12 @@ unsafe fn test_open_dir_reparse() {
};
}
+unsafe fn test_ntstatus_to_dos() {
+ // We won't test all combinations, just a couple common ones
+ assert_eq!(RtlNtStatusToDosError(STATUS_IO_DEVICE_ERROR), ERROR_IO_DEVICE);
+ assert_eq!(RtlNtStatusToDosError(STATUS_ACCESS_DENIED), ERROR_ACCESS_DENIED);
+}
+
fn to_wide_cstr(path: &Path) -> Vec<u16> {
let mut raw_path = path.as_os_str().encode_wide().collect::<Vec<_>>();
raw_path.extend([0, 0]);
diff --git a/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs
index a1da60c..27ea123 100644
--- a/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs
+++ b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs
@@ -1,4 +1,4 @@
-use std::mem::{size_of, align_of};
+use std::mem::{align_of, size_of};
// See <https://github.com/rust-lang/rust/issues/134713>
diff --git a/src/tools/miri/tests/pass/issues/issue-139553.rs b/src/tools/miri/tests/pass/issues/issue-139553.rs
new file mode 100644
index 0000000..119d589
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-139553.rs
@@ -0,0 +1,45 @@
+//@compile-flags: -Zmiri-preemption-rate=0 -Zmiri-compare-exchange-weak-failure-rate=0
+use std::sync::mpsc::channel;
+use std::thread;
+
+/// This test aims to trigger a race condition that causes a double free in the unbounded channel
+/// implementation. The test relies on a particular thread scheduling to happen as annotated by the
+/// comments below.
+fn main() {
+ let (s1, r) = channel::<u64>();
+ let s2 = s1.clone();
+
+ let t1 = thread::spawn(move || {
+ // 1. The first action executed is an attempt to send the first value in the channel. This
+ // will begin to initialize the channel but will stop at a critical momement as
+ // indicated by the `yield_now()` call in the `start_send` method of the implementation.
+ let _ = s1.send(42);
+ // 4. The sender is re-scheduled and it finishes the initialization of the channel by
+ // setting head.block to the same value as tail.block. It then proceeds to publish its
+ // value but observes that the channel has already disconnected (due to the concurrent
+ // call of `discard_all_messages`) and aborts the send.
+ });
+ std::thread::yield_now();
+
+ // 2. A second sender attempts to send a value while the channel is in a half-initialized
+ // state. Here, half-initialized means that the `tail.block` pointer points to a valid block
+ // but `head.block` is still null. This condition is ensured by the yield of step 1. When
+ // this call returns the channel state has tail.index != head.index, tail.block != NULL, and
+ // head.block = NULL.
+ s2.send(42).unwrap();
+ // 3. This thread continues with dropping the one and only receiver. When all receivers are
+ // gone `discard_all_messages` will attempt to drop all currently sent values and
+ // de-allocate all the blocks. If `tail.block != NULL` but `head.block = NULL` the
+ // implementation waits for the initializing sender to finish by spinning/yielding.
+ drop(r);
+ // 5. This thread is rescheduled and `discard_all_messages` observes the head.block pointer set
+ // by step 4 and proceeds with deallocation. In the problematic version of the code
+ // `head.block` is simply read via an `Acquire` load and not swapped with NULL. After this
+ // call returns the channel state has tail.index = head.index, tail.block = NULL, and
+ // head.block != NULL.
+ t1.join().unwrap();
+ // 6. The last sender (s2) is dropped here which also attempts to cleanup any data in the
+ // channel. It observes `tail.index = head.index` and so it doesn't attempt to cleanup any
+ // messages but it also observes that `head.block != NULL` and attempts to deallocate it.
+ // This is however already deallocated by `discard_all_messages`, leading to a double free.
+}
diff --git a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs
index 341b228..abc0968 100644
--- a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs
+++ b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs
@@ -13,7 +13,7 @@ pub fn main() {
TLS.set(Some(Box::leak(Box::new(123))));
// We can only ignore leaks on targets that use `#[thread_local]` statics to implement
- // `thread_local!`. Ignore the test on targest that don't.
+ // `thread_local!`. Ignore the test on targets that don't.
if cfg!(target_thread_local) {
thread_local! {
static TLS_KEY: Cell<Option<&'static i32>> = Cell::new(None);
diff --git a/src/tools/nix-dev-shell/flake.nix b/src/tools/nix-dev-shell/flake.nix
index 1b838bd..b8287de 100644
--- a/src/tools/nix-dev-shell/flake.nix
+++ b/src/tools/nix-dev-shell/flake.nix
@@ -1,32 +1,24 @@
{
description = "rustc dev shell";
- inputs = {
- nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
- flake-utils.url = "github:numtide/flake-utils";
- };
+ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
- outputs = { self, nixpkgs, flake-utils, ... }:
- flake-utils.lib.eachDefaultSystem (system:
- let
- pkgs = import nixpkgs { inherit system; };
- x = import ./x { inherit pkgs; };
- in
- {
- devShells.default = with pkgs; mkShell {
- name = "rustc-dev-shell";
- nativeBuildInputs = with pkgs; [
- binutils cmake ninja pkg-config python3 git curl cacert patchelf nix
- ];
- buildInputs = with pkgs; [
- openssl glibc.out glibc.static x
- ];
- # Avoid creating text files for ICEs.
- RUSTC_ICE = "0";
- # Provide `libstdc++.so.6` for the self-contained lld.
- # Provide `libz.so.1`.
- LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [stdenv.cc.cc.lib zlib]}";
- };
- }
- );
+ outputs =
+ {
+ self,
+ nixpkgs,
+ }:
+ let
+ inherit (nixpkgs) lib;
+ forEachSystem = lib.genAttrs lib.systems.flakeExposed;
+ in
+ {
+ devShells = forEachSystem (system: {
+ default = nixpkgs.legacyPackages.${system}.callPackage ./shell.nix { };
+ });
+
+ packages = forEachSystem (system: {
+ default = nixpkgs.legacyPackages.${system}.callPackage ./x { };
+ });
+ };
}
diff --git a/src/tools/nix-dev-shell/shell.nix b/src/tools/nix-dev-shell/shell.nix
index a3f5969..0adbacf 100644
--- a/src/tools/nix-dev-shell/shell.nix
+++ b/src/tools/nix-dev-shell/shell.nix
@@ -1,18 +1,26 @@
-{ pkgs ? import <nixpkgs> {} }:
-let
- x = import ./x { inherit pkgs; };
+{
+ pkgs ? import <nixpkgs> { },
+}:
+let
+ inherit (pkgs.lib) lists attrsets;
+
+ x = pkgs.callPackage ./x { };
+ inherit (x.passthru) cacert env;
in
pkgs.mkShell {
- name = "rustc";
- nativeBuildInputs = with pkgs; [
- binutils cmake ninja pkg-config python3 git curl cacert patchelf nix
- ];
- buildInputs = with pkgs; [
- openssl glibc.out glibc.static x
- ];
- # Avoid creating text files for ICEs.
- RUSTC_ICE = "0";
- # Provide `libstdc++.so.6` for the self-contained lld.
- # Provide `libz.so.1`
- LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [stdenv.cc.cc.lib zlib]}";
+ name = "rustc-shell";
+
+ inputsFrom = [ x ];
+ packages = [
+ pkgs.git
+ pkgs.nix
+ x
+ # Get the runtime deps of the x wrapper
+ ] ++ lists.flatten (attrsets.attrValues env);
+
+ env = {
+ # Avoid creating text files for ICEs.
+ RUSTC_ICE = 0;
+ SSL_CERT_FILE = cacert;
+ };
}
diff --git a/src/tools/nix-dev-shell/x/default.nix b/src/tools/nix-dev-shell/x/default.nix
index e6dfbad..422c1c4 100644
--- a/src/tools/nix-dev-shell/x/default.nix
+++ b/src/tools/nix-dev-shell/x/default.nix
@@ -1,22 +1,83 @@
{
- pkgs ? import <nixpkgs> { },
+ pkgs,
+ lib,
+ stdenv,
+ rustc,
+ python3,
+ makeBinaryWrapper,
+ # Bootstrap
+ curl,
+ pkg-config,
+ libiconv,
+ openssl,
+ patchelf,
+ cacert,
+ zlib,
+ # LLVM Deps
+ ninja,
+ cmake,
+ glibc,
}:
-pkgs.stdenv.mkDerivation {
- name = "x";
+stdenv.mkDerivation (self: {
+ strictDeps = true;
+ name = "x-none";
+
+ outputs = [
+ "out"
+ "unwrapped"
+ ];
src = ./x.rs;
dontUnpack = true;
- nativeBuildInputs = with pkgs; [ rustc ];
+ nativeBuildInputs = [
+ rustc
+ makeBinaryWrapper
+ ];
+ env.PYTHON = python3.interpreter;
buildPhase = ''
- PYTHON=${pkgs.lib.getExe pkgs.python3} rustc -Copt-level=3 --crate-name x $src --out-dir $out/bin
+ rustc -Copt-level=3 --crate-name x $src --out-dir $unwrapped/bin
'';
- meta = with pkgs.lib; {
+ installPhase =
+ let
+ inherit (self.passthru) cacert env;
+ in
+ ''
+ makeWrapper $unwrapped/bin/x $out/bin/x \
+ --set-default SSL_CERT_FILE ${cacert} \
+ --prefix CPATH ";" "${lib.makeSearchPath "include" env.cpath}" \
+ --prefix PATH : ${lib.makeBinPath env.path} \
+ --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath env.ldLib}
+ '';
+
+ # For accessing them in the devshell
+ passthru = {
+ env = {
+ cpath = [ libiconv ];
+ path = [
+ python3
+ patchelf
+ curl
+ pkg-config
+ cmake
+ ninja
+ stdenv.cc
+ ];
+ ldLib = [
+ openssl
+ zlib
+ stdenv.cc.cc.lib
+ ];
+ };
+ cacert = "${cacert}/etc/ssl/certs/ca-bundle.crt";
+ };
+
+ meta = {
description = "Helper for rust-lang/rust x.py";
homepage = "https://github.com/rust-lang/rust/blob/master/src/tools/x";
- license = licenses.mit;
+ license = lib.licenses.mit;
mainProgram = "x";
};
-}
+})
diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs
index 90d0ca7..9342d16 100644
--- a/src/tools/opt-dist/src/environment.rs
+++ b/src/tools/opt-dist/src/environment.rs
@@ -25,6 +25,7 @@ pub struct Environment {
prebuilt_rustc_perf: Option<Utf8PathBuf>,
use_bolt: bool,
shared_llvm: bool,
+ run_tests: bool,
}
impl Environment {
@@ -101,6 +102,10 @@ pub fn skipped_tests(&self) -> &[String] {
pub fn benchmark_cargo_config(&self) -> &[String] {
&self.benchmark_cargo_config
}
+
+ pub fn run_tests(&self) -> bool {
+ self.run_tests
+ }
}
/// What is the extension of binary executables on this platform?
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index ac5d294..d5e6640 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -76,7 +76,7 @@ enum EnvironmentCmd {
rustc_perf_checkout_dir: Option<Utf8PathBuf>,
/// Is LLVM for `rustc` built in shared library mode?
- #[arg(long, default_value_t = true)]
+ #[arg(long, default_value_t = true, action(clap::ArgAction::Set))]
llvm_shared: bool,
/// Should BOLT optimization be used? If yes, host LLVM must have BOLT binaries
@@ -94,6 +94,10 @@ enum EnvironmentCmd {
/// Arguments passed to `rustc-perf --cargo-config <value>` when running benchmarks.
#[arg(long)]
benchmark_cargo_config: Vec<String>,
+
+ /// Perform tests after final build if it's not a try build
+ #[arg(long)]
+ run_tests: bool,
},
/// Perform an optimized build on Linux CI, from inside Docker.
LinuxCi {
@@ -125,6 +129,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
skipped_tests,
benchmark_cargo_config,
shared,
+ run_tests,
} => {
let env = EnvironmentBuilder::default()
.host_tuple(target_triple)
@@ -138,6 +143,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
.use_bolt(use_bolt)
.skipped_tests(skipped_tests)
.benchmark_cargo_config(benchmark_cargo_config)
+ .run_tests(run_tests)
.build()?;
(env, shared.build_args)
@@ -160,6 +166,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
// FIXME: Enable bolt for aarch64 once it's fixed upstream. Broken as of December 2024.
.use_bolt(!is_aarch64)
.skipped_tests(vec![])
+ .run_tests(true)
.build()?;
(env, shared.build_args)
@@ -179,6 +186,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
.shared_llvm(false)
.use_bolt(false)
.skipped_tests(vec![])
+ .run_tests(true)
.build()?;
(env, shared.build_args)
@@ -344,7 +352,7 @@ fn execute_pipeline(
// possible regressions.
// The tests are not executed for try builds, which can be in various broken states, so we don't
// want to gatekeep them with tests.
- if !is_try_build() {
+ if !is_try_build() && env.run_tests() {
timer.section("Run tests", |_| run_tests(env))?;
}
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 30c79f9..47159a4 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -70,7 +70,9 @@ fn merge_llvm_profiles(
profdata: LlvmProfdata,
) -> anyhow::Result<()> {
let llvm_profdata = match profdata {
- LlvmProfdata::Host => env.host_llvm_dir().join("bin/llvm-profdata"),
+ LlvmProfdata::Host => {
+ env.host_llvm_dir().join(format!("bin/llvm-profdata{}", executable_extension()))
+ }
LlvmProfdata::Target => env
.build_artifacts()
.join("llvm")
diff --git a/src/tools/opt-dist/src/utils/mod.rs b/src/tools/opt-dist/src/utils/mod.rs
index 32d88a5..fb4f14e 100644
--- a/src/tools/opt-dist/src/utils/mod.rs
+++ b/src/tools/opt-dist/src/utils/mod.rs
@@ -36,7 +36,9 @@ pub fn clear_llvm_files(env: &Environment) -> anyhow::Result<()> {
// directories ourselves.
log::info!("Clearing LLVM build files");
delete_directory(&env.build_artifacts().join("llvm"))?;
- delete_directory(&env.build_artifacts().join("lld"))?;
+ if env.build_artifacts().join("lld").is_dir() {
+ delete_directory(&env.build_artifacts().join("lld"))?;
+ }
Ok(())
}
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index f9beffe..15ed03a 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -14,9 +14,5 @@
serde_json = "1.0"
libc = "0.2"
-# FIXME(#137532): replace `os_pipe` with `anonymous_pipe` once it stabilizes and
-# reaches beta.
-os_pipe = "1.2.1"
-
[lib]
crate-type = ["lib", "dylib"]
diff --git a/src/tools/run-make-support/src/artifact_names.rs b/src/tools/run-make-support/src/artifact_names.rs
index 8968f83..b0d588d 100644
--- a/src/tools/run-make-support/src/artifact_names.rs
+++ b/src/tools/run-make-support/src/artifact_names.rs
@@ -1,11 +1,11 @@
//! A collection of helpers to construct artifact names, such as names of dynamic or static
-//! librarys which are target-dependent.
+//! libraries which are target-dependent.
-// FIXME(jieyouxu): convert these to return `PathBuf`s instead of strings!
-
+use crate::target;
use crate::targets::is_msvc;
/// Construct the static library name based on the target.
+#[track_caller]
#[must_use]
pub fn static_lib_name(name: &str) -> String {
assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace");
@@ -14,15 +14,34 @@ pub fn static_lib_name(name: &str) -> String {
}
/// Construct the dynamic library name based on the target.
+#[track_caller]
#[must_use]
pub fn dynamic_lib_name(name: &str) -> String {
assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");
- format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION)
+ format!("{}{name}.{}", dynamic_lib_prefix(), dynamic_lib_extension())
}
-/// Construct the name of the import library for the dynamic library, exclusive to MSVC and
-/// accepted by link.exe.
+fn dynamic_lib_prefix() -> &'static str {
+ if target().contains("windows") { "" } else { "lib" }
+}
+
+/// Construct the dynamic library extension based on the target.
+#[must_use]
+pub fn dynamic_lib_extension() -> &'static str {
+ let target = target();
+
+ if target.contains("apple") {
+ "dylib"
+ } else if target.contains("windows") {
+ "dll"
+ } else {
+ "so"
+ }
+}
+
+/// Construct the name of the import library for the dynamic library, exclusive to MSVC and accepted
+/// by link.exe.
#[track_caller]
#[must_use]
pub fn msvc_import_dynamic_lib_name(name: &str) -> String {
@@ -32,20 +51,28 @@ pub fn msvc_import_dynamic_lib_name(name: &str) -> String {
format!("{name}.dll.lib")
}
-/// Construct the dynamic library extension based on the target.
-#[must_use]
-pub fn dynamic_lib_extension() -> &'static str {
- std::env::consts::DLL_EXTENSION
-}
-
/// Construct the name of a rust library (rlib).
+#[track_caller]
#[must_use]
pub fn rust_lib_name(name: &str) -> String {
format!("lib{name}.rlib")
}
/// Construct the binary (executable) name based on the target.
+#[track_caller]
#[must_use]
pub fn bin_name(name: &str) -> String {
- format!("{name}{}", std::env::consts::EXE_SUFFIX)
+ let target = target();
+
+ if target.contains("windows") {
+ format!("{name}.exe")
+ } else if target.contains("uefi") {
+ format!("{name}.efi")
+ } else if target.contains("wasm") {
+ format!("{name}.wasm")
+ } else if target.contains("nvptx") {
+ format!("{name}.ptx")
+ } else {
+ name.to_string()
+ }
}
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index c75d500..f37b38a 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -41,8 +41,6 @@ pub mod rfs {
pub use gimli;
pub use libc;
pub use object;
-// FIXME(#137532): replace with std `anonymous_pipe` once it stabilizes and reaches beta.
-pub use os_pipe;
pub use regex;
pub use serde_json;
pub use similar;
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 745a809..2dbb3f5 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -902,9 +902,9 @@
[[package]]
name = "libc"
-version = "0.2.169"
+version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libloading"
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
index 0a7a7d1..706d044 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
@@ -3795,35 +3795,6 @@ fn main() {
deny_since: None,
},
Lint {
- label: "cfg_boolean_literals",
- description: r##"# `cfg_boolean_literals`
-
-The tracking issue for this feature is: [#131204]
-
-[#131204]: https://github.com/rust-lang/rust/issues/131204
-
-------------------------
-
-The `cfg_boolean_literals` feature makes it possible to use the `true`/`false`
-literal as cfg predicate. They always evaluate to true/false respectively.
-
-## Examples
-
-```rust
-#![feature(cfg_boolean_literals)]
-
-#[cfg(true)]
-const A: i32 = 5;
-
-#[cfg(all(false))]
-const A: i32 = 58 * 89;
-```
-"##,
- default_severity: Severity::Allow,
- warn_since: None,
- deny_since: None,
- },
- Lint {
label: "cfg_eval",
description: r##"# `cfg_eval`
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 59293ee..80f6d85 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -11,7 +11,7 @@
use intern::Symbol;
use proc_macro::bridge::{self, server};
-use span::{FileId, Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
+use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
use tt::{TextRange, TextSize};
use crate::server_impl::{literal_kind_to_internal, token_stream::TokenStreamBuilder, TopSubtree};
@@ -27,10 +27,6 @@ mod tt {
type TokenStream = crate::server_impl::TokenStream<Span>;
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub struct SourceFile {
- file_id: FileId,
-}
pub struct FreeFunctions;
pub struct RaSpanServer {
@@ -46,7 +42,6 @@ pub struct RaSpanServer {
impl server::Types for RaSpanServer {
type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream;
- type SourceFile = SourceFile;
type Span = Span;
type Symbol = Symbol;
}
@@ -245,25 +240,17 @@ fn into_trees(
}
}
-impl server::SourceFile for RaSpanServer {
- fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
- file1 == file2
- }
- fn path(&mut self, _file: &Self::SourceFile) -> String {
- // FIXME
- String::new()
- }
- fn is_real(&mut self, _file: &Self::SourceFile) -> bool {
- true
- }
-}
-
impl server::Span for RaSpanServer {
fn debug(&mut self, span: Self::Span) -> String {
format!("{:?}", span)
}
- fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
- SourceFile { file_id: span.anchor.file_id.file_id() }
+ fn file(&mut self, _: Self::Span) -> String {
+ // FIXME
+ String::new()
+ }
+ fn local_file(&mut self, _: Self::Span) -> Option<String> {
+ // FIXME
+ None
}
fn save_span(&mut self, _span: Self::Span) -> usize {
// FIXME, quote is incompatible with third-party tools
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
index 409cf3c..4d7c7c4 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -24,8 +24,6 @@ mod tt {
type Span = tt::TokenId;
type TokenStream = crate::server_impl::TokenStream<Span>;
-#[derive(Clone)]
-pub struct SourceFile;
pub struct FreeFunctions;
pub struct TokenIdServer {
@@ -37,7 +35,6 @@ pub struct TokenIdServer {
impl server::Types for TokenIdServer {
type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream;
- type SourceFile = SourceFile;
type Span = Span;
type Symbol = Symbol;
}
@@ -223,24 +220,15 @@ fn into_trees(
}
}
-impl server::SourceFile for TokenIdServer {
- fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool {
- true
- }
- fn path(&mut self, _file: &Self::SourceFile) -> String {
- String::new()
- }
- fn is_real(&mut self, _file: &Self::SourceFile) -> bool {
- true
- }
-}
-
impl server::Span for TokenIdServer {
fn debug(&mut self, span: Self::Span) -> String {
format!("{:?}", span.0)
}
- fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
- SourceFile {}
+ fn file(&mut self, _span: Self::Span) -> String {
+ String::new()
+ }
+ fn local_file(&mut self, _span: Self::Span) -> Option<String> {
+ None
}
fn save_span(&mut self, _span: Self::Span) -> usize {
0
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
index 15de88e..4bd365b 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
@@ -97,6 +97,7 @@ fn test_fn_like_macro_clone_raw_ident() {
}
#[test]
+#[cfg(not(bootstrap))]
fn test_fn_like_fn_like_span_join() {
assert_expand(
"fn_like_span_join",
@@ -111,6 +112,7 @@ fn test_fn_like_fn_like_span_join() {
}
#[test]
+#[cfg(not(bootstrap))]
fn test_fn_like_fn_like_span_ops() {
assert_expand(
"fn_like_span_ops",
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 09bbbd6..c14372d 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -951,6 +951,7 @@
"once_cell",
"pathdiff",
"pulldown-cmark 0.10.3",
+ "railroad",
"regex",
"semver",
"serde_json",
@@ -981,9 +982,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.8.7"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
@@ -1301,6 +1302,15 @@
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
+name = "railroad"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ecedffc46c1b2cb04f4b80e094eae6b3f3f470a9635f1f396dd5206428f6b58"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/rustdoc-gui-test/Cargo.toml b/src/tools/rustdoc-gui-test/Cargo.toml
index f7384a9..8d958ac 100644
--- a/src/tools/rustdoc-gui-test/Cargo.toml
+++ b/src/tools/rustdoc-gui-test/Cargo.toml
@@ -5,6 +5,7 @@
[dependencies]
build_helper = { path = "../../build_helper" }
+camino = "1"
compiletest = { path = "../compiletest" }
getopts = "0.2"
walkdir = "2"
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
index f1c6e13..addb0af 100644
--- a/src/tools/rustdoc-gui-test/src/main.rs
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -118,7 +118,11 @@ fn main() -> Result<(), ()> {
..Default::default()
};
- let test_props = TestProps::from_file(&librs, None, &compiletest_c);
+ let test_props = TestProps::from_file(
+ &camino::Utf8PathBuf::try_from(librs).unwrap(),
+ None,
+ &compiletest_c,
+ );
if !test_props.compile_flags.is_empty() {
cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" "));
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index ddf3d2c..1e16aac 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -858,18 +858,18 @@ fn add_repeat(
};
self.result.push(ParsedMacroArg {
- kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()),
+ kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok),
});
Some(())
}
- fn update_buffer(&mut self, t: &Token) {
+ fn update_buffer(&mut self, t: Token) {
if self.buf.is_empty() {
- self.start_tok = t.clone();
+ self.start_tok = t;
} else {
let needs_space = match next_space(&self.last_tok.kind) {
- SpaceState::Ident => ident_like(t),
- SpaceState::Punctuation => !ident_like(t),
+ SpaceState::Ident => ident_like(&t),
+ SpaceState::Punctuation => !ident_like(&t),
SpaceState::Always => true,
SpaceState::Never => false,
};
@@ -878,7 +878,7 @@ fn update_buffer(&mut self, t: &Token) {
}
}
- self.buf.push_str(&pprust::token_to_string(t));
+ self.buf.push_str(&pprust::token_to_string(&t));
}
fn need_space_prefix(&self) -> bool {
@@ -937,7 +937,7 @@ fn parse(mut self, tokens: TokenStream) -> Option<Vec<ParsedMacroArg>> {
) if self.is_meta_var => {
self.add_meta_variable(&mut iter)?;
}
- TokenTree::Token(ref t, _) => self.update_buffer(t),
+ &TokenTree::Token(t, _) => self.update_buffer(t),
&TokenTree::Delimited(_dspan, _spacing, delimited, ref tts) => {
if !self.buf.is_empty() {
if next_space(&self.last_tok.kind) == SpaceState::Always {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 1a57d2b..dd7f9c6 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -132,15 +132,16 @@
("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),
("foldhash", "Zlib"),
("im-rc", "MPL-2.0+"),
+ ("libz-rs-sys", "Zlib"),
("normalize-line-endings", "Apache-2.0"),
("openssl", "Apache-2.0"),
("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
- ("sha1_smol", "BSD-3-Clause"),
("similar", "Apache-2.0"),
("sized-chunks", "MPL-2.0+"),
("subtle", "BSD-3-Clause"),
("supports-hyperlinks", "Apache-2.0"),
("unicode-bom", "Apache-2.0"),
+ ("zlib-rs", "Zlib"),
// tidy-alphabetical-end
];
@@ -259,7 +260,6 @@
"constant_time_eq",
"cpufeatures",
"crc32fast",
- "crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-utils",
@@ -269,7 +269,6 @@
"darling_core",
"darling_macro",
"datafrog",
- "deranged",
"derive-where",
"derive_setters",
"digest",
@@ -295,7 +294,6 @@
"gimli",
"gsgdt",
"hashbrown",
- "hermit-abi",
"icu_list",
"icu_list_data",
"icu_locid",
@@ -310,6 +308,8 @@
"intl_pluralrules",
"itertools",
"itoa",
+ "jiff",
+ "jiff-static",
"jobserver",
"lazy_static",
"leb128",
@@ -327,8 +327,6 @@
"miniz_oxide",
"nix",
"nu-ansi-term",
- "num-conv",
- "num_cpus",
"object",
"odht",
"once_cell",
@@ -340,7 +338,7 @@
"pin-project-lite",
"polonius-engine",
"portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std
- "powerfmt",
+ "portable-atomic-util",
"ppv-lite86",
"proc-macro-hack",
"proc-macro2",
@@ -361,7 +359,6 @@
"rustc-demangle",
"rustc-hash",
"rustc-literal-escaper",
- "rustc-rayon",
"rustc-rayon-core",
"rustc-stable-hash",
"rustc_apfloat",
@@ -394,9 +391,6 @@
"thorin-dwp",
"thread_local",
"tikv-jemalloc-sys",
- "time",
- "time-core",
- "time-macros",
"tinystr",
"tinyvec",
"tinyvec_macros",
@@ -686,8 +680,10 @@ fn check_proc_macro_dep_list(root: &Path, cargo: &Path, bless: bool, bad: &mut b
pub fn has_missing_submodule(root: &Path, submodules: &[&str]) -> bool {
!CiEnv::is_ci()
&& submodules.iter().any(|submodule| {
+ let path = root.join(submodule);
+ !path.exists()
// If the directory is empty, we can consider it as an uninitialized submodule.
- read_dir(root.join(submodule)).unwrap().next().is_none()
+ || read_dir(path).unwrap().next().is_none()
})
}
diff --git a/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs b/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs
index faff6e7..257608f 100644
--- a/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs
+++ b/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -g --crate-type=rlib -Zdwarf-version=4
+//@ compile-flags: -g --crate-type=rlib -Cdwarf-version=4
pub fn check_is_even(number: &u64) -> bool {
number % 2 == 0
diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs
index 7436e24..f7d0775 100644
--- a/tests/assembly/cstring-merging.rs
+++ b/tests/assembly/cstring-merging.rs
@@ -1,17 +1,20 @@
+// MIPS assembler uses the label prefix `$anon.` for local anonymous variables
+// other architectures (including ARM and x86-64) use the prefix `.Lanon.`
//@ only-linux
//@ assembly-output: emit-asm
-//@ compile-flags: --crate-type=lib -Copt-level=3 --edition 2024
+//@ compile-flags: --crate-type=lib -Copt-level=3
+//@ edition: 2024
use std::ffi::CStr;
-// CHECK: .section .rodata.str1.1,"aMS"
-// CHECK: .Lanon.{{.+}}:
+// CHECK: .section .rodata.str1.{{[12]}},"aMS"
+// CHECK: {{(\.L|\$)}}anon.{{.+}}:
// CHECK-NEXT: .asciz "foo"
#[unsafe(no_mangle)]
static CSTR: &[u8; 4] = b"foo\0";
// CHECK-NOT: .section
-// CHECK: .Lanon.{{.+}}:
+// CHECK: {{(\.L|\$)}}anon.{{.+}}:
// CHECK-NEXT: .asciz "bar"
#[unsafe(no_mangle)]
pub fn cstr() -> &'static CStr {
@@ -19,7 +22,7 @@ pub fn cstr() -> &'static CStr {
}
// CHECK-NOT: .section
-// CHECK: .Lanon.{{.+}}:
+// CHECK: {{(\.L|\$)}}anon.{{.+}}:
// CHECK-NEXT: .asciz "baz"
#[unsafe(no_mangle)]
pub fn manual_cstr() -> &'static str {
diff --git a/tests/assembly/dwarf-mixed-versions-lto.rs b/tests/assembly/dwarf-mixed-versions-lto.rs
index f1fc081..9910a6e 100644
--- a/tests/assembly/dwarf-mixed-versions-lto.rs
+++ b/tests/assembly/dwarf-mixed-versions-lto.rs
@@ -4,7 +4,7 @@
//@ only-linux
//@ aux-build:dwarf-mixed-versions-lto-aux.rs
-//@ compile-flags: -C lto -g -Zdwarf-version=5
+//@ compile-flags: -C lto -g -Cdwarf-version=5
//@ assembly-output: emit-asm
//@ no-prefer-dynamic
diff --git a/tests/assembly/dwarf4.rs b/tests/assembly/dwarf4.rs
index 6013adf..03a3886 100644
--- a/tests/assembly/dwarf4.rs
+++ b/tests/assembly/dwarf4.rs
@@ -1,7 +1,7 @@
-// Makes sure that `-Z dwarf-version=4` causes `rustc` to emit DWARF version 4.
+// Makes sure that `-C dwarf-version=4` causes `rustc` to emit DWARF version 4.
//@ assembly-output: emit-asm
//@ add-core-stubs
-//@ compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=4 -Copt-level=0
+//@ compile-flags: -g --target x86_64-unknown-linux-gnu -C dwarf-version=4 -Copt-level=0
//@ needs-llvm-components: x86
#![feature(no_core, lang_items)]
diff --git a/tests/assembly/dwarf5.rs b/tests/assembly/dwarf5.rs
index 9cd596e..9bd92cc 100644
--- a/tests/assembly/dwarf5.rs
+++ b/tests/assembly/dwarf5.rs
@@ -1,7 +1,7 @@
-// Makes sure that `-Z dwarf-version=5` causes `rustc` to emit DWARF version 5.
+// Makes sure that `-C dwarf-version=5` causes `rustc` to emit DWARF version 5.
//@ add-core-stubs
//@ assembly-output: emit-asm
-//@ compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 -Copt-level=0
+//@ compile-flags: -g --target x86_64-unknown-linux-gnu -C dwarf-version=5 -Copt-level=0
//@ needs-llvm-components: x86
#![feature(no_core, lang_items)]
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index 8f2fef0..3255591 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -571,6 +571,9 @@
//@ revisions: x86_64_linux_android
//@ [x86_64_linux_android] compile-flags: --target x86_64-linux-android
//@ [x86_64_linux_android] needs-llvm-components: x86
+//@ revisions: x86_64_lynx_lynxos178
+//@ [x86_64_lynx_lynxos178] compile-flags: --target x86_64-lynx-lynxos178
+//@ [x86_64_lynx_lynxos178] needs-llvm-components: x86
//@ revisions: x86_64_pc_nto_qnx710
//@ [x86_64_pc_nto_qnx710] compile-flags: --target x86_64-pc-nto-qnx710
//@ [x86_64_pc_nto_qnx710] needs-llvm-components: x86
diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs
index 97f23cc..660d8cd 100644
--- a/tests/codegen/align-fn.rs
+++ b/tests/codegen/align-fn.rs
@@ -47,3 +47,22 @@ impl T for () {}
pub fn foo() {
().trait_method();
}
+
+// CHECK-LABEL: align_specified_twice_1
+// CHECK-SAME: align 64
+#[no_mangle]
+#[repr(align(32), align(64))]
+pub fn align_specified_twice_1() {}
+
+// CHECK-LABEL: align_specified_twice_2
+// CHECK-SAME: align 128
+#[no_mangle]
+#[repr(align(128), align(32))]
+pub fn align_specified_twice_2() {}
+
+// CHECK-LABEL: align_specified_twice_3
+// CHECK-SAME: align 256
+#[no_mangle]
+#[repr(align(32))]
+#[repr(align(256))]
+pub fn align_specified_twice_3() {}
diff --git a/tests/codegen/array-cmp.rs b/tests/codegen/array-cmp.rs
index 2565a38..0d33765 100644
--- a/tests/codegen/array-cmp.rs
+++ b/tests/codegen/array-cmp.rs
@@ -1,6 +1,7 @@
// Ensure the asm for array comparisons is properly optimized.
//@ compile-flags: -C opt-level=2
+//@ needs-deterministic-layouts (checks depend on tuple layout)
#![crate_type = "lib"]
@@ -17,3 +18,57 @@ pub fn compare() -> bool {
[0x00, 0x00, 0x48, 0x41]
}
}
+
+// CHECK-LABEL: @array_of_tuple_le
+#[no_mangle]
+pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool {
+ // Ensure that, after all the optimizations have run, the happy path just checks
+ // `eq` on each corresponding pair and moves onto the next one if it is.
+ // Then there's a dedup'd comparison for the place that's different.
+ // (As opposed to, say, running a full `[su]cmp` as part of checking equality.)
+
+ // This is written quite specifically because different library code was triggering
+ // <https://github.com/llvm/llvm-project/issues/132678> along the way, so this
+ // has enough checks to make sure that's not happening. It doesn't need to be
+ // *exactly* this IR, but be careful if you ever need to update these checks.
+
+ // CHECK: start:
+ // CHECK: %[[A00:.+]] = load i16, ptr %a
+ // CHECK: %[[B00:.+]] = load i16, ptr %b
+ // CHECK-NOT: cmp
+ // CHECK: %[[EQ00:.+]] = icmp eq i16 %[[A00]], %[[B00]]
+ // CHECK-NEXT: br i1 %[[EQ00]], label %[[L01:.+]], label %[[EXIT_S:.+]]
+
+ // CHECK: [[L01]]:
+ // CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2
+ // CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2
+ // CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]]
+ // CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]]
+ // CHECK-NOT: cmp
+ // CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]]
+ // CHECK-NEXT: br i1 %[[EQ01]], label %[[L10:.+]], label %[[EXIT_U:.+]]
+
+ // CHECK: [[L10]]:
+ // CHECK: %[[PA10:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 4
+ // CHECK: %[[PB10:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 4
+ // CHECK: %[[A10:.+]] = load i16, ptr %[[PA10]]
+ // CHECK: %[[B10:.+]] = load i16, ptr %[[PB10]]
+ // CHECK-NOT: cmp
+ // CHECK: %[[EQ10:.+]] = icmp eq i16 %[[A10]], %[[B10]]
+ // CHECK-NEXT: br i1 %[[EQ10]], label %[[L11:.+]], label %[[EXIT_S]]
+
+ // CHECK: [[L11]]:
+ // CHECK: %[[PA11:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 6
+ // CHECK: %[[PB11:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 6
+ // CHECK: %[[A11:.+]] = load i16, ptr %[[PA11]]
+ // CHECK: %[[B11:.+]] = load i16, ptr %[[PB11]]
+ // CHECK-NOT: cmp
+ // CHECK: %[[EQ11:.+]] = icmp eq i16 %[[A11]], %[[B11]]
+ // CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U]]
+
+ // CHECK: [[DONE]]:
+ // CHECK: %[[RET:.+]] = phi i1 [ %{{.+}}, %[[EXIT_S]] ], [ %{{.+}}, %[[EXIT_U]] ], [ true, %[[L11]] ]
+ // CHECK: ret i1 %[[RET]]
+
+ a <= b
+}
diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs
index 2d67e02..b5b369e 100644
--- a/tests/codegen/async-closure-debug.rs
+++ b/tests/codegen/async-closure-debug.rs
@@ -1,6 +1,7 @@
// Just make sure that async closures don't ICE.
//
-//@ compile-flags: -C debuginfo=2 --edition=2018
+//@ compile-flags: -C debuginfo=2
+//@ edition: 2018
//@ ignore-msvc
// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "async_closure_test"
diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs
index ab13d45..50860c9 100644
--- a/tests/codegen/async-fn-debug-awaitee-field.rs
+++ b/tests/codegen/async-fn-debug-awaitee-field.rs
@@ -7,7 +7,8 @@
//@[MSVC] only-msvc
//@[NONMSVC] ignore-msvc
-//@ compile-flags: -C debuginfo=2 --edition=2018 -Copt-level=0
+//@ compile-flags: -C debuginfo=2 -Copt-level=0
+//@ edition: 2018
#![crate_type = "lib"]
diff --git a/tests/codegen/async-fn-debug-msvc.rs b/tests/codegen/async-fn-debug-msvc.rs
index 7c69504..e0c6011 100644
--- a/tests/codegen/async-fn-debug-msvc.rs
+++ b/tests/codegen/async-fn-debug-msvc.rs
@@ -4,7 +4,8 @@
// - Other fields are not marked artificial
//
//
-//@ compile-flags: -C debuginfo=2 --edition=2018
+//@ compile-flags: -C debuginfo=2
+//@ edition: 2018
//@ only-msvc
async fn foo() {}
@@ -19,23 +20,23 @@ async fn async_fn_test() {
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_msvc::async_fn_test::async_fn_env$0>",
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
// For brevity, we only check the struct name and members of the last variant.
-// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
+// CHECK-SAME: file: [[FILE:![0-9]*]], line: 12,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]],
-// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-SAME: file: [[FILE]], line: 16,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]],
-// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-SAME: file: [[FILE]], line: 16,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]],
-// CHECK-SAME: file: [[FILE]], line: 12,
+// CHECK-SAME: file: [[FILE]], line: 13,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
-// CHECK-SAME: file: [[FILE]], line: 14,
+// CHECK-SAME: file: [[FILE]], line: 15,
// CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]]
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
diff --git a/tests/codegen/async-fn-debug.rs b/tests/codegen/async-fn-debug.rs
index 7be4ad4..ed704c7 100644
--- a/tests/codegen/async-fn-debug.rs
+++ b/tests/codegen/async-fn-debug.rs
@@ -4,7 +4,8 @@
// - Other fields are not marked artificial
//
//
-//@ compile-flags: -C debuginfo=2 --edition=2018
+//@ compile-flags: -C debuginfo=2
+//@ edition: 2018
//@ ignore-msvc
async fn foo() {}
@@ -22,26 +23,26 @@ async fn async_fn_test() {
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
+// CHECK-SAME: file: [[FILE:![0-9]*]], line: 12,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]],
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-SAME: file: [[FILE]], line: 16,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 15,
+// CHECK-SAME: file: [[FILE]], line: 16,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 12,
+// CHECK-SAME: file: [[FILE]], line: 13,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 14,
+// CHECK-SAME: file: [[FILE]], line: 15,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
diff --git a/tests/codegen/autodiffv2.rs b/tests/codegen/autodiffv2.rs
new file mode 100644
index 0000000..a40d19d
--- /dev/null
+++ b/tests/codegen/autodiffv2.rs
@@ -0,0 +1,113 @@
+//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat
+//@ no-prefer-dynamic
+//@ needs-enzyme
+//
+// In Enzyme, we test against a large range of LLVM versions (5+) and don't have overly many
+// breakages. One benefit is that we match the IR generated by Enzyme only after running it
+// through LLVM's O3 pipeline, which will remove most of the noise.
+// However, our integration test could also be affected by changes in how rustc lowers MIR into
+// LLVM-IR, which could cause additional noise and thus breakages. If that's the case, we should
+// reduce this test to only match the first lines and the ret instructions.
+//
+// The function tested here has 4 inputs and 5 outputs, so we could either call forward-mode
+// autodiff 4 times, or reverse mode 5 times. Since a forward-mode call is usually faster than
+// reverse mode, we prefer it here. This file also tests a new optimization (batch mode), which
+// allows us to call forward-mode autodiff only once, and get all 5 outputs in a single call.
+//
+// We support 2 different batch modes. `d_square2` has the same interface as scalar forward-mode,
+// but each shadow argument is `width` times larger (thus 16 and 20 elements here).
+// `d_square3` instead takes `width` (4) shadow arguments, which are all the same size as the
+// original function arguments.
+//
+// FIXME(autodiff): We currently can't test `d_square1` and `d_square3` in the same file, since they
+// generate the same dummy functions which get merged by LLVM, breaking pieces of our pipeline which
+// try to rewrite the dummy functions later. We should consider to change to pure declarations both
+// in our frontend and in the llvm backend to avoid these issues.
+
+#![feature(autodiff)]
+
+use std::autodiff::autodiff;
+
+#[no_mangle]
+//#[autodiff(d_square1, Forward, Dual, Dual)]
+#[autodiff(d_square2, Forward, 4, Dualv, Dualv)]
+#[autodiff(d_square3, Forward, 4, Dual, Dual)]
+fn square(x: &[f32], y: &mut [f32]) {
+ assert!(x.len() >= 4);
+ assert!(y.len() >= 5);
+ y[0] = 4.3 * x[0] + 1.2 * x[1] + 3.4 * x[2] + 2.1 * x[3];
+ y[1] = 2.3 * x[0] + 4.5 * x[1] + 1.7 * x[2] + 6.4 * x[3];
+ y[2] = 1.1 * x[0] + 3.3 * x[1] + 2.5 * x[2] + 4.7 * x[3];
+ y[3] = 5.2 * x[0] + 1.4 * x[1] + 2.6 * x[2] + 3.8 * x[3];
+ y[4] = 1.0 * x[0] + 2.0 * x[1] + 3.0 * x[2] + 4.0 * x[3];
+}
+
+fn main() {
+ let x1 = std::hint::black_box(vec![0.0, 1.0, 2.0, 3.0]);
+
+ let dx1 = std::hint::black_box(vec![1.0; 12]);
+
+ let z1 = std::hint::black_box(vec![1.0, 0.0, 0.0, 0.0]);
+ let z2 = std::hint::black_box(vec![0.0, 1.0, 0.0, 0.0]);
+ let z3 = std::hint::black_box(vec![0.0, 0.0, 1.0, 0.0]);
+ let z4 = std::hint::black_box(vec![0.0, 0.0, 0.0, 1.0]);
+
+ let z5 = std::hint::black_box(vec![
+ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
+ ]);
+
+ let mut y1 = std::hint::black_box(vec![0.0; 5]);
+ let mut y2 = std::hint::black_box(vec![0.0; 5]);
+ let mut y3 = std::hint::black_box(vec![0.0; 5]);
+ let mut y4 = std::hint::black_box(vec![0.0; 5]);
+
+ let mut y5 = std::hint::black_box(vec![0.0; 5]);
+
+ let mut y6 = std::hint::black_box(vec![0.0; 5]);
+
+ let mut dy1_1 = std::hint::black_box(vec![0.0; 5]);
+ let mut dy1_2 = std::hint::black_box(vec![0.0; 5]);
+ let mut dy1_3 = std::hint::black_box(vec![0.0; 5]);
+ let mut dy1_4 = std::hint::black_box(vec![0.0; 5]);
+
+ let mut dy2 = std::hint::black_box(vec![0.0; 20]);
+
+ let mut dy3_1 = std::hint::black_box(vec![0.0; 5]);
+ let mut dy3_2 = std::hint::black_box(vec![0.0; 5]);
+ let mut dy3_3 = std::hint::black_box(vec![0.0; 5]);
+ let mut dy3_4 = std::hint::black_box(vec![0.0; 5]);
+
+ // scalar.
+ //d_square1(&x1, &z1, &mut y1, &mut dy1_1);
+ //d_square1(&x1, &z2, &mut y2, &mut dy1_2);
+ //d_square1(&x1, &z3, &mut y3, &mut dy1_3);
+ //d_square1(&x1, &z4, &mut y4, &mut dy1_4);
+
+ // assert y1 == y2 == y3 == y4
+ //for i in 0..5 {
+ // assert_eq!(y1[i], y2[i]);
+ // assert_eq!(y1[i], y3[i]);
+ // assert_eq!(y1[i], y4[i]);
+ //}
+
+ // batch mode A)
+ d_square2(&x1, &z5, &mut y5, &mut dy2);
+
+ // assert y1 == y2 == y3 == y4 == y5
+ //for i in 0..5 {
+ // assert_eq!(y1[i], y5[i]);
+ //}
+
+ // batch mode B)
+ d_square3(&x1, &z1, &z2, &z3, &z4, &mut y6, &mut dy3_1, &mut dy3_2, &mut dy3_3, &mut dy3_4);
+ for i in 0..5 {
+ assert_eq!(y5[i], y6[i]);
+ }
+
+ for i in 0..5 {
+ assert_eq!(dy2[0..5][i], dy3_1[i]);
+ assert_eq!(dy2[5..10][i], dy3_2[i]);
+ assert_eq!(dy2[10..15][i], dy3_3[i]);
+ assert_eq!(dy2[15..20][i], dy3_4[i]);
+ }
+}
diff --git a/tests/codegen/cffi/ffi-const.rs b/tests/codegen/cffi/ffi-const.rs
index 6c90902..3ea9d51 100644
--- a/tests/codegen/cffi/ffi-const.rs
+++ b/tests/codegen/cffi/ffi-const.rs
@@ -10,6 +10,6 @@ pub fn bar() {
// CHECK-LABEL: declare{{.*}}void @foo()
// CHECK-SAME: [[ATTRS:#[0-9]+]]
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(none){{.*}} }
- #[ffi_const]
+ #[unsafe(ffi_const)]
pub fn foo();
}
diff --git a/tests/codegen/cffi/ffi-pure.rs b/tests/codegen/cffi/ffi-pure.rs
index 2c5d5f5..a61e80e 100644
--- a/tests/codegen/cffi/ffi-pure.rs
+++ b/tests/codegen/cffi/ffi-pure.rs
@@ -10,6 +10,6 @@ pub fn bar() {
// CHECK-LABEL: declare{{.*}}void @foo()
// CHECK-SAME: [[ATTRS:#[0-9]+]]
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(read){{.*}} }
- #[ffi_pure]
+ #[unsafe(ffi_pure)]
pub fn foo();
}
diff --git a/tests/codegen/coroutine-debug.rs b/tests/codegen/coroutine-debug.rs
index d00667a..ff62e97 100644
--- a/tests/codegen/coroutine-debug.rs
+++ b/tests/codegen/coroutine-debug.rs
@@ -4,7 +4,8 @@
// - Other fields are not marked artificial
//
//
-//@ compile-flags: -C debuginfo=2 --edition=2018
+//@ compile-flags: -C debuginfo=2
+//@ edition: 2018
//@ ignore-msvc
#![feature(coroutines, coroutine_trait)]
@@ -27,26 +28,26 @@ fn coroutine_test() -> impl Coroutine<Yield = i32, Return = ()> {
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE:![0-9]*]], line: 15,
+// CHECK-SAME: file: [[FILE:![0-9]*]], line: 16,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]],
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 19,
+// CHECK-SAME: file: [[FILE]], line: 20,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 19,
+// CHECK-SAME: file: [[FILE]], line: 20,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 16,
+// CHECK-SAME: file: [[FILE]], line: 17,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]],
-// CHECK-SAME: file: [[FILE]], line: 18,
+// CHECK-SAME: file: [[FILE]], line: 19,
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
diff --git a/tests/codegen/debuginfo-generic-closure-env-names.rs b/tests/codegen/debuginfo-generic-closure-env-names.rs
index 6b314c9..64bc58e 100644
--- a/tests/codegen/debuginfo-generic-closure-env-names.rs
+++ b/tests/codegen/debuginfo-generic-closure-env-names.rs
@@ -18,7 +18,8 @@
// legacy mangling scheme rustc version and generic parameters are both hashed into a single part
// of the name, thus randomizing item order with respect to rustc version.
-//@ compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0
+//@ edition: 2021
// non_generic_closure()
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]],
diff --git a/tests/codegen/dont-shuffle-bswaps.rs b/tests/codegen/dont-shuffle-bswaps.rs
index e100474..c1dab2b 100644
--- a/tests/codegen/dont-shuffle-bswaps.rs
+++ b/tests/codegen/dont-shuffle-bswaps.rs
@@ -1,8 +1,11 @@
-//@ revisions: OPT2 OPT3
+//@ revisions: OPT2 OPT3 OPT3_S390X
//@[OPT2] compile-flags: -Copt-level=2
//@[OPT3] compile-flags: -C opt-level=3
// some targets don't do the opt we are looking for
//@[OPT3] only-64bit
+//@[OPT3] ignore-s390x
+//@[OPT3_S390X] compile-flags: -C opt-level=3 -C target-cpu=z13
+//@[OPT3_S390X] only-s390x
#![crate_type = "lib"]
#![no_std]
@@ -17,6 +20,10 @@
// OPT3-NEXT: call <8 x i16> @llvm.bswap
// OPT3-NEXT: store <8 x i16>
// OPT3-NEXT: ret void
+// OPT3_S390X: load <8 x i16>
+// OPT3_S390X-NEXT: call <8 x i16> @llvm.bswap
+// OPT3_S390X-NEXT: store <8 x i16>
+// OPT3_S390X-NEXT: ret void
#[no_mangle]
pub fn convert(value: [u16; 8]) -> [u8; 16] {
#[cfg(target_endian = "little")]
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
index 6e185cf..6da6ad1 100644
--- a/tests/codegen/enum/enum-match.rs
+++ b/tests/codegen/enum/enum-match.rs
@@ -15,7 +15,7 @@ pub enum Enum0 {
B,
}
-// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0(i8{{.+}}%0)
+// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0(i8{{.+}}%0)
// CHECK-NEXT: start:
// CHECK-NEXT: %[[IS_B:.+]] = icmp eq i8 %0, 2
// CHECK-NEXT: %[[TRUNC:.+]] = and i8 %0, 1
@@ -37,7 +37,7 @@ pub enum Enum1 {
C,
}
-// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1(i8{{.+}}%0)
+// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1(i8{{.+}}%0)
// CHECK-NEXT: start:
// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
@@ -98,7 +98,7 @@ pub enum Enum2 {
E,
}
-// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0)
+// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0)
// CHECK-NEXT: start:
// CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %0, 2
// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
@@ -121,7 +121,7 @@ pub fn match2(e: Enum2) -> u8 {
// And make sure it works even if the niched scalar is a pointer.
// (For example, that we don't try to `sub` on pointers.)
-// CHECK-LABEL: define noundef{{( range\(i16 -?[0-9]+, -?[0-9]+\))?}} i16 @match3(ptr{{.+}}%0)
+// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i16 -?[0-9]+, -?[0-9]+\))?}} i16 @match3(ptr{{.+}}%0)
// CHECK-NEXT: start:
// CHECK-NEXT: %[[IS_NULL:.+]] = icmp eq ptr %0, null
// CHECK-NEXT: br i1 %[[IS_NULL]]
@@ -145,7 +145,7 @@ pub enum MiddleNiche {
E,
}
-// CHECK-LABEL: define noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0)
+// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0)
// CHECK-NEXT: start:
// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5
@@ -449,7 +449,7 @@ pub enum HugeVariantIndex {
Possible259,
}
-// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0)
+// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0)
// CHECK-NEXT: start:
// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs
index 3756faf..c2297c5 100644
--- a/tests/codegen/infallible-unwrap-in-opt-z.rs
+++ b/tests/codegen/infallible-unwrap-in-opt-z.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: -C opt-level=z --edition=2021
+//@ compile-flags: -C opt-level=z
+//@ edition: 2021
#![crate_type = "lib"]
diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs
index 53a1791..c31419c 100644
--- a/tests/codegen/inline-function-args-debug-info.rs
+++ b/tests/codegen/inline-function-args-debug-info.rs
@@ -2,7 +2,8 @@
// gets inlined by MIR inlining. Without function argument indexes, `info args` in gdb won't show
// arguments and their values for the current function.
-//@ compile-flags: -Zinline-mir=yes -Cdebuginfo=2 --edition=2021
+//@ compile-flags: -Zinline-mir=yes -Cdebuginfo=2
+//@ edition: 2021
#![crate_type = "lib"]
@@ -14,9 +15,9 @@ pub fn outer_function(x: usize, y: usize) -> usize {
#[inline]
fn inner_function(aaaa: usize, bbbb: usize) -> usize {
// CHECK: !DILocalVariable(name: "aaaa", arg: 1
- // CHECK-SAME: line: 15
+ // CHECK-SAME: line: 16
// CHECK-NOT: !DILexicalBlock(
// CHECK: !DILocalVariable(name: "bbbb", arg: 2
- // CHECK-SAME: line: 15
+ // CHECK-SAME: line: 16
aaaa + bbbb
}
diff --git a/tests/codegen/intrinsic-no-unnamed-attr.rs b/tests/codegen/intrinsic-no-unnamed-attr.rs
index 35eb025..4bec579 100644
--- a/tests/codegen/intrinsic-no-unnamed-attr.rs
+++ b/tests/codegen/intrinsic-no-unnamed-attr.rs
@@ -1,9 +1,8 @@
//@ compile-flags: -C no-prepopulate-passes
-#![feature(intrinsics)]
+#![feature(core_intrinsics)]
-#[rustc_intrinsic]
-unsafe fn sqrtf32(x: f32) -> f32;
+use std::intrinsics::sqrtf32;
// CHECK: @llvm.sqrt.f32(float) #{{[0-9]*}}
diff --git a/tests/codegen/intrinsics/select_unpredictable.rs b/tests/codegen/intrinsics/select_unpredictable.rs
index 68a02c8..2db4ae1 100644
--- a/tests/codegen/intrinsics/select_unpredictable.rs
+++ b/tests/codegen/intrinsics/select_unpredictable.rs
@@ -46,21 +46,21 @@ pub fn test_zst(p: bool, a: (), b: ()) -> () {
pub fn test_int2(p: bool, a: u64, b: u64) -> u64 {
// CHECK-LABEL: define{{.*}} @test_int2
// CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable
- p.select_unpredictable(a, b)
+ core::hint::select_unpredictable(p, a, b)
}
#[no_mangle]
pub fn test_pair2(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) {
// CHECK-LABEL: define{{.*}} @test_pair2
// CHECK: select i1 %p, {{.*}}, !unpredictable
- p.select_unpredictable(a, b)
+ core::hint::select_unpredictable(p, a, b)
}
#[no_mangle]
pub fn test_struct2(p: bool, a: Large, b: Large) -> Large {
// CHECK-LABEL: define{{.*}} @test_struct2
// CHECK: select i1 %p, {{.*}}, !unpredictable
- p.select_unpredictable(a, b)
+ core::hint::select_unpredictable(p, a, b)
}
#[no_mangle]
@@ -68,5 +68,5 @@ pub fn test_zst2(p: bool, a: (), b: ()) -> () {
// CHECK-LABEL: define{{.*}} @test_zst2
// CHECK-NEXT: start:
// CHECK-NEXT: ret void
- p.select_unpredictable(a, b)
+ core::hint::select_unpredictable(p, a, b)
}
diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs
index 7fb850c..8d15921 100644
--- a/tests/codegen/issues/issue-101082.rs
+++ b/tests/codegen/issues/issue-101082.rs
@@ -1,9 +1,18 @@
//@ compile-flags: -Copt-level=3
-//@ revisions: host x86-64-v3
+//@ revisions: host x86-64 x86-64-v3
//@ min-llvm-version: 20
-// This particular CPU regressed in #131563
+//@[host] ignore-x86_64
+
+// Set the base cpu explicitly, in case the default has been changed.
+//@[x86-64] only-x86_64
+//@[x86-64] compile-flags: -Ctarget-cpu=x86-64
+
+// FIXME(cuviper) x86-64-v3 in particular regressed in #131563, and the workaround
+// at the time still sometimes fails, so only verify it for the power-of-two size
+// - https://github.com/llvm/llvm-project/issues/134735
//@[x86-64-v3] only-x86_64
+//@[x86-64-v3] min-llvm-version: 21
//@[x86-64-v3] compile-flags: -Ctarget-cpu=x86-64-v3
#![crate_type = "lib"]
@@ -19,3 +28,15 @@ pub fn test() -> usize {
}
acc
}
+
+#[no_mangle]
+pub fn test_eight() -> usize {
+ // CHECK-LABEL: @test_eight(
+ // CHECK: ret {{i64|i32}} 220
+ let values = [23, 16, 54, 3, 60, 9, 13, 42];
+ let mut acc = 0;
+ for item in values {
+ acc += item;
+ }
+ acc
+}
diff --git a/tests/codegen/issues/issue-119422.rs b/tests/codegen/issues/issue-119422.rs
index e1a082c..17ae716 100644
--- a/tests/codegen/issues/issue-119422.rs
+++ b/tests/codegen/issues/issue-119422.rs
@@ -1,7 +1,8 @@
//! This test checks that compiler don't generate useless compares to zeros
//! for `NonZero` integer types.
//!
-//@ compile-flags: -Copt-level=3 --edition=2021 -Zmerge-functions=disabled
+//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
+//@ edition: 2021
//@ only-64bit (because the LLVM type of i64 for usize shows up)
#![crate_type = "lib"]
diff --git a/tests/codegen/remap_path_prefix/aux_mod.rs b/tests/codegen/remap_path_prefix/aux_mod.rs
index c37e91c..3217e9e 100644
--- a/tests/codegen/remap_path_prefix/aux_mod.rs
+++ b/tests/codegen/remap_path_prefix/aux_mod.rs
@@ -1,4 +1,4 @@
-//@ ignore-test: this is not a test
+//@ ignore-auxiliary (used by `./main.rs`)
#[inline]
pub fn some_aux_mod_function() -> i32 {
diff --git a/tests/codegen/simd/simd-wide-sum.rs b/tests/codegen/simd/simd-wide-sum.rs
index fb9b618..95117b2 100644
--- a/tests/codegen/simd/simd-wide-sum.rs
+++ b/tests/codegen/simd/simd-wide-sum.rs
@@ -1,5 +1,6 @@
//@ revisions: llvm mir-opt3
-//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021
+//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled
+//@ edition: 2021
//@ only-x86_64
//@ [mir-opt3]compile-flags: -Zmir-opt-level=3
//@ [mir-opt3]build-pass
diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs
index 9f68d74..398c9a5 100644
--- a/tests/codegen/try_question_mark_nop.rs
+++ b/tests/codegen/try_question_mark_nop.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled --edition=2021
+//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
+//@ edition: 2021
//@ only-x86_64
//@ revisions: NINETEEN TWENTY
//@[NINETEEN] exact-llvm-major-version: 19
diff --git a/tests/crashes/100618.rs b/tests/crashes/100618.rs
deleted file mode 100644
index 911c409..0000000
--- a/tests/crashes/100618.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #100618
-//@ compile-flags: -Cdebuginfo=2
-
-//@ only-x86_64
-enum Foo<T: 'static> {
- Value(T),
- Recursive(&'static Foo<Option<T>>),
-}
-
-fn main() {
- let _x = Foo::Value(());
-}
diff --git a/tests/crashes/115994.rs b/tests/crashes/115994.rs
deleted file mode 100644
index 23d1507..0000000
--- a/tests/crashes/115994.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ known-bug: #115994
-//@ compile-flags: -Cdebuginfo=2 --crate-type lib
-
-// To prevent "overflow while adding drop-check rules".
-use std::mem::ManuallyDrop;
-
-pub enum Foo<U> {
- Leaf(U),
-
- Branch(BoxedFoo<BoxedFoo<U>>),
-}
-
-pub type BoxedFoo<U> = ManuallyDrop<Box<Foo<U>>>;
-
-pub fn test() -> Foo<usize> {
- todo!()
-}
diff --git a/tests/crashes/119095.rs b/tests/crashes/119095.rs
index 28742e0..9b6c976 100644
--- a/tests/crashes/119095.rs
+++ b/tests/crashes/119095.rs
@@ -1,5 +1,5 @@
//@ known-bug: #119095
-//@ compile-flags: --edition=2021
+//@ edition: 2021
fn any<T>() -> T {
loop {}
diff --git a/tests/crashes/120016.rs b/tests/crashes/120016.rs
index faba1af..7eda330 100644
--- a/tests/crashes/120016.rs
+++ b/tests/crashes/120016.rs
@@ -1,5 +1,6 @@
//@ known-bug: #120016
-//@ compile-flags: -Zcrate-attr=feature(const_async_blocks) --edition=2021
+//@ compile-flags: -Zcrate-attr=feature(const_async_blocks)
+//@ edition: 2021
#![feature(type_alias_impl_trait, const_async_blocks)]
diff --git a/tests/crashes/121538.rs b/tests/crashes/121538.rs
deleted file mode 100644
index f18bad8..0000000
--- a/tests/crashes/121538.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ known-bug: #121538
-//@ compile-flags: -Cdebuginfo=2
-
-use std::marker::PhantomData;
-
-struct Digit<T> {
- elem: T
-}
-
-struct Node<T:'static> { m: PhantomData<&'static T> }
-
-enum FingerTree<T:'static> {
- Single(T),
-
- Deep(
- Digit<T>,
- Node<FingerTree<Node<T>>>,
- )
-}
-
-enum Wrapper<T:'static> {
- Simple,
- Other(FingerTree<T>),
-}
-
-fn main() {
- let w =
- Some(Wrapper::Simple::<u32>);
-
-}
diff --git a/tests/crashes/127033.rs b/tests/crashes/127033.rs
index 919c9df..52b880e 100644
--- a/tests/crashes/127033.rs
+++ b/tests/crashes/127033.rs
@@ -1,5 +1,5 @@
//@ known-bug: #127033
-//@ compile-flags: --edition=2021
+//@ edition: 2021
pub trait RaftLogStorage {
fn save_vote(vote: ()) -> impl std::future::Future + Send;
diff --git a/tests/crashes/128094.rs b/tests/crashes/128094.rs
index 5f0ae10..56d09d7 100644
--- a/tests/crashes/128094.rs
+++ b/tests/crashes/128094.rs
@@ -1,5 +1,6 @@
//@ known-bug: rust-lang/rust#128094
-//@ compile-flags: -Zmir-enable-passes=+GVN --edition=2018
+//@ compile-flags: -Zmir-enable-passes=+GVN
+//@ edition: 2018
pub enum Request {
TestSome(T),
diff --git a/tests/crashes/132103.rs b/tests/crashes/132103.rs
index 5bf4792..e2d8378 100644
--- a/tests/crashes/132103.rs
+++ b/tests/crashes/132103.rs
@@ -1,5 +1,6 @@
//@ known-bug: #132103
-//@compile-flags: -Zvalidate-mir --edition=2018 -Zinline-mir=yes
+//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
+//@ edition: 2018
use core::future::{async_drop_in_place, Future};
use core::mem::{self};
use core::pin::pin;
diff --git a/tests/crashes/132430.rs b/tests/crashes/132430.rs
index 995bdf0..81c8c6d 100644
--- a/tests/crashes/132430.rs
+++ b/tests/crashes/132430.rs
@@ -1,6 +1,7 @@
//@ known-bug: #132430
-//@compile-flags: --edition=2018 --crate-type=lib
+//@ compile-flags: --crate-type=lib
+//@ edition: 2018
#![feature(cmse_nonsecure_entry)]
struct Test;
diff --git a/tests/crashes/135128.rs b/tests/crashes/135128.rs
index a8fd1ae..c718b75 100644
--- a/tests/crashes/135128.rs
+++ b/tests/crashes/135128.rs
@@ -1,5 +1,6 @@
//@ known-bug: #135128
-//@ compile-flags: -Copt-level=1 --edition=2021
+//@ compile-flags: -Copt-level=1
+//@ edition: 2021
#![feature(trivial_bounds)]
diff --git a/tests/crashes/135470.rs b/tests/crashes/135470.rs
index 7d357a9..efa017b 100644
--- a/tests/crashes/135470.rs
+++ b/tests/crashes/135470.rs
@@ -1,5 +1,6 @@
//@ known-bug: #135470
-//@ compile-flags: --edition=2021 -Copt-level=0
+//@ compile-flags: -Copt-level=0
+//@ edition: 2021
use std::future::Future;
trait Access {
diff --git a/tests/crashes/135646.rs b/tests/crashes/135646.rs
index 67b0ad9..841ea5b8 100644
--- a/tests/crashes/135646.rs
+++ b/tests/crashes/135646.rs
@@ -1,5 +1,7 @@
//@ known-bug: #135646
-//@ compile-flags: --edition=2024 -Zpolonius=next
+//@ compile-flags: -Zpolonius=next
+//@ edition: 2024
+
fn main() {
&{ [1, 2, 3][4] };
}
diff --git a/tests/crashes/137467-1.rs b/tests/crashes/137467-1.rs
index 1d62cba..b6bff2b 100644
--- a/tests/crashes/137467-1.rs
+++ b/tests/crashes/137467-1.rs
@@ -1,5 +1,5 @@
//@ known-bug: #137467
-//@ compile-flags: --edition=2021
+//@ edition: 2021
enum Camera {
Normal { base_transform: i32 },
Volume { transform: i32 },
diff --git a/tests/crashes/137467-2.rs b/tests/crashes/137467-2.rs
index 151d6a0..a70ea92 100644
--- a/tests/crashes/137467-2.rs
+++ b/tests/crashes/137467-2.rs
@@ -1,5 +1,5 @@
//@ known-bug: #137467
-//@ compile-flags: --edition=2021
+//@ edition: 2021
enum Camera {
Normal { base_transform: i32 },
diff --git a/tests/crashes/137467-3.rs b/tests/crashes/137467-3.rs
index 2140fe0..cb81a9a 100644
--- a/tests/crashes/137467-3.rs
+++ b/tests/crashes/137467-3.rs
@@ -1,5 +1,5 @@
//@ known-bug: #137467
-//@ compile-flags: --edition=2021
+//@ edition: 2021
fn meow(x: (u32, u32, u32)) {
let f = || {
diff --git a/tests/crashes/137916.rs b/tests/crashes/137916.rs
index 3d6b0e0..b25e7b2 100644
--- a/tests/crashes/137916.rs
+++ b/tests/crashes/137916.rs
@@ -1,5 +1,5 @@
//@ known-bug: #137916
-//@ compile-flags: --edition=2021
+//@ edition: 2021
use std::ptr::null;
async fn a() -> Box<dyn Send> {
diff --git a/tests/crashes/74451.rs b/tests/crashes/74451.rs
deleted file mode 100644
index 8f93699..0000000
--- a/tests/crashes/74451.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-//@ known-bug: #74451
-//@ compile-flags: -Copt-level=0
-
-#![feature(specialization)]
-#![feature(unsize, coerce_unsized)]
-#![allow(incomplete_features)]
-#![crate_type = "lib"]
-
-use std::ops::CoerceUnsized;
-
-pub struct SmartassPtr<A: Smartass+?Sized>(A::Data);
-
-pub trait Smartass {
- type Data;
- type Data2: CoerceUnsized<*const [u8]>;
-}
-
-pub trait MaybeObjectSafe {}
-
-impl MaybeObjectSafe for () {}
-
-impl<T> Smartass for T {
- type Data = <Self as Smartass>::Data2;
- default type Data2 = *const [u8; 0];
-}
-
-impl Smartass for () {
- type Data2 = *const [u8; 1];
-}
-
-impl Smartass for dyn MaybeObjectSafe {
- type Data = *const [u8];
- type Data2 = *const [u8; 0];
-}
-
-impl<U: Smartass+?Sized, T: Smartass+?Sized> CoerceUnsized<SmartassPtr<T>> for SmartassPtr<U>
- where <U as Smartass>::Data: std::ops::CoerceUnsized<<T as Smartass>::Data>
-{}
-
-pub fn conv(s: SmartassPtr<()>) -> SmartassPtr<dyn MaybeObjectSafe> {
- s // This shouldn't coerce
-}
diff --git a/tests/debuginfo/coroutine-closure.rs b/tests/debuginfo/coroutine-closure.rs
index ffb6ae6..0025310 100644
--- a/tests/debuginfo/coroutine-closure.rs
+++ b/tests/debuginfo/coroutine-closure.rs
@@ -1,6 +1,7 @@
#![feature(async_closure)]
//@ only-cdb
-//@ compile-flags:-g --edition=2021
+//@ compile-flags: -g
+//@ edition: 2021
// === CDB TESTS ==================================================================================
diff --git a/tests/debuginfo/drop-locations.rs b/tests/debuginfo/drop-locations.rs
index a55cf7b..91b3da5 100644
--- a/tests/debuginfo/drop-locations.rs
+++ b/tests/debuginfo/drop-locations.rs
@@ -1,5 +1,7 @@
//@ ignore-android
-//@ ignore-test: #128971
+
+// FIXME: stepping with "next" in a debugger skips past end-of-scope drops
+//@ ignore-test (broken, see #128971)
#![allow(unused)]
diff --git a/tests/debuginfo/recursive-enum.rs b/tests/debuginfo/recursive-enum.rs
index c2c3e71..b861e6d 100644
--- a/tests/debuginfo/recursive-enum.rs
+++ b/tests/debuginfo/recursive-enum.rs
@@ -4,7 +4,7 @@
// gdb-command:run
// Test whether compiling a recursive enum definition crashes debug info generation. The test case
-// is taken from issue #11083.
+// is taken from issue #11083 and #135093.
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
@@ -18,6 +18,21 @@ struct WindowCallbacks<'a> {
pos_callback: Option<Box<FnMut(&Window, i32, i32) + 'a>>,
}
+enum ExpandingRecursive<T> {
+ Recurse(Indirect<T>),
+ Item(T),
+}
+
+struct Indirect<U> {
+ rec: *const ExpandingRecursive<Option<U>>,
+}
+
+
fn main() {
let x = WindowCallbacks { pos_callback: None };
+
+ // EXPANDING RECURSIVE
+ let expanding_recursive: ExpandingRecursive<u64> = ExpandingRecursive::Recurse(Indirect {
+ rec: &ExpandingRecursive::Item(Option::Some(42)),
+ });
}
diff --git a/tests/crashes/107362.rs b/tests/debuginfo/recursive-type-with-gat.rs
similarity index 96%
rename from tests/crashes/107362.rs
rename to tests/debuginfo/recursive-type-with-gat.rs
index 8d55d61..b8a67d8 100644
--- a/tests/crashes/107362.rs
+++ b/tests/debuginfo/recursive-type-with-gat.rs
@@ -1,4 +1,3 @@
-//@ known-bug: #107362
//@ compile-flags: -Cdebuginfo=2
pub trait Functor
diff --git a/tests/incremental/const-generic-type-cycle.rs b/tests/incremental/const-generic-type-cycle.rs
index cd0437f..40a40eb 100644
--- a/tests/incremental/const-generic-type-cycle.rs
+++ b/tests/incremental/const-generic-type-cycle.rs
@@ -3,7 +3,6 @@
//
//@ compile-flags: -Zincremental-ignore-spans
//@ revisions: cpass cfail
-//@ error-pattern: cycle detected when computing type of `Bar::N`
#![feature(trait_alias)]
#![crate_type="lib"]
@@ -13,5 +12,9 @@ trait Bar<const N: usize> {}
#[cfg(cfail)]
trait Bar<const N: dyn BB> {}
+//[cfail]~^ ERROR cycle detected when computing type of `Bar::N`
+//[cfail]~| ERROR cycle detected when computing type of `Bar::N`
+//[cfail]~| ERROR cycle detected when computing type of `Bar::N`
+//[cfail]~| ERROR `(dyn Bar<{ 2 + 1 }> + 'static)` is forbidden as the type of a const generic parameter
trait BB = Bar<{ 2 + 1 }>;
diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs
index 1534aca..7b409db 100644
--- a/tests/incremental/delayed_span_bug.rs
+++ b/tests/incremental/delayed_span_bug.rs
@@ -1,8 +1,7 @@
//@ revisions: cfail1 cfail2
//@ should-ice
-//@ error-pattern: delayed bug triggered by #[rustc_delayed_bug_from_inside_query]
#![feature(rustc_attrs)]
#[rustc_delayed_bug_from_inside_query]
-fn main() {}
+fn main() {} //~ ERROR delayed bug triggered by #[rustc_delayed_bug_from_inside_query]
diff --git a/tests/incremental/issue-85360-eval-obligation-ice.rs b/tests/incremental/issue-85360-eval-obligation-ice.rs
index 6efae1a..70bb43f 100644
--- a/tests/incremental/issue-85360-eval-obligation-ice.rs
+++ b/tests/incremental/issue-85360-eval-obligation-ice.rs
@@ -1,6 +1,7 @@
//@ revisions:cfail1 cfail2
-//@[cfail1] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=not-loaded
-//@[cfail2] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=loaded
+//@[cfail1] compile-flags: --crate-type=lib -Zassert-incr-state=not-loaded
+//@[cfail2] compile-flags: --crate-type=lib -Zassert-incr-state=loaded
+//@ edition: 2021
//@ build-pass
use core::any::Any;
diff --git a/tests/incremental/link_order/main.rs b/tests/incremental/link_order/main.rs
index 847a47a..20931e2 100644
--- a/tests/incremental/link_order/main.rs
+++ b/tests/incremental/link_order/main.rs
@@ -1,5 +1,4 @@
//@ aux-build:my_lib.rs
-//@ error-pattern: error: linking with
//@ revisions:cfail1 cfail2
//@ compile-flags:-Z query-dep-graph
@@ -10,3 +9,5 @@
extern crate my_lib;
fn main() {}
+
+//~? ERROR linking with
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
index 56d4d50..151580d 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
@@ -33,7 +33,7 @@
- _4 = g() -> [return: bb1, unwind unreachable];
+ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
+ _3 = &mut _4;
-+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 };
++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { pointer: copy _3 };
+ StorageDead(_3);
+ StorageLive(_5);
+ _5 = const false;
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index 751916a..6196fc0 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -33,7 +33,7 @@
- _4 = g() -> [return: bb1, unwind continue];
+ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
+ _3 = &mut _4;
-+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 };
++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { pointer: copy _3 };
+ StorageDead(_3);
+ StorageLive(_5);
+ _5 = const false;
diff --git "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff" "b/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
index e49d7ce..1e9a6dd 100644
--- "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
+++ "b/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-abort.diff"
@@ -121,7 +121,7 @@
- }
-
- bb2: {
-+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 };
++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { pointer: copy _5 };
StorageDead(_5);
StorageLive(_6);
StorageLive(_7);
@@ -218,7 +218,7 @@
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
+ _20 = &mut (*_21);
-+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
++ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
+ StorageDead(_20);
+ StorageLive(_22);
+ StorageLive(_23);
@@ -239,7 +239,7 @@
+ _48 = &mut (_19.0: &mut std::future::Ready<()>);
+ _45 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_48);
-+ _47 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _45 };
++ _47 = Pin::<&mut std::future::Ready<()>> { pointer: copy _45 };
+ StorageDead(_47);
+ _44 = &mut ((*_45).0: std::option::Option<()>);
+ StorageLive(_49);
diff --git "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff" "b/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
index e7aed556..94b89a31 100644
--- "a/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
+++ "b/tests/mir-opt/inline_coroutine_body.run2-\173closure\0430\175.Inline.panic-unwind.diff"
@@ -123,7 +123,7 @@
- }
-
- bb2: {
-+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 };
++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { pointer: copy _5 };
StorageDead(_5);
StorageLive(_6);
StorageLive(_7);
@@ -235,7 +235,7 @@
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
+ _20 = &mut (*_21);
-+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
++ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
+ StorageDead(_20);
+ StorageLive(_22);
+ StorageLive(_23);
@@ -256,7 +256,7 @@
+ _50 = &mut (_19.0: &mut std::future::Ready<()>);
+ _47 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_50);
-+ _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 };
++ _49 = Pin::<&mut std::future::Ready<()>> { pointer: copy _47 };
+ StorageDead(_49);
+ _46 = &mut ((*_47).0: std::option::Option<()>);
+ StorageLive(_51);
diff --git a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff
index 047441e..c3272f2 100644
--- a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff
+++ b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff
@@ -3,7 +3,7 @@
fn bitwise_not() -> i32 {
let mut _0: i32;
- let mut _1: i32;
+ let _1: i32;
let mut _2: bool;
let mut _3: i32;
let mut _4: i32;
@@ -13,7 +13,6 @@
bb0: {
StorageLive(_1);
- _1 = const 0_i32;
_1 = const 1_i32;
StorageLive(_2);
StorageLive(_3);
@@ -22,7 +21,8 @@
_3 = Not(move _4);
StorageDead(_4);
_2 = Eq(move _3, const 0_i32);
- switchInt(move _2) -> [0: bb2, otherwise: bb1];
+- switchInt(move _2) -> [0: bb2, otherwise: bb1];
++ goto -> bb2;
}
bb1: {
diff --git a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff
index 047441e..c3272f2 100644
--- a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff
+++ b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff
@@ -3,7 +3,7 @@
fn bitwise_not() -> i32 {
let mut _0: i32;
- let mut _1: i32;
+ let _1: i32;
let mut _2: bool;
let mut _3: i32;
let mut _4: i32;
@@ -13,7 +13,6 @@
bb0: {
StorageLive(_1);
- _1 = const 0_i32;
_1 = const 1_i32;
StorageLive(_2);
StorageLive(_3);
@@ -22,7 +21,8 @@
_3 = Not(move _4);
StorageDead(_4);
_2 = Eq(move _3, const 0_i32);
- switchInt(move _2) -> [0: bb2, otherwise: bb1];
+- switchInt(move _2) -> [0: bb2, otherwise: bb1];
++ goto -> bb2;
}
bb1: {
diff --git a/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-abort.diff
new file mode 100644
index 0000000..ad8be1e
--- /dev/null
+++ b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-abort.diff
@@ -0,0 +1,46 @@
+- // MIR for `logical_not` before JumpThreading
++ // MIR for `logical_not` after JumpThreading
+
+ fn logical_not() -> i32 {
+ let mut _0: i32;
+ let _1: bool;
+ let mut _2: bool;
+ let mut _3: bool;
+ let mut _4: bool;
+ scope 1 {
+ debug a => _1;
+ }
+
+ bb0: {
+ StorageLive(_1);
+ _1 = const false;
+ StorageLive(_2);
+ StorageLive(_3);
+ StorageLive(_4);
+ _4 = copy _1;
+ _3 = Not(move _4);
+ StorageDead(_4);
+ _2 = Eq(move _3, const true);
+- switchInt(move _2) -> [0: bb2, otherwise: bb1];
++ goto -> bb1;
+ }
+
+ bb1: {
+ StorageDead(_3);
+ _0 = const 1_i32;
+ goto -> bb3;
+ }
+
+ bb2: {
+ StorageDead(_3);
+ _0 = const 0_i32;
+ goto -> bb3;
+ }
+
+ bb3: {
+ StorageDead(_2);
+ StorageDead(_1);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-unwind.diff
new file mode 100644
index 0000000..ad8be1e
--- /dev/null
+++ b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-unwind.diff
@@ -0,0 +1,46 @@
+- // MIR for `logical_not` before JumpThreading
++ // MIR for `logical_not` after JumpThreading
+
+ fn logical_not() -> i32 {
+ let mut _0: i32;
+ let _1: bool;
+ let mut _2: bool;
+ let mut _3: bool;
+ let mut _4: bool;
+ scope 1 {
+ debug a => _1;
+ }
+
+ bb0: {
+ StorageLive(_1);
+ _1 = const false;
+ StorageLive(_2);
+ StorageLive(_3);
+ StorageLive(_4);
+ _4 = copy _1;
+ _3 = Not(move _4);
+ StorageDead(_4);
+ _2 = Eq(move _3, const true);
+- switchInt(move _2) -> [0: bb2, otherwise: bb1];
++ goto -> bb1;
+ }
+
+ bb1: {
+ StorageDead(_3);
+ _0 = const 1_i32;
+ goto -> bb3;
+ }
+
+ bb2: {
+ StorageDead(_3);
+ _0 = const 0_i32;
+ goto -> bb3;
+ }
+
+ bb3: {
+ StorageDead(_2);
+ StorageDead(_1);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs
index 743ee8e..009e106 100644
--- a/tests/mir-opt/jump_threading.rs
+++ b/tests/mir-opt/jump_threading.rs
@@ -532,14 +532,19 @@ fn floats() -> u32 {
pub fn bitwise_not() -> i32 {
// CHECK-LABEL: fn bitwise_not(
- // CHECK: switchInt(
// Test for #131195, which was optimizing `!a == b` into `a != b`.
- let mut a: i32 = 0;
- a = 1;
+ let a = 1;
if !a == 0 { 1 } else { 0 }
}
+pub fn logical_not() -> i32 {
+ // CHECK-LABEL: fn logical_not(
+
+ let a = false;
+ if !a == true { 1 } else { 0 }
+}
+
fn main() {
// CHECK-LABEL: fn main(
too_complex(Ok(0));
@@ -555,6 +560,8 @@ fn main() {
aggregate(7);
assume(7, false);
floats();
+ bitwise_not();
+ logical_not();
}
// EMIT_MIR jump_threading.too_complex.JumpThreading.diff
@@ -572,3 +579,4 @@ fn main() {
// EMIT_MIR jump_threading.aggregate_copy.JumpThreading.diff
// EMIT_MIR jump_threading.floats.JumpThreading.diff
// EMIT_MIR jump_threading.bitwise_not.JumpThreading.diff
+// EMIT_MIR jump_threading.logical_not.JumpThreading.diff
diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff
index 596ad70..f29bc5d 100644
--- a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff
@@ -18,7 +18,7 @@
_4 = copy _1;
StorageLive(_5);
_5 = copy _2;
-- _3 = three_way_compare::<char>(move _4, move _5) -> [return: bb1, unwind continue];
+- _3 = three_way_compare::<char>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = Cmp(move _4, move _5);
+ goto -> bb1;
}
diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff
index 987c216..654cb25 100644
--- a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff
@@ -15,7 +15,7 @@
_4 = copy _1;
StorageLive(_5);
_5 = copy _2;
-- _3 = three_way_compare::<i16>(move _4, move _5) -> [return: bb1, unwind continue];
+- _3 = three_way_compare::<i16>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = Cmp(move _4, move _5);
+ goto -> bb1;
}
diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff
index d7ec6dc..82c89b7 100644
--- a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff
@@ -18,7 +18,7 @@
_4 = copy _1;
StorageLive(_5);
_5 = copy _2;
-- _3 = three_way_compare::<u32>(move _4, move _5) -> [return: bb1, unwind continue];
+- _3 = three_way_compare::<u32>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = Cmp(move _4, move _5);
+ goto -> bb1;
}
diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
index ee6e16d..7d7cb76 100644
--- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
+++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
@@ -73,9 +73,6 @@
}
bb7: {
- backward incompatible drop(_2);
- backward incompatible drop(_4);
- backward incompatible drop(_5);
goto -> bb21;
}
diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
index ee6e16d..7d7cb76 100644
--- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
+++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
@@ -73,9 +73,6 @@
}
bb7: {
- backward incompatible drop(_2);
- backward incompatible drop(_4);
- backward incompatible drop(_5);
goto -> bb21;
}
diff --git a/tests/pretty/ast-stmt-expr-attr.rs b/tests/pretty/ast-stmt-expr-attr.rs
index fd7272a..4ca6046 100644
--- a/tests/pretty/ast-stmt-expr-attr.rs
+++ b/tests/pretty/ast-stmt-expr-attr.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
let _ = #[attr] [];
let _ = #[attr] [0];
diff --git a/tests/pretty/enum-variant-vis.rs b/tests/pretty/enum-variant-vis.rs
index 3397e7d..5b9f7e0 100644
--- a/tests/pretty/enum-variant-vis.rs
+++ b/tests/pretty/enum-variant-vis.rs
@@ -4,5 +4,5 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
enum Foo { pub V, }
diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp
index dfbaff6..b6bc8e9 100644
--- a/tests/pretty/hir-fn-variadic.pp
+++ b/tests/pretty/hir-fn-variadic.pp
@@ -13,3 +13,39 @@
}
unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::<usize>() }
+
+fn main() {
+ fn g1(_: extern "C" fn(_: u8, va: ...)) { }
+ fn g2(_: extern "C" fn(_: u8, ...)) { }
+ fn g3(_: extern "C" fn(u8, va: ...)) { }
+ fn g4(_: extern "C" fn(u8, ...)) { }
+
+ fn g5(_: extern "C" fn(va: ...)) { }
+ fn g6(_: extern "C" fn(...)) { }
+
+ {
+ let _ =
+ {
+ unsafe extern "C" fn f1(_: u8, va: ...) { }
+ };
+ };
+ {
+ let _ =
+ {
+ unsafe extern "C" fn f2(_: u8, _: ...) { }
+ };
+ };
+
+ {
+ let _ =
+ {
+ unsafe extern "C" fn f5(va: ...) { }
+ };
+ };
+ {
+ let _ =
+ {
+ unsafe extern "C" fn f6(_: ...) { }
+ };
+ };
+}
diff --git a/tests/pretty/hir-fn-variadic.rs b/tests/pretty/hir-fn-variadic.rs
index 3d3f7ee..99aa402 100644
--- a/tests/pretty/hir-fn-variadic.rs
+++ b/tests/pretty/hir-fn-variadic.rs
@@ -11,3 +11,19 @@
pub unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize {
va2.arg::<usize>()
}
+
+fn main() {
+ fn g1(_: extern "C" fn(_: u8, va: ...)) {}
+ fn g2(_: extern "C" fn(_: u8, ...)) {}
+ fn g3(_: extern "C" fn(u8, va: ...)) {}
+ fn g4(_: extern "C" fn(u8, ...)) {}
+
+ fn g5(_: extern "C" fn(va: ...)) {}
+ fn g6(_: extern "C" fn(...)) {}
+
+ _ = { unsafe extern "C" fn f1(_: u8, va: ...) {} };
+ _ = { unsafe extern "C" fn f2(_: u8, ...) {} };
+
+ _ = { unsafe extern "C" fn f5(va: ...) {} };
+ _ = { unsafe extern "C" fn f6(...) {} };
+}
diff --git a/tests/pretty/if-attr.rs b/tests/pretty/if-attr.rs
index 89d6130..8b343a8 100644
--- a/tests/pretty/if-attr.rs
+++ b/tests/pretty/if-attr.rs
@@ -1,6 +1,6 @@
//@ pp-exact
-#[cfg(FALSE)]
+#[cfg(false)]
fn simple_attr() {
#[attr]
@@ -10,21 +10,21 @@ fn simple_attr() {
if true {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn if_else_chain() {
#[first_attr]
if true {} else if false {} else {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn if_let() {
#[attr]
if let Some(_) = Some(true) {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn let_attr_if() {
let _ = #[attr] if let _ = 0 {};
let _ = #[attr] if true {};
diff --git a/tests/pretty/nested-item-vis-defaultness.rs b/tests/pretty/nested-item-vis-defaultness.rs
index 1e971fc..68f56a1 100644
--- a/tests/pretty/nested-item-vis-defaultness.rs
+++ b/tests/pretty/nested-item-vis-defaultness.rs
@@ -4,7 +4,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" {
static X: u8;
type X;
@@ -14,7 +14,7 @@ fn main() {}
pub fn foo();
}
-#[cfg(FALSE)]
+#[cfg(false)]
trait T {
const X: u8;
type X;
@@ -30,7 +30,7 @@ trait T {
pub default fn foo();
}
-#[cfg(FALSE)]
+#[cfg(false)]
impl T for S {
const X: u8;
type X;
diff --git a/tests/pretty/postfix-yield.rs b/tests/pretty/postfix-yield.rs
index f76e814..60380a40 100644
--- a/tests/pretty/postfix-yield.rs
+++ b/tests/pretty/postfix-yield.rs
@@ -2,7 +2,8 @@
//@ edition: 2024
//@ pp-exact
-#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)]
+#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr,
+stmt_expr_attributes)]
use std::ops::{Coroutine, CoroutineState};
use std::pin::pin;
diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs
index 3e54b57..0521b39 100644
--- a/tests/run-make/broken-pipe-no-ice/rmake.rs
+++ b/tests/run-make/broken-pipe-no-ice/rmake.rs
@@ -14,9 +14,7 @@
use std::io::Read;
use std::process::{Command, Stdio};
-// FIXME(#137532): replace `os_pipe` dependency with std `anonymous_pipe` once that stabilizes and
-// reaches beta.
-use run_make_support::{env_var, os_pipe};
+use run_make_support::env_var;
#[derive(Debug, PartialEq)]
enum Binary {
@@ -25,7 +23,7 @@ enum Binary {
}
fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) {
- let (reader, writer) = os_pipe::pipe().unwrap();
+ let (reader, writer) = std::io::pipe().unwrap();
drop(reader); // close read-end
cmd.stdout(writer).stderr(Stdio::piped());
diff --git a/tests/run-make/crate-data-smoke/rmake.rs b/tests/run-make/crate-data-smoke/rmake.rs
index 70f8e46..b5708d0 100644
--- a/tests/run-make/crate-data-smoke/rmake.rs
+++ b/tests/run-make/crate-data-smoke/rmake.rs
@@ -1,9 +1,20 @@
-use run_make_support::{bin_name, rust_lib_name, rustc};
+use run_make_support::{bin_name, rust_lib_name, rustc, target};
fn main() {
- rustc().print("crate-name").input("crate.rs").run().assert_stdout_equals("foo");
- rustc().print("file-names").input("crate.rs").run().assert_stdout_equals(bin_name("foo"));
rustc()
+ .target(target())
+ .print("crate-name")
+ .input("crate.rs")
+ .run()
+ .assert_stdout_equals("foo");
+ rustc()
+ .target(target())
+ .print("file-names")
+ .input("crate.rs")
+ .run()
+ .assert_stdout_equals(bin_name("foo"));
+ rustc()
+ .target(target())
.print("file-names")
.crate_type("lib")
.arg("--test")
@@ -11,11 +22,22 @@ fn main() {
.run()
.assert_stdout_equals(bin_name("foo"));
rustc()
+ .target(target())
.print("file-names")
.arg("--test")
.input("lib.rs")
.run()
.assert_stdout_equals(bin_name("mylib"));
- rustc().print("file-names").input("lib.rs").run().assert_stdout_equals(rust_lib_name("mylib"));
- rustc().print("file-names").input("rlib.rs").run().assert_stdout_equals(rust_lib_name("mylib"));
+ rustc()
+ .target(target())
+ .print("file-names")
+ .input("lib.rs")
+ .run()
+ .assert_stdout_equals(rust_lib_name("mylib"));
+ rustc()
+ .target(target())
+ .print("file-names")
+ .input("rlib.rs")
+ .run()
+ .assert_stdout_equals(rust_lib_name("mylib"));
}
diff --git a/tests/run-make/crate-name-priority/rmake.rs b/tests/run-make/crate-name-priority/rmake.rs
index 5bdb49b..82e482b 100644
--- a/tests/run-make/crate-name-priority/rmake.rs
+++ b/tests/run-make/crate-name-priority/rmake.rs
@@ -4,6 +4,8 @@
// and the compiler flags, and checks that the flag is favoured each time.
// See https://github.com/rust-lang/rust/pull/15518
+//@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`)
+
use run_make_support::{bin_name, rfs, rustc};
fn main() {
diff --git a/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs
new file mode 100644
index 0000000..942b667
--- /dev/null
+++ b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs
@@ -0,0 +1,32 @@
+//@ only-x86_64-unknown-linux-gnu
+
+// Regression test for the incremental bug in <https://github.com/rust-lang/rust/issues/139407>.
+//
+// A detailed explanation is described in <https://github.com/rust-lang/rust/pull/139453>,
+// however the gist of the issue is that hard-linking temporary files can interact strangely
+// across incremental sessions that are not finalized due to errors originating from the
+// codegen backend.
+
+use run_make_support::{run, rustc};
+
+fn main() {
+ let mk_rustc = || {
+ let mut rustc = rustc();
+ rustc.input("test.rs").incremental("incr").arg("-Csave-temps").output("test");
+ rustc
+ };
+
+ // Revision 1
+ mk_rustc().cfg("rpass1").run();
+
+ run("test");
+
+ // Revision 2
+ mk_rustc().cfg("cfail2").run_fail();
+ // Expected to fail.
+
+ // Revision 3
+ mk_rustc().cfg("rpass3").run();
+
+ run("test");
+}
diff --git a/tests/run-make/dirty-incr-due-to-hard-link/test.rs b/tests/run-make/dirty-incr-due-to-hard-link/test.rs
new file mode 100644
index 0000000..dba5a6b
--- /dev/null
+++ b/tests/run-make/dirty-incr-due-to-hard-link/test.rs
@@ -0,0 +1,31 @@
+#[inline(never)]
+#[cfg(any(rpass1, rpass3))]
+fn a() -> i32 {
+ 0
+}
+
+#[cfg(any(cfail2))]
+fn a() -> i32 {
+ 1
+}
+
+fn main() {
+ evil::evil();
+ assert_eq!(a(), 0);
+}
+
+mod evil {
+ #[cfg(any(rpass1, rpass3))]
+ pub fn evil() {
+ unsafe {
+ std::arch::asm!("/* */");
+ }
+ }
+
+ #[cfg(any(cfail2))]
+ pub fn evil() {
+ unsafe {
+ std::arch::asm!("missing");
+ }
+ }
+}
diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs
index 0aae07f..550c8b9 100644
--- a/tests/run-make/embed-source-dwarf/rmake.rs
+++ b/tests/run-make/embed-source-dwarf/rmake.rs
@@ -21,7 +21,7 @@ fn main() {
.output(&output)
.arg("-g")
.arg("-Zembed-source=yes")
- .arg("-Zdwarf-version=5")
+ .arg("-Cdwarf-version=5")
.run();
let output = rfs::read(output);
let obj = object::File::parse(output.as_slice()).unwrap();
diff --git a/tests/run-make/extra-filename-with-temp-outputs/rmake.rs b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs
index 0910045..f93a3ec 100644
--- a/tests/run-make/extra-filename-with-temp-outputs/rmake.rs
+++ b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs
@@ -6,6 +6,8 @@
// are named as expected.
// See https://github.com/rust-lang/rust/pull/15686
+//@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`)
+
use run_make_support::{bin_name, cwd, has_prefix, has_suffix, rfs, rustc, shallow_find_files};
fn main() {
diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs
index c0569af..8da0bfa 100644
--- a/tests/run-make/output-type-permutations/rmake.rs
+++ b/tests/run-make/output-type-permutations/rmake.rs
@@ -4,6 +4,9 @@
// files are exactly what is expected, no more, no less.
// See https://github.com/rust-lang/rust/pull/12020
+//@ ignore-cross-compile
+// Reason: some cross-compiled targets don't support various crate types and fail to link.
+
use std::path::PathBuf;
use run_make_support::{
@@ -17,6 +20,7 @@
// `dir`: the name of the directory where the test happens
// `rustc_invocation`: the rustc command being tested
// Any unexpected output files not listed in `must_exist` or `can_exist` will cause a failure.
+#[track_caller]
fn assert_expected_output_files(expectations: Expectations, rustc_invocation: impl Fn()) {
let Expectations { expected_files: must_exist, allowed_files: can_exist, test_dir: dir } =
expectations;
diff --git a/tests/run-make/print-request-help-stable-unstable/help-diff.diff b/tests/run-make/print-request-help-stable-unstable/help-diff.diff
new file mode 100644
index 0000000..07eafca
--- /dev/null
+++ b/tests/run-make/print-request-help-stable-unstable/help-diff.diff
@@ -0,0 +1,7 @@
+@@ -1,5 +1,5 @@
+ error: unknown print request: `xxx`
+ |
+- = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models`
++ = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
+ = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
+
diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs
new file mode 100644
index 0000000..a59963d
--- /dev/null
+++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs
@@ -0,0 +1,33 @@
+//! Check that unstable print requests are omitted from help if compiler is in stable channel.
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/138698>
+use run_make_support::{diff, rustc, similar};
+
+fn main() {
+ let stable_invalid_print_request_help = rustc()
+ .env("RUSTC_BOOTSTRAP", "-1")
+ .cfg("force_stable")
+ .print("xxx")
+ .run_fail()
+ .stderr_utf8();
+ assert!(!stable_invalid_print_request_help.contains("all-target-specs-json"));
+ diff()
+ .expected_file("stable-invalid-print-request-help.err")
+ .actual_text("stable_invalid_print_request_help", &stable_invalid_print_request_help)
+ .run();
+
+ let unstable_invalid_print_request_help = rustc().print("xxx").run_fail().stderr_utf8();
+ assert!(unstable_invalid_print_request_help.contains("all-target-specs-json"));
+ diff()
+ .expected_file("unstable-invalid-print-request-help.err")
+ .actual_text("unstable_invalid_print_request_help", &unstable_invalid_print_request_help)
+ .run();
+
+ let help_diff = similar::TextDiff::from_lines(
+ &stable_invalid_print_request_help,
+ &unstable_invalid_print_request_help,
+ )
+ .unified_diff()
+ .to_string();
+ diff().expected_file("help-diff.diff").actual_text("help_diff", help_diff).run();
+}
diff --git a/tests/run-make/print-request-help-stable-unstable/stable-invalid-print-request-help.err b/tests/run-make/print-request-help-stable-unstable/stable-invalid-print-request-help.err
new file mode 100644
index 0000000..019a578
--- /dev/null
+++ b/tests/run-make/print-request-help-stable-unstable/stable-invalid-print-request-help.err
@@ -0,0 +1,5 @@
+error: unknown print request: `xxx`
+ |
+ = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models`
+ = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
+
diff --git a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err
new file mode 100644
index 0000000..50ef340
--- /dev/null
+++ b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err
@@ -0,0 +1,5 @@
+error: unknown print request: `xxx`
+ |
+ = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models`
+ = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
+
diff --git a/tests/run-make/reproducible-build/rmake.rs b/tests/run-make/reproducible-build/rmake.rs
index 8a8b0d6..93fc30d 100644
--- a/tests/run-make/reproducible-build/rmake.rs
+++ b/tests/run-make/reproducible-build/rmake.rs
@@ -20,6 +20,8 @@
// See https://github.com/rust-lang/rust/pull/32293
// Tracking Issue: https://github.com/rust-lang/rust/issues/129080
+//@ ignore-cross-compile (linker binary needs to run)
+
use run_make_support::{
bin_name, cwd, diff, is_darwin, is_windows, regex, rfs, run_in_tmpdir, rust_lib_name, rustc,
};
diff --git a/tests/run-make/rustc-help/help-v.diff b/tests/run-make/rustc-help/help-v.diff
index 22c5dd8..30703f6 100644
--- a/tests/run-make/rustc-help/help-v.diff
+++ b/tests/run-make/rustc-help/help-v.diff
@@ -1,4 +1,4 @@
-@@ -51,10 +51,27 @@
+@@ -53,10 +53,27 @@
Set a codegen option
-V, --version Print version info and exit
-v, --verbose Use verbose output
diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout
index f19ca1e..13af6e2 100644
--- a/tests/run-make/rustc-help/help-v.stdout
+++ b/tests/run-make/rustc-help/help-v.stdout
@@ -29,8 +29,10 @@
--emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
Comma separated list of types of output for the
compiler to emit
- --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
- Compiler information to print on stdout
+ --print INFO[=FILE]
+ Compiler information to print on stdout (or to a file)
+ INFO may be one of
+ (all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models).
-g Equivalent to -C debuginfo=2
-O Equivalent to -C opt-level=3
-o FILENAME Write output to <filename>
diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout
index f7d3529..62757d9 100644
--- a/tests/run-make/rustc-help/help.stdout
+++ b/tests/run-make/rustc-help/help.stdout
@@ -29,8 +29,10 @@
--emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]
Comma separated list of types of output for the
compiler to emit
- --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
- Compiler information to print on stdout
+ --print INFO[=FILE]
+ Compiler information to print on stdout (or to a file)
+ INFO may be one of
+ (all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models).
-g Equivalent to -C debuginfo=2
-O Equivalent to -C opt-level=3
-o FILENAME Write output to <filename>
diff --git a/tests/run-make/strip/rmake.rs b/tests/run-make/strip/rmake.rs
index ef1acc2..01b31ac 100644
--- a/tests/run-make/strip/rmake.rs
+++ b/tests/run-make/strip/rmake.rs
@@ -1,4 +1,5 @@
-//@ ignore-windows Windows does not actually strip
+//@ ignore-windows (Windows does not actually strip)
+//@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`)
// Test that -Cstrip correctly strips/preserves debuginfo and symbols.
diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs
index 1fb03c6..79ddd06 100644
--- a/tests/run-make/symbols-all-mangled/rmake.rs
+++ b/tests/run-make/symbols-all-mangled/rmake.rs
@@ -1,5 +1,7 @@
// Check that all symbols in cdylibs, staticlibs and bins are mangled
//@ only-elf some object file formats create multiple symbols for each function with different names
+//@ ignore-nvptx64 (needs target std)
+//@ ignore-cross-compile (host-only)
use run_make_support::object::read::{Object, ObjectSymbol};
use run_make_support::{bin_name, dynamic_lib_name, object, rfs, rustc, static_lib_name};
diff --git a/tests/rustdoc-js-std/unbox-type-result.js b/tests/rustdoc-js-std/unbox-type-result.js
new file mode 100644
index 0000000..1f5cba5
--- /dev/null
+++ b/tests/rustdoc-js-std/unbox-type-result.js
@@ -0,0 +1,20 @@
+// exact-check
+
+// Test case for https://github.com/rust-lang/rust/issues/139665
+// make sure that std::io::Result and std::thread::Result get unboxed
+
+const EXPECTED = [
+ {
+ query: "File -> Metadata",
+ others: [
+ { path: "std::fs::File", name: "metadata" },
+ { path: "std::fs::File", name: "metadata_at" },
+ ]
+ },
+ {
+ query: "JoinHandle<T> -> T",
+ others: [
+ { path: "std::thread::JoinHandle", name: "join" },
+ ]
+ },
+];
diff --git a/tests/rustdoc-js/generics-unbox.js b/tests/rustdoc-js/generics-unbox.js
index 6baf00c..a4f2ba8 100644
--- a/tests/rustdoc-js/generics-unbox.js
+++ b/tests/rustdoc-js/generics-unbox.js
@@ -31,4 +31,10 @@
{ 'path': 'generics_unbox', 'name': 'beta' },
],
},
+ {
+ 'query': '-> Sigma',
+ 'others': [
+ { 'path': 'generics_unbox', 'name': 'delta' },
+ ],
+ },
];
diff --git a/tests/rustdoc-js/generics-unbox.rs b/tests/rustdoc-js/generics-unbox.rs
index c257857..b16e35e 100644
--- a/tests/rustdoc-js/generics-unbox.rs
+++ b/tests/rustdoc-js/generics-unbox.rs
@@ -42,3 +42,15 @@ pub fn beta<T, U>(_: Inside<T>) -> Out<Out3<T, U>, Out4<U, T>> {
pub fn gamma<T, U>(_: Inside<T>) -> Out<Out3<U, T>, Out4<T, U>> {
loop {}
}
+
+pub fn delta(_: i32) -> Epsilon<Sigma> {
+ loop {}
+}
+
+#[doc(search_unbox)]
+pub struct Theta<T>(T);
+
+#[doc(search_unbox)]
+pub type Epsilon<T> = Theta<T>;
+
+pub struct Sigma;
diff --git a/tests/rustdoc-json/targets/aarch64_apple_darwin.rs b/tests/rustdoc-json/targets/aarch64_apple_darwin.rs
new file mode 100644
index 0000000..c6ae551
--- /dev/null
+++ b/tests/rustdoc-json/targets/aarch64_apple_darwin.rs
@@ -0,0 +1,14 @@
+//@ only-aarch64-apple-darwin
+
+//@ is "$.target.triple" \"aarch64-apple-darwin\"
+//@ is "$.target.target_features[?(@.name=='vh')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]'
+//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"'
+//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"'
+
+// Ensure we don't look like x86-64
+//@ !has "$.target.target_features[?(@.name=='avx2')]"
diff --git a/tests/rustdoc-json/targets/aarch64_reflects_compiler_options.rs b/tests/rustdoc-json/targets/aarch64_reflects_compiler_options.rs
new file mode 100644
index 0000000..f91221e
--- /dev/null
+++ b/tests/rustdoc-json/targets/aarch64_reflects_compiler_options.rs
@@ -0,0 +1,10 @@
+//@ only-aarch64
+
+// If we enable SVE Bit Permute, we should see that it is enabled
+//@ compile-flags: -Ctarget-feature=+sve2-bitperm
+//@ is "$.target.target_features[?(@.name=='sve2-bitperm')].globally_enabled" true
+
+// As well as its dependency chain
+//@ is "$.target.target_features[?(@.name=='sve2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true
diff --git a/tests/rustdoc-json/targets/aarch64_unknown_linux_gnu.rs b/tests/rustdoc-json/targets/aarch64_unknown_linux_gnu.rs
new file mode 100644
index 0000000..9139b00
--- /dev/null
+++ b/tests/rustdoc-json/targets/aarch64_unknown_linux_gnu.rs
@@ -0,0 +1,14 @@
+//@ only-aarch64-unknown-linux-gnu
+
+//@ is "$.target.triple" \"aarch64-unknown-linux-gnu\"
+//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]'
+//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"'
+//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"'
+
+// Ensure we don't look like x86-64
+//@ !has "$.target.target_features[?(@.name=='avx2')]"
diff --git a/tests/rustdoc-json/targets/i686_pc_windows_msvc.rs b/tests/rustdoc-json/targets/i686_pc_windows_msvc.rs
new file mode 100644
index 0000000..088c741
--- /dev/null
+++ b/tests/rustdoc-json/targets/i686_pc_windows_msvc.rs
@@ -0,0 +1,14 @@
+//@ only-i686-pc-windows-msvc
+
+//@ is "$.target.triple" \"i686-pc-windows-msvc\"
+//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
+//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
+//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
+
+// Ensure we don't look like aarch64
+//@ !has "$.target.target_features[?(@.name=='sve2')]"
diff --git a/tests/rustdoc-json/targets/i686_unknown_linux_gnu.rs b/tests/rustdoc-json/targets/i686_unknown_linux_gnu.rs
new file mode 100644
index 0000000..03788b0
--- /dev/null
+++ b/tests/rustdoc-json/targets/i686_unknown_linux_gnu.rs
@@ -0,0 +1,14 @@
+//@ only-i686-unknown-linux-gnu
+
+//@ is "$.target.triple" \"i686-unknown-linux-gnu\"
+//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
+//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
+//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
+
+// Ensure we don't look like aarch64
+//@ !has "$.target.target_features[?(@.name=='sve2')]"
diff --git a/tests/rustdoc-json/targets/x86_64_apple_darwin.rs b/tests/rustdoc-json/targets/x86_64_apple_darwin.rs
new file mode 100644
index 0000000..a46f913
--- /dev/null
+++ b/tests/rustdoc-json/targets/x86_64_apple_darwin.rs
@@ -0,0 +1,14 @@
+//@ only-x86_64-apple-darwin
+
+//@ is "$.target.triple" \"x86_64-apple-darwin\"
+//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
+//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
+//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
+
+// Ensure we don't look like aarch64
+//@ !has "$.target.target_features[?(@.name=='sve2')]"
diff --git a/tests/rustdoc-json/targets/x86_64_pc_windows_gnu.rs b/tests/rustdoc-json/targets/x86_64_pc_windows_gnu.rs
new file mode 100644
index 0000000..7da12eb
--- /dev/null
+++ b/tests/rustdoc-json/targets/x86_64_pc_windows_gnu.rs
@@ -0,0 +1,14 @@
+//@ only-x86_64-pc-windows-gnu
+
+//@ is "$.target.triple" \"x86_64-pc-windows-gnu\"
+//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
+//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
+//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
+
+// Ensure we don't look like aarch64
+//@ !has "$.target.target_features[?(@.name=='sve2')]"
diff --git a/tests/rustdoc-json/targets/x86_64_pc_windows_msvc.rs b/tests/rustdoc-json/targets/x86_64_pc_windows_msvc.rs
new file mode 100644
index 0000000..d55f577
--- /dev/null
+++ b/tests/rustdoc-json/targets/x86_64_pc_windows_msvc.rs
@@ -0,0 +1,14 @@
+//@ only-x86_64-pc-windows-msvc
+
+//@ is "$.target.triple" \"x86_64-pc-windows-msvc\"
+//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
+//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
+//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
+
+// Ensure we don't look like aarch64
+//@ !has "$.target.target_features[?(@.name=='sve2')]"
diff --git a/tests/rustdoc-json/targets/x86_64_reflects_compiler_options.rs b/tests/rustdoc-json/targets/x86_64_reflects_compiler_options.rs
new file mode 100644
index 0000000..ba029b0
--- /dev/null
+++ b/tests/rustdoc-json/targets/x86_64_reflects_compiler_options.rs
@@ -0,0 +1,10 @@
+//@ only-x86_64
+
+// If we enable AVX2, we should see that it is enabled
+//@ compile-flags: -Ctarget-feature=+avx2
+//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" true
+
+// As well as its dependency chain
+//@ is "$.target.target_features[?(@.name=='avx')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='sse4.2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='sse4.1')].globally_enabled" true
diff --git a/tests/rustdoc-json/targets/x86_64_unknown_linux_gnu.rs b/tests/rustdoc-json/targets/x86_64_unknown_linux_gnu.rs
new file mode 100644
index 0000000..3372fe7
--- /dev/null
+++ b/tests/rustdoc-json/targets/x86_64_unknown_linux_gnu.rs
@@ -0,0 +1,14 @@
+//@ only-x86_64-unknown-linux-gnu
+
+//@ is "$.target.triple" \"x86_64-unknown-linux-gnu\"
+//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
+//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
+//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
+//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
+
+// If this breaks due to stabilization, check rustc_target::target_features for a replacement
+//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
+//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
+
+// Ensure we don't look like aarch64
+//@ !has "$.target.target_features[?(@.name=='sve2')]"
diff --git a/tests/rustdoc-ui/cfg-boolean-literal.rs b/tests/rustdoc-ui/cfg-boolean-literal.rs
index 4d4e599..74808d0 100644
--- a/tests/rustdoc-ui/cfg-boolean-literal.rs
+++ b/tests/rustdoc-ui/cfg-boolean-literal.rs
@@ -1,6 +1,5 @@
//@ check-pass
-#![feature(cfg_boolean_literals)]
#![feature(doc_cfg)]
#[doc(cfg(false))]
diff --git a/tests/rustdoc-ui/deprecated-attrs.rs b/tests/rustdoc-ui/deprecated-attrs.rs
index 0ae65a5..dcf8a52 100644
--- a/tests/rustdoc-ui/deprecated-attrs.rs
+++ b/tests/rustdoc-ui/deprecated-attrs.rs
@@ -1,5 +1,4 @@
//@ compile-flags: --passes unknown-pass
-//@ error-pattern: the `passes` flag no longer functions
#![doc(no_default_passes)]
//~^ ERROR unknown `doc` attribute `no_default_passes`
diff --git a/tests/rustdoc-ui/deprecated-attrs.stderr b/tests/rustdoc-ui/deprecated-attrs.stderr
index a30523e..3e98205 100644
--- a/tests/rustdoc-ui/deprecated-attrs.stderr
+++ b/tests/rustdoc-ui/deprecated-attrs.stderr
@@ -4,7 +4,7 @@
= help: you may want to use --document-private-items
error: unknown `doc` attribute `no_default_passes`
- --> $DIR/deprecated-attrs.rs:4:8
+ --> $DIR/deprecated-attrs.rs:3:8
|
LL | #![doc(no_default_passes)]
| ^^^^^^^^^^^^^^^^^ no longer functions
@@ -15,7 +15,7 @@
= note: `#[deny(invalid_doc_attributes)]` on by default
error: unknown `doc` attribute `passes`
- --> $DIR/deprecated-attrs.rs:11:8
+ --> $DIR/deprecated-attrs.rs:10:8
|
LL | #![doc(passes = "collapse-docs unindent-comments")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no longer functions
@@ -25,7 +25,7 @@
= note: `doc(passes)` is now a no-op
error: unknown `doc` attribute `plugins`
- --> $DIR/deprecated-attrs.rs:17:8
+ --> $DIR/deprecated-attrs.rs:16:8
|
LL | #![doc(plugins = "xxx")]
| ^^^^^^^^^^^^^^^ no longer functions
diff --git a/tests/rustdoc-ui/doc-cfg-unstable.rs b/tests/rustdoc-ui/doc-cfg-unstable.rs
index 14c2e83..b77c365 100644
--- a/tests/rustdoc-ui/doc-cfg-unstable.rs
+++ b/tests/rustdoc-ui/doc-cfg-unstable.rs
@@ -1,10 +1,6 @@
// #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))`
#![feature(doc_cfg)]
-// `cfg_boolean_literals`
-#[doc(cfg(false))] //~ ERROR `cfg(false)` is experimental and subject to change
-pub fn cfg_boolean_literals() {}
-
// `cfg_version`
#[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change
pub fn cfg_sanitize() {}
diff --git a/tests/rustdoc-ui/doc-cfg-unstable.stderr b/tests/rustdoc-ui/doc-cfg-unstable.stderr
index 54de3b1..9651c5f 100644
--- a/tests/rustdoc-ui/doc-cfg-unstable.stderr
+++ b/tests/rustdoc-ui/doc-cfg-unstable.stderr
@@ -1,15 +1,5 @@
-error[E0658]: `cfg(false)` is experimental and subject to change
- --> $DIR/doc-cfg-unstable.rs:5:11
- |
-LL | #[doc(cfg(false))]
- | ^^^^^
- |
- = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
- = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
error[E0658]: `cfg(sanitize)` is experimental and subject to change
- --> $DIR/doc-cfg-unstable.rs:9:11
+ --> $DIR/doc-cfg-unstable.rs:5:11
|
LL | #[doc(cfg(sanitize = "thread"))]
| ^^^^^^^^^^^^^^^^^^^
@@ -18,6 +8,6 @@
= help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs
index d8c4310..1ed6769 100644
--- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs
+++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs
@@ -1,7 +1,8 @@
// FIXME: if/when the output of the test harness can be tested on its own, this test should be
// adapted to use that, and that normalize line can go away
-//@ compile-flags:--test --edition 2021
+//@ compile-flags: --test
+//@ edition: 2021
//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
//@ failure-status: 101
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout
index 63d987d..9f4d60e 100644
--- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout
+++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout
@@ -1,14 +1,14 @@
running 1 test
-test $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) ... FAILED
+test $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) ... FAILED
failures:
----- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) stdout ----
+---- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) stdout ----
Test executable succeeded, but it's marked `should_panic`.
failures:
- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9)
+ $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10)
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout
index 90c0463..2b04b77 100644
--- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout
+++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout
@@ -5,7 +5,7 @@
failures:
---- $DIR/failed-doctest-should-panic.rs - Foo (line 10) stdout ----
-note: test did not panic as expected
+note: test did not panic as expected at $DIR/failed-doctest-should-panic.rs:10:0
failures:
$DIR/failed-doctest-should-panic.rs - Foo (line 10)
diff --git a/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs b/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs
index 636c3c8..bcfb790 100644
--- a/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs
+++ b/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs
@@ -3,7 +3,8 @@
//@ check-pass
//@ aux-build: inner-crate-doc.rs
-//@ compile-flags: --extern inner_crate_doc --edition 2018
+//@ compile-flags: --extern inner_crate_doc
+//@ edition: 2018
/// Import doc comment [inner_crate_doc]
#[doc(inline)]
diff --git a/tests/rustdoc-ui/invalid-theme-name.rs b/tests/rustdoc-ui/invalid-theme-name.rs
index 7f1d191..22b5e61 100644
--- a/tests/rustdoc-ui/invalid-theme-name.rs
+++ b/tests/rustdoc-ui/invalid-theme-name.rs
@@ -1,4 +1,4 @@
//@ compile-flags:--theme {{src-base}}/invalid-theme-name.rs
-//@ error-pattern: must have a .css extension
//~? ERROR invalid argument: "$DIR/invalid-theme-name.rs"
+//~? HELP must have a .css extension
diff --git a/tests/rustdoc/anon-fn-params.rs b/tests/rustdoc/anon-fn-params.rs
new file mode 100644
index 0000000..9af1af3
--- /dev/null
+++ b/tests/rustdoc/anon-fn-params.rs
@@ -0,0 +1,25 @@
+// Test that we render the deprecated anonymous trait function parameters from Rust 2015 as
+// underscores in order not to perpetuate it and for legibility.
+
+//@ edition: 2015
+#![expect(anonymous_parameters)]
+
+// Check the "local case" (HIR cleaning) //
+
+//@ has anon_fn_params/trait.Trait.html
+pub trait Trait {
+ //@ has - '//*[@id="tymethod.required"]' 'fn required(_: Option<i32>, _: impl Fn(&str) -> bool)'
+ fn required(Option<i32>, impl Fn(&str) -> bool);
+ //@ has - '//*[@id="method.provided"]' 'fn provided(_: [i32; 2])'
+ fn provided([i32; 2]) {}
+}
+
+// Check the "extern case" (middle cleaning) //
+
+//@ aux-build: ext-anon-fn-params.rs
+extern crate ext_anon_fn_params;
+
+//@ has anon_fn_params/trait.ExtTrait.html
+//@ has - '//*[@id="tymethod.required"]' 'fn required(_: Option<i32>, _: impl Fn(&str) -> bool)'
+//@ has - '//*[@id="method.provided"]' 'fn provided(_: [i32; 2])'
+pub use ext_anon_fn_params::Trait as ExtTrait;
diff --git a/tests/rustdoc/assoc-fns.rs b/tests/rustdoc/assoc-fns.rs
new file mode 100644
index 0000000..6ffbebc
--- /dev/null
+++ b/tests/rustdoc/assoc-fns.rs
@@ -0,0 +1,13 @@
+// Basic testing for associated functions (in traits, trait impls & inherent impls).
+
+//@ has assoc_fns/trait.Trait.html
+pub trait Trait {
+ //@ has - '//*[@id="tymethod.required"]' 'fn required(first: i32, second: &str)'
+ fn required(first: i32, second: &str);
+
+ //@ has - '//*[@id="method.provided"]' 'fn provided(only: ())'
+ fn provided(only: ()) {}
+
+ //@ has - '//*[@id="tymethod.params_are_unnamed"]' 'fn params_are_unnamed(_: i32, _: u32)'
+ fn params_are_unnamed(_: i32, _: u32);
+}
diff --git a/tests/rustdoc/auxiliary/ext-anon-fn-params.rs b/tests/rustdoc/auxiliary/ext-anon-fn-params.rs
new file mode 100644
index 0000000..1acb919
--- /dev/null
+++ b/tests/rustdoc/auxiliary/ext-anon-fn-params.rs
@@ -0,0 +1,7 @@
+//@ edition: 2015
+#![expect(anonymous_parameters)]
+
+pub trait Trait {
+ fn required(Option<i32>, impl Fn(&str) -> bool);
+ fn provided([i32; 2]) {}
+}
diff --git a/tests/rustdoc/auxiliary/ext-trait-aliases.rs b/tests/rustdoc/auxiliary/ext-trait-aliases.rs
new file mode 100644
index 0000000..8454c04
--- /dev/null
+++ b/tests/rustdoc/auxiliary/ext-trait-aliases.rs
@@ -0,0 +1,13 @@
+#![feature(trait_alias)]
+
+pub trait ExtAlias0 = Copy + Iterator<Item = u8>;
+
+pub trait ExtAlias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>;
+
+pub trait ExtAlias2<T> = where T: From<String>, String: Into<T>;
+
+pub trait ExtAlias3 = Sized;
+
+pub trait ExtAlias4 = where Self: Sized;
+
+pub trait ExtAlias5 = ;
diff --git a/tests/rustdoc/auxiliary/primitive-doc.rs b/tests/rustdoc/auxiliary/primitive-doc.rs
index a7253ed..859716c 100644
--- a/tests/rustdoc/auxiliary/primitive-doc.rs
+++ b/tests/rustdoc/auxiliary/primitive-doc.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: --crate-type lib --edition 2018
+//@ compile-flags: --crate-type lib
+//@ edition: 2018
#![feature(rustc_attrs)]
#![feature(no_core)]
diff --git a/tests/rustdoc/auxiliary/primitive-reexport.rs b/tests/rustdoc/auxiliary/primitive-reexport.rs
index 18b5703..7c85038 100644
--- a/tests/rustdoc/auxiliary/primitive-reexport.rs
+++ b/tests/rustdoc/auxiliary/primitive-reexport.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: --emit metadata --crate-type lib --edition 2018
+//@ compile-flags: --emit metadata --crate-type lib
+//@ edition: 2018
#![crate_name = "foo"]
diff --git a/tests/rustdoc/auxiliary/trait-alias-mention.rs b/tests/rustdoc/auxiliary/trait-alias-mention.rs
deleted file mode 100644
index 6df06c8..0000000
--- a/tests/rustdoc/auxiliary/trait-alias-mention.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![feature(trait_alias)]
-
-pub trait SomeAlias = std::fmt::Debug + std::marker::Copy;
diff --git a/tests/rustdoc/ffi.rs b/tests/rustdoc/ffi.rs
index 5ba7cdb..524fb0e 100644
--- a/tests/rustdoc/ffi.rs
+++ b/tests/rustdoc/ffi.rs
@@ -9,4 +9,8 @@
extern "C" {
//@ has ffi/fn.another.html //pre 'pub unsafe extern "C" fn another(cold_as_ice: u32)'
pub fn another(cold_as_ice: u32);
+
+ //@ has ffi/fn.params_are_unnamed.html //pre \
+ // 'pub unsafe extern "C" fn params_are_unnamed(_: i32, _: u32)'
+ pub fn params_are_unnamed(_: i32, _: u32);
}
diff --git a/tests/rustdoc/inline_cross/auxiliary/fn-type.rs b/tests/rustdoc/inline_cross/auxiliary/fn-ptr-ty.rs
similarity index 100%
rename from tests/rustdoc/inline_cross/auxiliary/fn-type.rs
rename to tests/rustdoc/inline_cross/auxiliary/fn-ptr-ty.rs
diff --git a/tests/rustdoc/inline_cross/default-generic-args.rs b/tests/rustdoc/inline_cross/default-generic-args.rs
index 0469221..5124fbd 100644
--- a/tests/rustdoc/inline_cross/default-generic-args.rs
+++ b/tests/rustdoc/inline_cross/default-generic-args.rs
@@ -53,17 +53,17 @@
//@ has user/type.H0.html
// Check that we handle higher-ranked regions correctly:
-//@ has - '//*[@class="rust item-decl"]//code' "fn(_: for<'a> fn(_: Re<'a>))"
+//@ has - '//*[@class="rust item-decl"]//code' "fn(for<'a> fn(Re<'a>))"
pub use default_generic_args::H0;
//@ has user/type.H1.html
// Check that we don't conflate distinct universially quantified regions (#1):
-//@ has - '//*[@class="rust item-decl"]//code' "for<'b> fn(_: for<'a> fn(_: Re<'a, &'b ()>))"
+//@ has - '//*[@class="rust item-decl"]//code' "for<'b> fn(for<'a> fn(Re<'a, &'b ()>))"
pub use default_generic_args::H1;
//@ has user/type.H2.html
// Check that we don't conflate distinct universially quantified regions (#2):
-//@ has - '//*[@class="rust item-decl"]//code' "for<'a> fn(_: for<'b> fn(_: Re<'a, &'b ()>))"
+//@ has - '//*[@class="rust item-decl"]//code' "for<'a> fn(for<'b> fn(Re<'a, &'b ()>))"
pub use default_generic_args::H2;
//@ has user/type.P0.html
@@ -86,7 +86,7 @@
// Demonstrates that we currently don't elide generic arguments that are alpha-equivalent to their
// respective generic parameter (after instantiation) for perf reasons (it would require us to
// create an inference context).
-//@ has - '//*[@class="rust item-decl"]//code' "Alpha<for<'arbitrary> fn(_: &'arbitrary ())>"
+//@ has - '//*[@class="rust item-decl"]//code' "Alpha<for<'arbitrary> fn(&'arbitrary ())>"
pub use default_generic_args::A1;
//@ has user/type.M0.html
diff --git a/tests/rustdoc/inline_cross/fn-type.rs b/tests/rustdoc/inline_cross/fn-ptr-ty.rs
similarity index 71%
rename from tests/rustdoc/inline_cross/fn-type.rs
rename to tests/rustdoc/inline_cross/fn-ptr-ty.rs
index 8db6f65..0105962 100644
--- a/tests/rustdoc/inline_cross/fn-type.rs
+++ b/tests/rustdoc/inline_cross/fn-ptr-ty.rs
@@ -2,11 +2,11 @@
// They should be rendered exactly as the user wrote it, i.e., in source order and with unused
// parameters present, not stripped.
-//@ aux-crate:fn_type=fn-type.rs
+//@ aux-crate:fn_ptr_ty=fn-ptr-ty.rs
//@ edition: 2021
#![crate_name = "user"]
//@ has user/type.F.html
//@ has - '//*[@class="rust item-decl"]//code' \
-// "for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a ();"
-pub use fn_type::F;
+// "for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a ();"
+pub use fn_ptr_ty::F;
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
index e6baf33..468ac08 100644
--- a/tests/rustdoc/inline_cross/impl_trait.rs
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -29,7 +29,7 @@
//@ has impl_trait/fn.func5.html
//@ has - '//pre[@class="rust item-decl"]' "func5("
//@ has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
-//@ has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
+//@ has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>"
//@ !has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func5;
diff --git a/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
index 7cec30c..30834bd 100644
--- a/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
+++ b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
@@ -6,7 +6,8 @@
//@ aux-build:empty2.rs
//@ aux-crate:priv:empty2=empty2.rs
//@ build-aux-docs
-//@ compile-flags:-Z unstable-options --edition 2018
+//@ compile-flags:-Z unstable-options
+//@ edition: 2018
//@ has extern_crate_only_used_in_link/index.html
//@ has - '//a[@href="../issue_66159_1/struct.Something.html"]' 'issue_66159_1::Something'
diff --git a/tests/rustdoc/primitive-reexport.rs b/tests/rustdoc/primitive-reexport.rs
index eb25574..9b23b24 100644
--- a/tests/rustdoc/primitive-reexport.rs
+++ b/tests/rustdoc/primitive-reexport.rs
@@ -1,5 +1,6 @@
//@ aux-build: primitive-reexport.rs
-//@ compile-flags:--extern foo --edition 2018
+//@ compile-flags: --extern foo
+//@ edition: 2018
#![crate_name = "bar"]
diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive-slice-auto-trait.rs
index e78d1d9..647c1cc 100644
--- a/tests/rustdoc/primitive-slice-auto-trait.rs
+++ b/tests/rustdoc/primitive-slice-auto-trait.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: --crate-type lib --edition 2018
+//@ compile-flags: --crate-type lib
+//@ edition: 2018
#![crate_name = "foo"]
#![feature(rustc_attrs)]
diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive-tuple-auto-trait.rs
index 045478e..51300bd 100644
--- a/tests/rustdoc/primitive-tuple-auto-trait.rs
+++ b/tests/rustdoc/primitive-tuple-auto-trait.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: --crate-type lib --edition 2018
+//@ compile-flags: --crate-type lib
+//@ edition: 2018
#![crate_name = "foo"]
#![feature(rustc_attrs)]
diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs
index d142729..bab5eaa 100644
--- a/tests/rustdoc/primitive-tuple-variadic.rs
+++ b/tests/rustdoc/primitive-tuple-variadic.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: --crate-type lib --edition 2018
+//@ compile-flags: --crate-type lib
+//@ edition: 2018
#![crate_name = "foo"]
#![feature(rustdoc_internals)]
diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive-unit-auto-trait.rs
index 6cae094..7dada1f 100644
--- a/tests/rustdoc/primitive-unit-auto-trait.rs
+++ b/tests/rustdoc/primitive-unit-auto-trait.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: --crate-type lib --edition 2018
+//@ compile-flags: --crate-type lib
+//@ edition: 2018
#![crate_name = "foo"]
#![feature(rustc_attrs)]
diff --git a/tests/rustdoc/trait-alias-mention.rs b/tests/rustdoc/trait-alias-mention.rs
deleted file mode 100644
index b6ef926..0000000
--- a/tests/rustdoc/trait-alias-mention.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ aux-build:trait-alias-mention.rs
-//@ build-aux-docs
-
-#![crate_name = "foo"]
-
-extern crate trait_alias_mention;
-
-//@ has foo/fn.mention_alias_in_bounds.html '//a[@href="../trait_alias_mention/traitalias.SomeAlias.html"]' 'SomeAlias'
-pub fn mention_alias_in_bounds<T: trait_alias_mention::SomeAlias>() {
-}
diff --git a/tests/rustdoc/trait-aliases.rs b/tests/rustdoc/trait-aliases.rs
new file mode 100644
index 0000000..1be93f7
--- /dev/null
+++ b/tests/rustdoc/trait-aliases.rs
@@ -0,0 +1,82 @@
+// Basic testing for trait aliases.
+#![feature(trait_alias)]
+#![crate_name = "it"]
+
+// Check the "local case" (HIR cleaning) //
+
+//@ has it/all.html '//a[@href="traitalias.Alias0.html"]' 'Alias0'
+//@ has it/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases'
+//@ has it/index.html '//a[@class="traitalias"]' 'Alias0'
+//@ has it/traitalias.Alias0.html
+//@ has - '//*[@class="rust item-decl"]//code' 'trait Alias0 = Copy + Iterator<Item = u8>;'
+pub trait Alias0 = Copy + Iterator<Item = u8>;
+
+//@ has it/traitalias.Alias1.html
+//@ has - '//pre[@class="rust item-decl"]' \
+// "trait Alias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>;"
+pub trait Alias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>;
+
+//@ has it/traitalias.Alias2.html
+//@ has - '//pre[@class="rust item-decl"]' \
+// 'trait Alias2<T> = where T: From<String>, String: Into<T>;'
+pub trait Alias2<T> = where T: From<String>, String: Into<T>;
+
+//@ has it/traitalias.Alias3.html
+//@ has - '//pre[@class="rust item-decl"]' 'trait Alias3 = ;'
+pub trait Alias3 =;
+
+//@ has it/traitalias.Alias4.html
+//@ has - '//pre[@class="rust item-decl"]' 'trait Alias4 = ;'
+pub trait Alias4 = where;
+
+//@ has it/fn.usage0.html
+//@ has - '//pre[@class="rust item-decl"]' "pub fn usage0(_: impl Alias0)"
+//@ has - '//a[@href="traitalias.Alias0.html"]' 'Alias0'
+pub fn usage0(_: impl Alias0) {}
+
+// FIXME: One can only "disambiguate" intra-doc links to trait aliases with `type@` but not with
+// `trait@` (fails to resolve) or `traitalias@` (doesn't exist). We should make at least one of
+// the latter two work, right?
+
+//@ has it/link0/index.html
+//@ has - '//a/@href' 'traitalias.Alias0.html'
+//@ has - '//a/@href' 'traitalias.Alias1.html'
+/// [Alias0], [type@Alias1]
+pub mod link0 {}
+
+// Check the "extern case" (middle cleaning) //
+
+//@ aux-build: ext-trait-aliases.rs
+extern crate ext_trait_aliases as ext;
+
+//@ has it/traitalias.ExtAlias0.html
+//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias0 = Copy + Iterator<Item = u8>;'
+pub use ext::ExtAlias0;
+
+//@ has it/traitalias.ExtAlias1.html
+//@ has - '//pre[@class="rust item-decl"]' \
+// "trait ExtAlias1<'a, T, const N: usize> = From<[&'a T; N]> where T: 'a + Clone;"
+pub use ext::ExtAlias1;
+
+//@ has it/traitalias.ExtAlias2.html
+//@ has - '//pre[@class="rust item-decl"]' \
+// 'trait ExtAlias2<T> = where T: From<String>, String: Into<T>;'
+pub use ext::ExtAlias2;
+
+//@ has it/traitalias.ExtAlias3.html
+//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias3 = Sized;'
+pub use ext::ExtAlias3;
+
+// NOTE: Middle cleaning can't discern `= Sized` and `= where Self: Sized` and that's okay.
+//@ has it/traitalias.ExtAlias4.html
+//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias4 = Sized;'
+pub use ext::ExtAlias4;
+
+//@ has it/traitalias.ExtAlias5.html
+//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias5 = ;'
+pub use ext::ExtAlias5;
+
+//@ has it/fn.usage1.html
+//@ has - '//pre[@class="rust item-decl"]' "pub fn usage1(_: impl ExtAlias0)"
+//@ has - '//a[@href="traitalias.ExtAlias0.html"]' 'ExtAlias0'
+pub fn usage1(_: impl ExtAlias0) {}
diff --git a/tests/rustdoc/trait_alias.rs b/tests/rustdoc/trait_alias.rs
deleted file mode 100644
index bfdb9d4..0000000
--- a/tests/rustdoc/trait_alias.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#![feature(trait_alias)]
-
-#![crate_name = "foo"]
-
-use std::fmt::Debug;
-
-//@ has foo/all.html '//a[@href="traitalias.CopyAlias.html"]' 'CopyAlias'
-//@ has foo/all.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
-//@ has foo/all.html '//a[@href="traitalias.Foo.html"]' 'Foo'
-
-//@ has foo/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases'
-//@ has foo/index.html '//a[@class="traitalias"]' 'CopyAlias'
-//@ has foo/index.html '//a[@class="traitalias"]' 'Alias2'
-//@ has foo/index.html '//a[@class="traitalias"]' 'Foo'
-
-//@ has foo/traitalias.CopyAlias.html
-//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait CopyAlias = Copy;'
-pub trait CopyAlias = Copy;
-//@ has foo/traitalias.Alias2.html
-//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Alias2 = Copy + Debug;'
-pub trait Alias2 = Copy + Debug;
-//@ has foo/traitalias.Foo.html
-//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Foo<T> = Into<T> + Debug;'
-pub trait Foo<T> = Into<T> + Debug;
-//@ has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
-pub fn bar<T>() where T: Alias2 {}
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs
index 442f9d7..1238fef 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs
@@ -15,7 +15,7 @@
use rustc_errors::{
Diag, DiagCtxtHandle, DiagInner, DiagMessage, Diagnostic, EmissionGuarantee, Level,
- LintDiagnostic, SubdiagMessage, SubdiagMessageOp, Subdiagnostic,
+ LintDiagnostic, SubdiagMessage, Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span;
@@ -56,10 +56,9 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
pub struct UntranslatableInAddtoDiag;
impl Subdiagnostic for UntranslatableInAddtoDiag {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+ fn add_to_diag<G: EmissionGuarantee>(
self,
diag: &mut Diag<'_, G>,
- f: &F,
) {
diag.note("untranslatable diagnostic");
//~^ ERROR diagnostics should be created using translatable messages
@@ -69,10 +68,9 @@ fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
pub struct TranslatableInAddtoDiag;
impl Subdiagnostic for TranslatableInAddtoDiag {
- fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+ fn add_to_diag<G: EmissionGuarantee>(
self,
diag: &mut Diag<'_, G>,
- f: &F,
) {
diag.note(crate::fluent_generated::no_crate_note);
}
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
index 36dd3cf..b260c4b 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -11,19 +11,19 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:64:19
+ --> $DIR/diagnostics.rs:63:19
|
LL | diag.note("untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:85:19
+ --> $DIR/diagnostics.rs:83:19
|
LL | diag.note("untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
- --> $DIR/diagnostics.rs:99:21
+ --> $DIR/diagnostics.rs:97:21
|
LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example);
| ^^^^^^^^^^
@@ -35,37 +35,37 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
- --> $DIR/diagnostics.rs:102:21
+ --> $DIR/diagnostics.rs:100:21
|
LL | let _diag = dcx.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:102:32
+ --> $DIR/diagnostics.rs:100:32
|
LL | let _diag = dcx.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:120:7
+ --> $DIR/diagnostics.rs:118:7
|
LL | f("untranslatable diagnostic", crate::fluent_generated::no_crate_example);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:122:50
+ --> $DIR/diagnostics.rs:120:50
|
LL | f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:124:7
+ --> $DIR/diagnostics.rs:122:7
|
LL | f("untranslatable diagnostic", "untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:124:36
+ --> $DIR/diagnostics.rs:122:36
|
LL | f("untranslatable diagnostic", "untranslatable diagnostic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.rs b/tests/ui-fulldeps/missing-rustc-driver-error.rs
index d582efa..c6dff2d 100644
--- a/tests/ui-fulldeps/missing-rustc-driver-error.rs
+++ b/tests/ui-fulldeps/missing-rustc-driver-error.rs
@@ -1,11 +1,15 @@
// Test that we get the following hint when trying to use a compiler crate without rustc_driver.
-//@ error-pattern: try adding `extern crate rustc_driver;` at the top level of this crate
-//@ compile-flags: --emit link --error-format=human
+//@ compile-flags: --emit link
//@ normalize-stderr: ".*crate .* required.*\n\n" -> ""
//@ normalize-stderr: "aborting due to [0-9]+" -> "aborting due to NUMBER"
+//@ dont-require-annotations: ERROR
#![feature(rustc_private)]
extern crate rustc_serialize;
fn main() {}
+
+//~? HELP try adding `extern crate rustc_driver;` at the top level of this crate
+//~? HELP try adding `extern crate rustc_driver;` at the top level of this crate
+//~? HELP try adding `extern crate rustc_driver;` at the top level of this crate
diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs
index ef2d5b4..ebf2e33 100644
--- a/tests/ui-fulldeps/stable-mir/check_abi.rs
+++ b/tests/ui-fulldeps/stable-mir/check_abi.rs
@@ -17,7 +17,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::abi::{
ArgAbi, CallConvention, FieldsShape, IntegerLength, PassMode, Primitive, Scalar, ValueAbi,
VariantsShape,
diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs
index c102f86..ae2609b 100644
--- a/tests/ui-fulldeps/stable-mir/check_allocation.rs
+++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs
@@ -19,7 +19,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::crate_def::CrateDef;
use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef};
diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
index f6f8955..9d61154 100644
--- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
+++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
@@ -17,7 +17,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use std::io::Write;
use std::collections::HashSet;
use stable_mir::CrateDef;
@@ -51,7 +50,7 @@ fn test_assoc_items() -> ControlFlow<()> {
check_items(
&trait_assoc_item_defs,
&[
- "ATrait::{synthetic#0}",
+ "ATrait::{anon_assoc#0}",
"ATrait::rpitit",
"ATrait::Assoc",
"ATrait::assoc_fn_no_self",
@@ -64,7 +63,7 @@ fn test_assoc_items() -> ControlFlow<()> {
check_items(
&impl_assoc_item_defs,
&[
- "<AStruct as ATrait>::{synthetic#0}",
+ "<AStruct as ATrait>::{anon_assoc#0}",
"<AStruct as ATrait>::rpitit",
"<AStruct as ATrait>::Assoc",
"<AStruct as ATrait>::assoc_fn_no_self",
diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs
index de5ba15..4148fc0 100644
--- a/tests/ui-fulldeps/stable-mir/check_attribute.rs
+++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs
@@ -15,7 +15,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::{CrateDef, CrateItems};
use std::io::Write;
use std::ops::ControlFlow;
diff --git a/tests/ui-fulldeps/stable-mir/check_binop.rs b/tests/ui-fulldeps/stable-mir/check_binop.rs
index 65b3ffd..6a141e9 100644
--- a/tests/ui-fulldeps/stable-mir/check_binop.rs
+++ b/tests/ui-fulldeps/stable-mir/check_binop.rs
@@ -15,7 +15,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::mir::mono::Instance;
use stable_mir::mir::visit::{Location, MirVisitor};
use stable_mir::mir::{LocalDecl, Rvalue, Statement, StatementKind, Terminator, TerminatorKind};
diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
index 71cca94..31c4719 100644
--- a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
+++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
@@ -16,7 +16,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::CrateDef;
use std::collections::HashSet;
use std::io::Write;
diff --git a/tests/ui-fulldeps/stable-mir/check_def_ty.rs b/tests/ui-fulldeps/stable-mir/check_def_ty.rs
index 37b9a83..00a34f1 100644
--- a/tests/ui-fulldeps/stable-mir/check_def_ty.rs
+++ b/tests/ui-fulldeps/stable-mir/check_def_ty.rs
@@ -17,7 +17,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::ty::{Ty, ForeignItemKind};
use stable_mir::*;
use std::io::Write;
diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs
index cd3d76d..1ba7337 100644
--- a/tests/ui-fulldeps/stable-mir/check_defs.rs
+++ b/tests/ui-fulldeps/stable-mir/check_defs.rs
@@ -19,7 +19,6 @@
use std::assert_matches::assert_matches;
use mir::{mono::Instance, TerminatorKind::*};
use stable_mir::mir::mono::InstanceKind;
-use rustc_smir::rustc_internal;
use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy};
use stable_mir::*;
use std::io::Write;
diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs
index bc3956b..4419050 100644
--- a/tests/ui-fulldeps/stable-mir/check_foreign.rs
+++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs
@@ -17,7 +17,6 @@
extern crate rustc_span;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::{
ty::{Abi, ForeignItemKind},
*,
diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs
index 72a138f..1510a62 100644
--- a/tests/ui-fulldeps/stable-mir/check_instance.rs
+++ b/tests/ui-fulldeps/stable-mir/check_instance.rs
@@ -21,7 +21,6 @@
use mir::mono::Instance;
use mir::TerminatorKind::*;
-use rustc_smir::rustc_internal;
use stable_mir::ty::{RigidTy, TyKind};
use stable_mir::*;
diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
index 07a2a62..3f04abb 100644
--- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
+++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
@@ -20,7 +20,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::mir::mono::{Instance, InstanceKind};
use stable_mir::mir::visit::{Location, MirVisitor};
use stable_mir::mir::{LocalDecl, Terminator, TerminatorKind};
diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs
index 647ce53..bb8c00c 100644
--- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs
+++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs
@@ -16,7 +16,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::*;
use std::io::Write;
use std::ops::ControlFlow;
diff --git a/tests/ui-fulldeps/stable-mir/check_normalization.rs b/tests/ui-fulldeps/stable-mir/check_normalization.rs
index de14202..797cb4c 100644
--- a/tests/ui-fulldeps/stable-mir/check_normalization.rs
+++ b/tests/ui-fulldeps/stable-mir/check_normalization.rs
@@ -17,7 +17,6 @@
use mir::mono::Instance;
use ty::{Ty, TyKind, RigidTy};
-use rustc_smir::rustc_internal;
use stable_mir::*;
use std::io::Write;
use std::ops::ControlFlow;
diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs
index 23c2844..d9170d0 100644
--- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs
+++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs
@@ -16,7 +16,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::CrateDef;
use std::collections::HashSet;
use std::io::Write;
diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs
index d9fc924..604cc72 100644
--- a/tests/ui-fulldeps/stable-mir/check_transform.rs
+++ b/tests/ui-fulldeps/stable-mir/check_transform.rs
@@ -17,7 +17,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::mir::mono::Instance;
use stable_mir::mir::{Body, ConstOperand, Operand, Rvalue, StatementKind, TerminatorKind};
diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
index 9d71697..23233f8 100644
--- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
+++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
@@ -17,7 +17,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::mir::{
Body, FieldIdx, MirVisitor, Place, ProjectionElem,
visit::{Location, PlaceContext},
diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs
index b8a9e72..3941663 100644
--- a/tests/ui-fulldeps/stable-mir/compilation-result.rs
+++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs
@@ -16,7 +16,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use std::io::Write;
/// This test will generate and analyze a dummy crate using the stable mir.
diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs
index 4d2d7e2..e2086d5 100644
--- a/tests/ui-fulldeps/stable-mir/crate-info.rs
+++ b/tests/ui-fulldeps/stable-mir/crate-info.rs
@@ -18,7 +18,6 @@
extern crate stable_mir;
use rustc_hir::def::DefKind;
-use rustc_smir::rustc_internal;
use stable_mir::ItemKind;
use stable_mir::crate_def::CrateDef;
use stable_mir::mir::mono::Instance;
diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs
index 6f82eba..f3bd894 100644
--- a/tests/ui-fulldeps/stable-mir/projections.rs
+++ b/tests/ui-fulldeps/stable-mir/projections.rs
@@ -17,7 +17,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::ItemKind;
use stable_mir::crate_def::CrateDef;
use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs
index 9b3638a..3b3d743 100644
--- a/tests/ui-fulldeps/stable-mir/smir_serde.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs
@@ -19,7 +19,6 @@
extern crate stable_mir;
use rustc_middle::ty::TyCtxt;
-use rustc_smir::rustc_internal;
use serde_json::to_string;
use stable_mir::mir::Body;
use std::io::{BufWriter, Write};
diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
index 0a579a0..d225d97 100644
--- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
@@ -16,7 +16,6 @@
extern crate rustc_interface;
extern crate stable_mir;
-use rustc_smir::rustc_internal;
use stable_mir::mir::MirVisitor;
use stable_mir::mir::MutMirVisitor;
use stable_mir::*;
diff --git a/tests/ui/README.md b/tests/ui/README.md
deleted file mode 100644
index aa36481..0000000
--- a/tests/ui/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# UI Tests
-
-This folder contains `rustc`'s
-[UI tests](https://rustc-dev-guide.rust-lang.org/tests/ui.html).
-
-## Test Directives (Headers)
-
-Typically, a UI test will have some test directives / headers which are
-special comments that tell compiletest how to build and interpret a test.
-
-As part of an ongoing effort to rewrite compiletest
-(see <https://github.com/rust-lang/compiler-team/issues/536>), a major
-change proposal to change legacy compiletest-style headers `// <directive>`
-to [`ui_test`](https://github.com/oli-obk/ui_test)-style headers
-`//@ <directive>` was accepted (see
-<https://github.com/rust-lang/compiler-team/issues/512>.
-
-An example directive is `ignore-test`. In legacy compiletest style, the header
-would be written as
-
-```rs
-// ignore-test
-```
-
-but in `ui_test` style, the header would be written as
-
-```rs
-//@ ignore-test
-```
-
-compiletest is changed to accept only `//@` directives for UI tests
-(currently), and will reject and report an error if it encounters any
-comments `// <content>` that may be parsed as a legacy compiletest-style
-test header. To fix this, you should migrate to the `ui_test`-style header
-`//@ <content>`.
diff --git a/tests/ui/abi/debug.rs b/tests/ui/abi/debug.rs
index 6dbc316..c0d8de0 100644
--- a/tests/ui/abi/debug.rs
+++ b/tests/ui/abi/debug.rs
@@ -52,3 +52,6 @@ fn assoc_test(&self) { } //~ ERROR: fn_abi
#[rustc_abi(assert_eq)]
type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time
+
+#[rustc_abi("assert_eq")] //~ ERROR unrecognized argument
+type Bad = u32;
diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr
index 2239ba0..480f3f0 100644
--- a/tests/ui/abi/debug.stderr
+++ b/tests/ui/abi/debug.stderr
@@ -906,6 +906,12 @@
= help: the trait `Sized` is not implemented for `str`
= note: only the last element of a tuple may have a dynamically sized type
+error: unrecognized argument
+ --> $DIR/debug.rs:56:13
+ |
+LL | #[rustc_abi("assert_eq")]
+ | ^^^^^^^^^^^
+
error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions
--> $DIR/debug.rs:29:5
|
@@ -1004,6 +1010,6 @@
LL | fn assoc_test(&self) { }
| ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/abi/fixed_x18.rs b/tests/ui/abi/fixed_x18.rs
index d373468..d64b845 100644
--- a/tests/ui/abi/fixed_x18.rs
+++ b/tests/ui/abi/fixed_x18.rs
@@ -2,7 +2,6 @@
// Behavior on aarch64 is tested by tests/codegen/fixed-x18.rs.
//
//@ revisions: x64 i686 arm riscv32 riscv64
-//@ error-pattern: the `-Zfixed-x18` flag is not supported
//@ dont-check-compiler-stderr
//
//@ compile-flags: -Zfixed-x18
diff --git a/tests/ui/asm/naked-functions-rustic-abi.rs b/tests/ui/asm/naked-functions-rustic-abi.rs
new file mode 100644
index 0000000..b654d38
--- /dev/null
+++ b/tests/ui/asm/naked-functions-rustic-abi.rs
@@ -0,0 +1,27 @@
+//@ revisions: x86_64 aarch64
+//
+//@[aarch64] only-aarch64
+//@[x86_64] only-x86_64
+//
+//@ build-pass
+//@ needs-asm-support
+
+#![feature(naked_functions, naked_functions_rustic_abi, rust_cold_cc)]
+#![crate_type = "lib"]
+
+use std::arch::{asm, naked_asm};
+
+#[naked]
+pub unsafe fn rust_implicit() {
+ naked_asm!("ret");
+}
+
+#[naked]
+pub unsafe extern "Rust" fn rust_explicit() {
+ naked_asm!("ret");
+}
+
+#[naked]
+pub unsafe extern "rust-cold" fn rust_cold() {
+ naked_asm!("ret");
+}
diff --git a/tests/ui/asm/naked-functions-testattrs.rs b/tests/ui/asm/naked-functions-testattrs.rs
index 7e37327..ad31876 100644
--- a/tests/ui/asm/naked-functions-testattrs.rs
+++ b/tests/ui/asm/naked-functions-testattrs.rs
@@ -1,7 +1,6 @@
//@ needs-asm-support
//@ compile-flags: --test
-#![allow(undefined_naked_function_abi)]
#![feature(naked_functions)]
#![feature(test)]
#![crate_type = "lib"]
@@ -11,7 +10,7 @@
#[test]
#[naked]
//~^ ERROR [E0736]
-fn test_naked() {
+extern "C" fn test_naked() {
unsafe { naked_asm!("") };
}
@@ -19,7 +18,7 @@ fn test_naked() {
#[test]
#[naked]
//~^ ERROR [E0736]
-fn test_naked_should_panic() {
+extern "C" fn test_naked_should_panic() {
unsafe { naked_asm!("") };
}
@@ -27,13 +26,13 @@ fn test_naked_should_panic() {
#[test]
#[naked]
//~^ ERROR [E0736]
-fn test_naked_ignore() {
+extern "C" fn test_naked_ignore() {
unsafe { naked_asm!("") };
}
#[bench]
#[naked]
//~^ ERROR [E0736]
-fn bench_naked() {
+extern "C" fn bench_naked() {
unsafe { naked_asm!("") };
}
diff --git a/tests/ui/asm/naked-functions-testattrs.stderr b/tests/ui/asm/naked-functions-testattrs.stderr
index 4dabe41..0f0bb91 100644
--- a/tests/ui/asm/naked-functions-testattrs.stderr
+++ b/tests/ui/asm/naked-functions-testattrs.stderr
@@ -1,5 +1,5 @@
error[E0736]: cannot use `#[naked]` with testing attributes
- --> $DIR/naked-functions-testattrs.rs:12:1
+ --> $DIR/naked-functions-testattrs.rs:11:1
|
LL | #[test]
| ------- function marked with testing attribute here
@@ -7,7 +7,7 @@
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes
error[E0736]: cannot use `#[naked]` with testing attributes
- --> $DIR/naked-functions-testattrs.rs:20:1
+ --> $DIR/naked-functions-testattrs.rs:19:1
|
LL | #[test]
| ------- function marked with testing attribute here
@@ -15,7 +15,7 @@
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes
error[E0736]: cannot use `#[naked]` with testing attributes
- --> $DIR/naked-functions-testattrs.rs:28:1
+ --> $DIR/naked-functions-testattrs.rs:27:1
|
LL | #[test]
| ------- function marked with testing attribute here
@@ -23,7 +23,7 @@
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes
error[E0736]: cannot use `#[naked]` with testing attributes
- --> $DIR/naked-functions-testattrs.rs:35:1
+ --> $DIR/naked-functions-testattrs.rs:34:1
|
LL | #[bench]
| -------- function marked with testing attribute here
diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs
index 3d4d414..8ba0eec 100644
--- a/tests/ui/asm/naked-functions.rs
+++ b/tests/ui/asm/naked-functions.rs
@@ -8,7 +8,7 @@
use std::arch::{asm, naked_asm};
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn inline_asm_macro() {
asm!("", options(raw));
//~^ERROR the `asm!` macro is not allowed in naked functions
@@ -20,7 +20,7 @@ pub struct P {
y: u16,
}
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn patterns(
mut a: u32,
//~^ ERROR patterns not allowed in naked function parameters
@@ -34,27 +34,27 @@ pub struct P {
naked_asm!("")
}
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn inc(a: u32) -> u32 {
//~^ ERROR naked functions must contain a single `naked_asm!` invocation
a + 1
//~^ ERROR referencing function parameters is not allowed in naked functions
}
-#[naked]
+#[unsafe(naked)]
#[allow(asm_sub_register)]
pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
naked_asm!("/* {0} */", in(reg) a)
//~^ ERROR the `in` operand cannot be used with `naked_asm!`
}
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
//~^ ERROR naked functions must contain a single `naked_asm!` invocation
(|| a + 1)()
}
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn unsupported_operands() {
//~^ ERROR naked functions must contain a single `naked_asm!` invocation
let mut a = 0usize;
@@ -76,12 +76,12 @@ pub struct P {
);
}
-#[naked]
+#[unsafe(naked)]
pub extern "C" fn missing_assembly() {
//~^ ERROR naked functions must contain a single `naked_asm!` invocation
}
-#[naked]
+#[unsafe(naked)]
pub extern "C" fn too_many_asm_blocks() {
//~^ ERROR naked functions must contain a single `naked_asm!` invocation
unsafe {
@@ -92,7 +92,7 @@ pub extern "C" fn too_many_asm_blocks() {
}
pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
- #[naked]
+ #[unsafe(naked)]
pub extern "C" fn inner(y: usize) -> usize {
//~^ ERROR naked functions must contain a single `naked_asm!` invocation
*&y
@@ -101,14 +101,14 @@ pub extern "C" fn inner(y: usize) -> usize {
inner
}
-#[naked]
+#[unsafe(naked)]
unsafe extern "C" fn invalid_options() {
naked_asm!("", options(nomem, preserves_flags));
//~^ ERROR the `nomem` option cannot be used with `naked_asm!`
//~| ERROR the `preserves_flags` option cannot be used with `naked_asm!`
}
-#[naked]
+#[unsafe(naked)]
unsafe extern "C" fn invalid_options_continued() {
naked_asm!("", options(readonly, nostack), options(pure));
//~^ ERROR the `readonly` option cannot be used with `naked_asm!`
@@ -116,32 +116,20 @@ pub extern "C" fn inner(y: usize) -> usize {
//~| ERROR the `pure` option cannot be used with `naked_asm!`
}
-#[naked]
+#[unsafe(naked)]
unsafe extern "C" fn invalid_may_unwind() {
naked_asm!("", options(may_unwind));
//~^ ERROR the `may_unwind` option cannot be used with `naked_asm!`
}
-#[naked]
-pub unsafe fn default_abi() {
- //~^ WARN Rust ABI is unsupported in naked functions
- naked_asm!("");
-}
-
-#[naked]
-pub unsafe fn rust_abi() {
- //~^ WARN Rust ABI is unsupported in naked functions
- naked_asm!("");
-}
-
-#[naked]
+#[unsafe(naked)]
pub extern "C" fn valid_a<T>() -> T {
unsafe {
naked_asm!("");
}
}
-#[naked]
+#[unsafe(naked)]
pub extern "C" fn valid_b() {
unsafe {
{
@@ -152,32 +140,32 @@ pub extern "C" fn valid_b() {
}
}
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn valid_c() {
naked_asm!("");
}
#[cfg(target_arch = "x86_64")]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn valid_att_syntax() {
naked_asm!("", options(att_syntax));
}
-#[naked]
-#[naked]
+#[unsafe(naked)]
+#[unsafe(naked)]
pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
compile_error!("this is a user specified error")
//~^ ERROR this is a user specified error
}
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 {
compile_error!("this is a user specified error");
//~^ ERROR this is a user specified error
naked_asm!("")
}
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 {
naked_asm!(invalid_syntax)
//~^ ERROR asm template must be a string literal
@@ -185,7 +173,7 @@ pub extern "C" fn valid_b() {
#[cfg(target_arch = "x86_64")]
#[cfg_attr(target_pointer_width = "64", no_mangle)]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_cfg_attributes() {
naked_asm!("", options(att_syntax));
}
@@ -194,20 +182,20 @@ pub extern "C" fn valid_b() {
#[warn(dead_code)]
#[deny(dead_code)]
#[forbid(dead_code)]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_diagnostic_attributes() {
naked_asm!("", options(raw));
}
#[deprecated = "test"]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_deprecated_attributes() {
naked_asm!("", options(raw));
}
#[cfg(target_arch = "x86_64")]
#[must_use]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 {
naked_asm!(
"
@@ -219,13 +207,13 @@ pub extern "C" fn valid_b() {
#[export_name = "exported_function_name"]
#[link_section = ".custom_section"]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_ffi_attributes_1() {
naked_asm!("", options(raw));
}
#[cold]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_codegen_attributes() {
naked_asm!("", options(raw));
}
@@ -234,13 +222,13 @@ pub extern "C" fn valid_b() {
/// a doc comment
// a normal comment
#[doc(alias = "ADocAlias")]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_doc_attributes() {
naked_asm!("", options(raw));
}
#[linkage = "external"]
-#[naked]
+#[unsafe(naked)]
pub unsafe extern "C" fn compatible_linkage() {
naked_asm!("", options(raw));
}
diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr
index 0898f36..0a55bb9 100644
--- a/tests/ui/asm/naked-functions.stderr
+++ b/tests/ui/asm/naked-functions.stderr
@@ -53,19 +53,19 @@
| ^^^^^^^^^^ the `may_unwind` option is not meaningful for global-scoped inline assembly
error: this is a user specified error
- --> $DIR/naked-functions.rs:169:5
+ --> $DIR/naked-functions.rs:157:5
|
LL | compile_error!("this is a user specified error")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this is a user specified error
- --> $DIR/naked-functions.rs:175:5
+ --> $DIR/naked-functions.rs:163:5
|
LL | compile_error!("this is a user specified error");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: asm template must be a string literal
- --> $DIR/naked-functions.rs:182:16
+ --> $DIR/naked-functions.rs:170:16
|
LL | naked_asm!(invalid_syntax)
| ^^^^^^^^^^^^^^
@@ -175,20 +175,6 @@
LL | *&y
| --- not allowed in naked functions
-warning: Rust ABI is unsupported in naked functions
- --> $DIR/naked-functions.rs:126:1
- |
-LL | pub unsafe fn default_abi() {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `#[warn(undefined_naked_function_abi)]` on by default
-
-warning: Rust ABI is unsupported in naked functions
- --> $DIR/naked-functions.rs:132:1
- |
-LL | pub unsafe fn rust_abi() {
- | ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 25 previous errors; 2 warnings emitted
+error: aborting due to 25 previous errors
For more information about this error, try `rustc --explain E0787`.
diff --git a/tests/ui/asm/unpretty-expanded.rs b/tests/ui/asm/unpretty-expanded.rs
index 1da2c77..3eb46fe 100644
--- a/tests/ui/asm/unpretty-expanded.rs
+++ b/tests/ui/asm/unpretty-expanded.rs
@@ -1,4 +1,5 @@
//@ needs-asm-support
//@ check-pass
//@ compile-flags: -Zunpretty=expanded
+//@ edition: 2015
core::arch::global_asm!("x: .byte 42");
diff --git a/tests/ui/asm/unpretty-expanded.stdout b/tests/ui/asm/unpretty-expanded.stdout
index 80ccd12..7ba1702 100644
--- a/tests/ui/asm/unpretty-expanded.stdout
+++ b/tests/ui/asm/unpretty-expanded.stdout
@@ -7,4 +7,5 @@
//@ needs-asm-support
//@ check-pass
//@ compile-flags: -Zunpretty=expanded
+//@ edition: 2015
global_asm! ("x: .byte 42");
diff --git a/tests/ui/associated-types/associated-type-macro.rs b/tests/ui/associated-types/associated-type-macro.rs
index 22b5bca..8586dc1 100644
--- a/tests/ui/associated-types/associated-type-macro.rs
+++ b/tests/ui/associated-types/associated-type-macro.rs
@@ -1,4 +1,4 @@
fn main() {
- #[cfg(FALSE)]
+ #[cfg(false)]
<() as module>::mac!(); //~ ERROR macros cannot use qualified paths
}
diff --git a/tests/ui/associated-types/issue-36499.rs b/tests/ui/associated-types/issue-36499.rs
index 606918b..941b1aa 100644
--- a/tests/ui/associated-types/issue-36499.rs
+++ b/tests/ui/associated-types/issue-36499.rs
@@ -1,5 +1,3 @@
-//@ error-pattern: aborting due to 1 previous error
-
fn main() {
2 + +2; //~ ERROR leading `+` is not supported
}
diff --git a/tests/ui/associated-types/issue-36499.stderr b/tests/ui/associated-types/issue-36499.stderr
index dd91bac..aebf0fa 100644
--- a/tests/ui/associated-types/issue-36499.stderr
+++ b/tests/ui/associated-types/issue-36499.stderr
@@ -1,5 +1,5 @@
error: leading `+` is not supported
- --> $DIR/issue-36499.rs:4:9
+ --> $DIR/issue-36499.rs:2:9
|
LL | 2 + +2;
| ^ unexpected `+`
diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs
index 069744a..12dca58 100644
--- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs
+++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: -Zvalidate-mir --edition=2018 --crate-type=lib -Copt-level=3
+//@ compile-flags: -Zvalidate-mir --crate-type=lib -Copt-level=3
+//@ edition: 2018
fn main() {}
diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr
index 52697ba..03fa220 100644
--- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr
+++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr
@@ -1,5 +1,5 @@
error[E0507]: cannot move out of `x` which is behind a mutable reference
- --> $DIR/closure-shim-borrowck-error.rs:10:18
+ --> $DIR/closure-shim-borrowck-error.rs:11:18
|
LL | needs_fn_mut(async || {
| ^^^^^^^^ `x` is moved here
@@ -11,7 +11,7 @@
| move occurs because `x` has type `Ty`, which does not implement the `Copy` trait
|
note: if `Ty` implemented `Clone`, you could clone the value
- --> $DIR/closure-shim-borrowck-error.rs:16:1
+ --> $DIR/closure-shim-borrowck-error.rs:17:1
|
LL | x.hello();
| - you could clone this value
diff --git a/tests/ui/async-await/async-gen-move-suggestion.fixed b/tests/ui/async-await/async-gen-move-suggestion.fixed
new file mode 100644
index 0000000..d802076
--- /dev/null
+++ b/tests/ui/async-await/async-gen-move-suggestion.fixed
@@ -0,0 +1,35 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/139839>.
+// It ensures that the "add `move` keyword" suggestion is valid.
+
+//@ run-rustfix
+//@ edition:2024
+
+#![feature(coroutines)]
+#![feature(gen_blocks)]
+#![feature(async_iterator)]
+
+use std::async_iter::AsyncIterator;
+
+#[allow(dead_code)]
+fn moved() -> impl AsyncIterator<Item = u32> {
+ let mut x = "foo".to_string();
+
+ async gen move { //~ ERROR
+ x.clear();
+ for x in 3..6 { yield x }
+ }
+}
+
+#[allow(dead_code)]
+fn check_with_whitespace_chars() -> impl AsyncIterator<Item = u32> {
+ let mut x = "foo".to_string();
+
+ async // Just to check that whitespace characters are correctly handled
+ gen move { //~^ ERROR
+ x.clear();
+ for x in 3..6 { yield x }
+ }
+}
+
+fn main() {
+}
diff --git a/tests/ui/async-await/async-gen-move-suggestion.rs b/tests/ui/async-await/async-gen-move-suggestion.rs
new file mode 100644
index 0000000..825fb0f
--- /dev/null
+++ b/tests/ui/async-await/async-gen-move-suggestion.rs
@@ -0,0 +1,35 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/139839>.
+// It ensures that the "add `move` keyword" suggestion is valid.
+
+//@ run-rustfix
+//@ edition:2024
+
+#![feature(coroutines)]
+#![feature(gen_blocks)]
+#![feature(async_iterator)]
+
+use std::async_iter::AsyncIterator;
+
+#[allow(dead_code)]
+fn moved() -> impl AsyncIterator<Item = u32> {
+ let mut x = "foo".to_string();
+
+ async gen { //~ ERROR
+ x.clear();
+ for x in 3..6 { yield x }
+ }
+}
+
+#[allow(dead_code)]
+fn check_with_whitespace_chars() -> impl AsyncIterator<Item = u32> {
+ let mut x = "foo".to_string();
+
+ async // Just to check that whitespace characters are correctly handled
+ gen { //~^ ERROR
+ x.clear();
+ for x in 3..6 { yield x }
+ }
+}
+
+fn main() {
+}
diff --git a/tests/ui/async-await/async-gen-move-suggestion.stderr b/tests/ui/async-await/async-gen-move-suggestion.stderr
new file mode 100644
index 0000000..b8cdb8b
--- /dev/null
+++ b/tests/ui/async-await/async-gen-move-suggestion.stderr
@@ -0,0 +1,47 @@
+error[E0373]: async gen block may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/async-gen-move-suggestion.rs:17:5
+ |
+LL | async gen {
+ | ^^^^^^^^^ may outlive borrowed value `x`
+LL | x.clear();
+ | - `x` is borrowed here
+ |
+note: async gen block is returned here
+ --> $DIR/async-gen-move-suggestion.rs:17:5
+ |
+LL | / async gen {
+LL | | x.clear();
+LL | | for x in 3..6 { yield x }
+LL | | }
+ | |_____^
+help: to force the async gen block to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | async gen move {
+ | ++++
+
+error[E0373]: async gen block may outlive the current function, but it borrows `x`, which is owned by the current function
+ --> $DIR/async-gen-move-suggestion.rs:27:5
+ |
+LL | / async // Just to check that whitespace characters are correctly handled
+LL | | gen {
+ | |_______^ may outlive borrowed value `x`
+LL | x.clear();
+ | - `x` is borrowed here
+ |
+note: async gen block is returned here
+ --> $DIR/async-gen-move-suggestion.rs:27:5
+ |
+LL | / async // Just to check that whitespace characters are correctly handled
+LL | | gen {
+LL | | x.clear();
+LL | | for x in 3..6 { yield x }
+LL | | }
+ | |_____^
+help: to force the async gen block to take ownership of `x` (and any other referenced variables), use the `move` keyword
+ |
+LL | gen move {
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/tests/ui/async-await/feature-async-for-loop.rs b/tests/ui/async-await/feature-async-for-loop.rs
index 67817cb..22d3290 100644
--- a/tests/ui/async-await/feature-async-for-loop.rs
+++ b/tests/ui/async-await/feature-async-for-loop.rs
@@ -11,7 +11,7 @@ fn f() {
};
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn g() {
let _ = async {
for await _i in core::async_iter::from_iter(0..3) {
diff --git a/tests/ui/async-await/issue-60709.rs b/tests/ui/async-await/issue-60709.rs
index 8634d6f..a3f54d7 100644
--- a/tests/ui/async-await/issue-60709.rs
+++ b/tests/ui/async-await/issue-60709.rs
@@ -1,6 +1,7 @@
// This used to compile the future down to ud2, due to uninhabited types being
// handled incorrectly in coroutines.
-//@ compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
+//@ compile-flags: -Copt-level=z -Cdebuginfo=2
+//@ edition: 2018
//@ run-pass
diff --git a/tests/ui/async-await/issues/issue-59972.rs b/tests/ui/async-await/issues/issue-59972.rs
index c30477f..e64a856 100644
--- a/tests/ui/async-await/issues/issue-59972.rs
+++ b/tests/ui/async-await/issues/issue-59972.rs
@@ -4,7 +4,8 @@
//@ run-pass
-//@ compile-flags: --edition=2018 -Aunused
+//@ compile-flags: -Aunused
+//@ edition: 2018
pub enum Uninhabited { }
diff --git a/tests/ui/async-await/no-unsafe-async.rs b/tests/ui/async-await/no-unsafe-async.rs
index e58d878..cc7e89e 100644
--- a/tests/ui/async-await/no-unsafe-async.rs
+++ b/tests/ui/async-await/no-unsafe-async.rs
@@ -3,11 +3,11 @@
struct S;
impl S {
- #[cfg(FALSE)]
+ #[cfg(false)]
unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
}
-#[cfg(FALSE)]
+#[cfg(false)]
unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
fn main() {}
diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr
index a1ea2b4..dc8e424 100644
--- a/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr
+++ b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr
@@ -1,4 +1,4 @@
-error[E0499]: cannot borrow `*x.__pointer` as mutable more than once at a time
+error[E0499]: cannot borrow `*x.pointer` as mutable more than once at a time
--> $DIR/reborrow-once.rs:12:14
|
LL | twice(x, x);
diff --git a/tests/ui/async-await/post-cleanup-phase-validation.rs b/tests/ui/async-await/post-cleanup-phase-validation.rs
new file mode 100644
index 0000000..a347e35
--- /dev/null
+++ b/tests/ui/async-await/post-cleanup-phase-validation.rs
@@ -0,0 +1,19 @@
+//@ compile-flags: -Zvalidate-mir
+//@ edition: 2024
+//@ build-pass
+
+// Regression test that we don't ICE when encountering a transmute in a coroutine's
+// drop shim body, which is conceptually in the Runtime phase but wasn't having the
+// phase updated b/c the pass manager neither optimizes nor updates the phase for
+// drop shim bodies.
+
+struct HasDrop;
+impl Drop for HasDrop {
+ fn drop(&mut self) {}
+}
+
+fn main() {
+ async {
+ vec![async { HasDrop }.await];
+ };
+}
diff --git a/tests/ui/async-await/suggest-missing-await.rs b/tests/ui/async-await/suggest-missing-await.rs
index 9897928..de0b2ce 100644
--- a/tests/ui/async-await/suggest-missing-await.rs
+++ b/tests/ui/async-await/suggest-missing-await.rs
@@ -1,4 +1,5 @@
//@ edition:2018
+//@ dont-require-annotations: SUGGESTION
fn take_u32(_x: u32) {}
diff --git a/tests/ui/async-await/suggest-missing-await.stderr b/tests/ui/async-await/suggest-missing-await.stderr
index f9db86e..9db7eb9 100644
--- a/tests/ui/async-await/suggest-missing-await.stderr
+++ b/tests/ui/async-await/suggest-missing-await.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/suggest-missing-await.rs:12:14
+ --> $DIR/suggest-missing-await.rs:13:14
|
LL | take_u32(x)
| -------- ^ expected `u32`, found future
@@ -7,12 +7,12 @@
| arguments to this function are incorrect
|
note: calling an async function returns a future
- --> $DIR/suggest-missing-await.rs:12:14
+ --> $DIR/suggest-missing-await.rs:13:14
|
LL | take_u32(x)
| ^
note: function defined here
- --> $DIR/suggest-missing-await.rs:3:4
+ --> $DIR/suggest-missing-await.rs:4:4
|
LL | fn take_u32(_x: u32) {}
| ^^^^^^^^ -------
@@ -22,13 +22,13 @@
| ++++++
error[E0308]: mismatched types
- --> $DIR/suggest-missing-await.rs:22:5
+ --> $DIR/suggest-missing-await.rs:23:5
|
LL | dummy()
| ^^^^^^^ expected `()`, found future
|
note: calling an async function returns a future
- --> $DIR/suggest-missing-await.rs:22:5
+ --> $DIR/suggest-missing-await.rs:23:5
|
LL | dummy()
| ^^^^^^^
@@ -42,7 +42,7 @@
| +
error[E0308]: `if` and `else` have incompatible types
- --> $DIR/suggest-missing-await.rs:35:9
+ --> $DIR/suggest-missing-await.rs:36:9
|
LL | let _x = if true {
| ______________-
@@ -64,7 +64,7 @@
| ++++++
error[E0308]: `match` arms have incompatible types
- --> $DIR/suggest-missing-await.rs:45:14
+ --> $DIR/suggest-missing-await.rs:46:14
|
LL | let _x = match 0usize {
| ______________-
@@ -87,7 +87,7 @@
|
error[E0308]: mismatched types
- --> $DIR/suggest-missing-await.rs:53:9
+ --> $DIR/suggest-missing-await.rs:54:9
|
LL | let _x = match dummy() {
| ------- this expression has type `impl Future<Output = ()>`
@@ -102,7 +102,7 @@
| ++++++
error[E0308]: mismatched types
- --> $DIR/suggest-missing-await.rs:67:9
+ --> $DIR/suggest-missing-await.rs:68:9
|
LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
@@ -118,7 +118,7 @@
| ++++++
error[E0308]: mismatched types
- --> $DIR/suggest-missing-await.rs:69:9
+ --> $DIR/suggest-missing-await.rs:70:9
|
LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
@@ -134,7 +134,7 @@
| ++++++
error[E0308]: mismatched types
- --> $DIR/suggest-missing-await.rs:77:27
+ --> $DIR/suggest-missing-await.rs:78:27
|
LL | Some(do_async()).map(|()| {});
| ^^
diff --git a/tests/ui/attributes/check-builtin-attr-ice.rs b/tests/ui/attributes/check-builtin-attr-ice.rs
index 9ef5890..7745849 100644
--- a/tests/ui/attributes/check-builtin-attr-ice.rs
+++ b/tests/ui/attributes/check-builtin-attr-ice.rs
@@ -39,13 +39,17 @@
// Notably, `should_panic` is a `AttributeType::Normal` attribute that is checked separately.
+#![deny(unused_attributes)]
+
struct Foo {
#[should_panic::skip]
//~^ ERROR failed to resolve
+ //~| ERROR `#[should_panic::skip]` only has an effect on functions
pub field: u8,
#[should_panic::a::b::c]
//~^ ERROR failed to resolve
+ //~| ERROR `#[should_panic::a::b::c]` only has an effect on functions
pub field2: u8,
}
diff --git a/tests/ui/attributes/check-builtin-attr-ice.stderr b/tests/ui/attributes/check-builtin-attr-ice.stderr
index 06a4769..4f26f71 100644
--- a/tests/ui/attributes/check-builtin-attr-ice.stderr
+++ b/tests/ui/attributes/check-builtin-attr-ice.stderr
@@ -1,21 +1,39 @@
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic`
- --> $DIR/check-builtin-attr-ice.rs:43:7
+ --> $DIR/check-builtin-attr-ice.rs:45:7
|
LL | #[should_panic::skip]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic`
- --> $DIR/check-builtin-attr-ice.rs:47:7
+ --> $DIR/check-builtin-attr-ice.rs:50:7
|
LL | #[should_panic::a::b::c]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `deny`
- --> $DIR/check-builtin-attr-ice.rs:55:7
+ --> $DIR/check-builtin-attr-ice.rs:59:7
|
LL | #[deny::skip]
| ^^^^ use of unresolved module or unlinked crate `deny`
-error: aborting due to 3 previous errors
+error: `#[should_panic::skip]` only has an effect on functions
+ --> $DIR/check-builtin-attr-ice.rs:45:5
+ |
+LL | #[should_panic::skip]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/check-builtin-attr-ice.rs:42:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: `#[should_panic::a::b::c]` only has an effect on functions
+ --> $DIR/check-builtin-attr-ice.rs:50:5
+ |
+LL | #[should_panic::a::b::c]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr
index 644acc2..9d44bd1 100644
--- a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr
+++ b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr
@@ -10,11 +10,17 @@
LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: `not_local_inner_macros` isn't a valid `#[macro_export]` argument
+error: invalid `#[macro_export]` argument
--> $DIR/invalid_macro_export_argument.rs:13:16
|
LL | #[macro_export(not_local_inner_macros)]
| ^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: invalid `#[macro_export]` argument
+ --> $DIR/invalid_macro_export_argument.rs:33:16
+ |
+LL | #[macro_export("blah")]
+ | ^^^^^^
+
+error: aborting due to 3 previous errors
diff --git a/tests/ui/attributes/invalid_macro_export_argument.rs b/tests/ui/attributes/invalid_macro_export_argument.rs
index 96f6699..c5fe39d 100644
--- a/tests/ui/attributes/invalid_macro_export_argument.rs
+++ b/tests/ui/attributes/invalid_macro_export_argument.rs
@@ -11,7 +11,7 @@ macro_rules! a {
}
#[macro_export(not_local_inner_macros)]
-//[deny]~^ ERROR `not_local_inner_macros` isn't a valid `#[macro_export]` argument
+//[deny]~^ ERROR invalid `#[macro_export]` argument
macro_rules! b {
() => ()
}
@@ -30,4 +30,10 @@ macro_rules! e {
() => ()
}
+#[macro_export("blah")]
+//[deny]~^ ERROR invalid `#[macro_export]` argument
+macro_rules! f {
+ () => ()
+}
+
fn main() {}
diff --git a/tests/ui/attributes/no-sanitize.rs b/tests/ui/attributes/no-sanitize.rs
index 8c79866..ddf909b 100644
--- a/tests/ui/attributes/no-sanitize.rs
+++ b/tests/ui/attributes/no-sanitize.rs
@@ -38,3 +38,8 @@ fn valid() {}
#[no_sanitize(address)]
static VALID : i32 = 0;
+
+#[no_sanitize("address")]
+//~^ ERROR `#[no_sanitize(...)]` should be applied to a function
+//~| ERROR invalid argument for `no_sanitize`
+static VALID2 : i32 = 0;
diff --git a/tests/ui/attributes/no-sanitize.stderr b/tests/ui/attributes/no-sanitize.stderr
index 9b0b76e..8d5fbb1 100644
--- a/tests/ui/attributes/no-sanitize.stderr
+++ b/tests/ui/attributes/no-sanitize.stderr
@@ -59,5 +59,22 @@
LL | static INVALID : i32 = 0;
| ------------------------- not a function
-error: aborting due to 7 previous errors
+error: `#[no_sanitize(...)]` should be applied to a function
+ --> $DIR/no-sanitize.rs:42:15
+ |
+LL | #[no_sanitize("address")]
+ | ^^^^^^^^^
+...
+LL | static VALID2 : i32 = 0;
+ | ------------------------ not a function
+
+error: invalid argument for `no_sanitize`
+ --> $DIR/no-sanitize.rs:42:15
+ |
+LL | #[no_sanitize("address")]
+ | ^^^^^^^^^
+ |
+ = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
+
+error: aborting due to 9 previous errors
diff --git a/tests/ui/attributes/z-crate-attr/cfg-false.rs b/tests/ui/attributes/z-crate-attr/cfg-false.rs
index db37cfd..5e5662c 100644
--- a/tests/ui/attributes/z-crate-attr/cfg-false.rs
+++ b/tests/ui/attributes/z-crate-attr/cfg-false.rs
@@ -1,5 +1,5 @@
-// Ensure that `-Z crate-attr=cfg(FALSE)` can comment out the whole crate
-//@ compile-flags: --crate-type=lib -Zcrate-attr=cfg(FALSE)
+// Ensure that `-Z crate-attr=cfg(false)` can comment out the whole crate
+//@ compile-flags: --crate-type=lib -Zcrate-attr=cfg(false)
//@ check-pass
// NOTE: duplicate items are load-bearing
diff --git a/tests/ui/attributes/z-crate-attr/garbage.stderr b/tests/ui/attributes/z-crate-attr/garbage.stderr
index 082046e..12d18b0 100644
--- a/tests/ui/attributes/z-crate-attr/garbage.stderr
+++ b/tests/ui/attributes/z-crate-attr/garbage.stderr
@@ -1,20 +1,20 @@
error: unknown start of token: `
- --> <crate attribute>:1:1
+ --> <crate attribute>:1:4
|
-LL | `%~@$#
- | ^
+LL | #![`%~@$#]
+ | ^
|
help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
|
-LL - `%~@$#
-LL + '%~@$#
+LL - #![`%~@$#]
+LL + #!['%~@$#]
|
error: expected identifier, found `%`
- --> <crate attribute>:1:2
+ --> <crate attribute>:1:5
|
-LL | `%~@$#
- | ^ expected identifier
+LL | #![`%~@$#]
+ | ^ expected identifier
error: aborting due to 2 previous errors
diff --git a/tests/ui/attributes/z-crate-attr/injection.rs b/tests/ui/attributes/z-crate-attr/injection.rs
index a91f9d2..ee7a27c 100644
--- a/tests/ui/attributes/z-crate-attr/injection.rs
+++ b/tests/ui/attributes/z-crate-attr/injection.rs
@@ -1,5 +1,3 @@
//@ compile-flags: '-Zcrate-attr=feature(yeet_expr)]fn main(){}#[inline'
-
-fn foo() {}
-
-//~? ERROR unexpected closing delimiter: `]`
+//~? ERROR unexpected token
+fn foo() {} //~ ERROR `main` function not found
diff --git a/tests/ui/attributes/z-crate-attr/injection.stderr b/tests/ui/attributes/z-crate-attr/injection.stderr
index 6fec98b..899dad0 100644
--- a/tests/ui/attributes/z-crate-attr/injection.stderr
+++ b/tests/ui/attributes/z-crate-attr/injection.stderr
@@ -1,8 +1,15 @@
-error: unexpected closing delimiter: `]`
- --> <crate attribute>:1:19
+error: unexpected token: keyword `fn`
+ --> <crate attribute>:1:23
|
-LL | feature(yeet_expr)]fn main(){}#[inline
- | ^ unexpected closing delimiter
+LL | #![feature(yeet_expr)]fn main(){}#[inline]
+ | ^^ unexpected token after this
-error: aborting due to 1 previous error
+error[E0601]: `main` function not found in crate `injection`
+ --> $DIR/injection.rs:3:12
+ |
+LL | fn foo() {}
+ | ^ consider adding a `main` function to `$DIR/injection.rs`
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/tests/ui/attributes/z-crate-attr/injection2.rs b/tests/ui/attributes/z-crate-attr/injection2.rs
new file mode 100644
index 0000000..67ae3d1
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/injection2.rs
@@ -0,0 +1,3 @@
+//@ compile-flags: -Zcrate-attr=feature(yeet_expr)]#![allow(warnings)
+//~? ERROR unexpected token
+fn foo() {} //~ ERROR `main` function not found
diff --git a/tests/ui/attributes/z-crate-attr/injection2.stderr b/tests/ui/attributes/z-crate-attr/injection2.stderr
new file mode 100644
index 0000000..51f54f9
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/injection2.stderr
@@ -0,0 +1,15 @@
+error: unexpected token: `#`
+ --> <crate attribute>:1:23
+ |
+LL | #![feature(yeet_expr)]#![allow(warnings)]
+ | ^ unexpected token after this
+
+error[E0601]: `main` function not found in crate `injection2`
+ --> $DIR/injection2.rs:3:12
+ |
+LL | fn foo() {}
+ | ^ consider adding a `main` function to `$DIR/injection2.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/tests/ui/attributes/z-crate-attr/inner-attr.stderr b/tests/ui/attributes/z-crate-attr/inner-attr.stderr
index 06a063d..1acb8c2 100644
--- a/tests/ui/attributes/z-crate-attr/inner-attr.stderr
+++ b/tests/ui/attributes/z-crate-attr/inner-attr.stderr
@@ -1,8 +1,8 @@
error: expected identifier, found `#`
- --> <crate attribute>:1:1
+ --> <crate attribute>:1:4
|
-LL | #![feature(foo)]
- | ^ expected identifier
+LL | #![#![feature(foo)]]
+ | ^ expected identifier
error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/z-crate-attr/multiple.rs b/tests/ui/attributes/z-crate-attr/multiple.rs
index 47d35d2..8c60ea6 100644
--- a/tests/ui/attributes/z-crate-attr/multiple.rs
+++ b/tests/ui/attributes/z-crate-attr/multiple.rs
@@ -1,5 +1,3 @@
//@ compile-flags: -Zcrate-attr=feature(foo),feature(bar)
-
+//~? ERROR expected `]`
fn main() {}
-
-//~? ERROR invalid crate attribute
diff --git a/tests/ui/attributes/z-crate-attr/multiple.stderr b/tests/ui/attributes/z-crate-attr/multiple.stderr
index 9f968a7..b95c95d 100644
--- a/tests/ui/attributes/z-crate-attr/multiple.stderr
+++ b/tests/ui/attributes/z-crate-attr/multiple.stderr
@@ -1,8 +1,8 @@
-error: invalid crate attribute
- --> <crate attribute>:1:1
+error: expected `]`, found `,`
+ --> <crate attribute>:1:16
|
-LL | feature(foo),feature(bar)
- | ^^^^^^^^^^^^^
+LL | #![feature(foo),feature(bar)]
+ | ^ expected `]`
error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs
index 77d5d69..5ef0a75 100644
--- a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs
+++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs
@@ -1,6 +1,4 @@
// Show diagnostics for unbalanced parens.
//@ compile-flags: -Zcrate-attr=(
-
+//~? ERROR mismatched closing delimiter
fn main() {}
-
-//~? ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr b/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr
index 47b1b76..f6545d1 100644
--- a/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr
+++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr
@@ -1,10 +1,11 @@
-error: this file contains an unclosed delimiter
- --> <crate attribute>:1:2
+error: mismatched closing delimiter: `]`
+ --> <crate attribute>:1:4
|
-LL | (
- | -^
- | |
- | unclosed delimiter
+LL | #![(]
+ | -^^ mismatched closing delimiter
+ | ||
+ | |unclosed delimiter
+ | closing delimiter possibly meant for this
error: aborting due to 1 previous error
diff --git a/tests/ui/auto-traits/pre-cfg.rs b/tests/ui/auto-traits/pre-cfg.rs
index e806686..4820a53 100644
--- a/tests/ui/auto-traits/pre-cfg.rs
+++ b/tests/ui/auto-traits/pre-cfg.rs
@@ -1,6 +1,6 @@
//@ check-pass
-#[cfg(FALSE)]
+#[cfg(false)]
auto trait Foo {}
//~^ WARN `auto` traits are unstable
//~| WARN unstable syntax can change at any point in the future, causing a hard error!
diff --git a/tests/ui/bootstrap/self-test/a.rs b/tests/ui/bootstrap/self-test/a.rs
index 64d2d6f..0818665 100644
--- a/tests/ui/bootstrap/self-test/a.rs
+++ b/tests/ui/bootstrap/self-test/a.rs
@@ -1,2 +1 @@
//! Not used by compiler, this is used by bootstrap cli self-test.
-//@ ignore-test
diff --git a/tests/ui/bootstrap/self-test/b.rs b/tests/ui/bootstrap/self-test/b.rs
index 91f92f6..aeb4688 100644
--- a/tests/ui/bootstrap/self-test/b.rs
+++ b/tests/ui/bootstrap/self-test/b.rs
@@ -1,2 +1 @@
//! Not used by compiler, used by bootstrap cli self-test.
-//@ ignore-test
diff --git a/tests/ui/bootstrap/self-test/compiletest-ignore-dir b/tests/ui/bootstrap/self-test/compiletest-ignore-dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/ui/bootstrap/self-test/compiletest-ignore-dir
diff --git a/tests/ui/borrowck/move-error-snippets-ext.rs b/tests/ui/borrowck/move-error-snippets-ext.rs
index f810322..6dd6843 100644
--- a/tests/ui/borrowck/move-error-snippets-ext.rs
+++ b/tests/ui/borrowck/move-error-snippets-ext.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `./move-error-snippets.rs`)
macro_rules! aaa {
($c:ident) => {{
diff --git a/tests/ui/cast/cast-array-issue-138836.rs b/tests/ui/cast/cast-array-issue-138836.rs
new file mode 100644
index 0000000..3f8098e
--- /dev/null
+++ b/tests/ui/cast/cast-array-issue-138836.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a: [u8; 3] = [1,2,3];
+ let b = &a;
+ let c = b as *const [u32; 3]; //~ ERROR casting `&[u8; 3]` as `*const [u32; 3]` is invalid
+}
diff --git a/tests/ui/cast/cast-array-issue-138836.stderr b/tests/ui/cast/cast-array-issue-138836.stderr
new file mode 100644
index 0000000..309474c
--- /dev/null
+++ b/tests/ui/cast/cast-array-issue-138836.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `&[u8; 3]` as `*const [u32; 3]` is invalid
+ --> $DIR/cast-array-issue-138836.rs:4:13
+ |
+LL | let c = b as *const [u32; 3];
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/cast/cast-as-bool.rs b/tests/ui/cast/cast-as-bool.rs
index 511a027..fa9664e 100644
--- a/tests/ui/cast/cast-as-bool.rs
+++ b/tests/ui/cast/cast-as-bool.rs
@@ -1,3 +1,5 @@
+//@ dont-require-annotations: SUGGESTION
+
fn main() {
let u = 5 as bool; //~ ERROR cannot cast `i32` as `bool`
//~| HELP compare with zero instead
diff --git a/tests/ui/cast/cast-as-bool.stderr b/tests/ui/cast/cast-as-bool.stderr
index b2c9ae5..25377ebeb 100644
--- a/tests/ui/cast/cast-as-bool.stderr
+++ b/tests/ui/cast/cast-as-bool.stderr
@@ -1,5 +1,5 @@
error[E0054]: cannot cast `i32` as `bool`
- --> $DIR/cast-as-bool.rs:2:13
+ --> $DIR/cast-as-bool.rs:4:13
|
LL | let u = 5 as bool;
| ^^^^^^^^^
@@ -11,7 +11,7 @@
|
error[E0054]: cannot cast `i32` as `bool`
- --> $DIR/cast-as-bool.rs:6:13
+ --> $DIR/cast-as-bool.rs:8:13
|
LL | let t = (1 + 2) as bool;
| ^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@
|
error[E0054]: cannot cast `u32` as `bool`
- --> $DIR/cast-as-bool.rs:10:13
+ --> $DIR/cast-as-bool.rs:12:13
|
LL | let _ = 5_u32 as bool;
| ^^^^^^^^^^^^^
@@ -35,7 +35,7 @@
|
error[E0054]: cannot cast `f64` as `bool`
- --> $DIR/cast-as-bool.rs:13:13
+ --> $DIR/cast-as-bool.rs:15:13
|
LL | let _ = 64.0_f64 as bool;
| ^^^^^^^^^^^^^^^^
@@ -47,43 +47,43 @@
|
error[E0054]: cannot cast `IntEnum` as `bool`
- --> $DIR/cast-as-bool.rs:24:13
+ --> $DIR/cast-as-bool.rs:26:13
|
LL | let _ = IntEnum::One as bool;
| ^^^^^^^^^^^^^^^^^^^^ unsupported cast
error[E0054]: cannot cast `fn(u8) -> String {uwu}` as `bool`
- --> $DIR/cast-as-bool.rs:33:13
+ --> $DIR/cast-as-bool.rs:35:13
|
LL | let _ = uwu as bool;
| ^^^^^^^^^^^ unsupported cast
error[E0054]: cannot cast `unsafe fn() {owo}` as `bool`
- --> $DIR/cast-as-bool.rs:35:13
+ --> $DIR/cast-as-bool.rs:37:13
|
LL | let _ = owo as bool;
| ^^^^^^^^^^^ unsupported cast
error[E0054]: cannot cast `fn(u8) -> String` as `bool`
- --> $DIR/cast-as-bool.rs:38:13
+ --> $DIR/cast-as-bool.rs:40:13
|
LL | let _ = uwu as fn(u8) -> String as bool;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported cast
error[E0054]: cannot cast `char` as `bool`
- --> $DIR/cast-as-bool.rs:40:13
+ --> $DIR/cast-as-bool.rs:42:13
|
LL | let _ = 'x' as bool;
| ^^^^^^^^^^^ unsupported cast
error[E0054]: cannot cast `*const ()` as `bool`
- --> $DIR/cast-as-bool.rs:44:13
+ --> $DIR/cast-as-bool.rs:46:13
|
LL | let _ = ptr as bool;
| ^^^^^^^^^^^ unsupported cast
error[E0606]: casting `&'static str` as `bool` is invalid
- --> $DIR/cast-as-bool.rs:46:13
+ --> $DIR/cast-as-bool.rs:48:13
|
LL | let v = "hello" as bool;
| ^^^^^^^^^^^^^^^
diff --git a/tests/ui/cfg/auxiliary/cfg_false_lib.rs b/tests/ui/cfg/auxiliary/cfg_false_lib.rs
index 6c2dbb4..d1768e6 100644
--- a/tests/ui/cfg/auxiliary/cfg_false_lib.rs
+++ b/tests/ui/cfg/auxiliary/cfg_false_lib.rs
@@ -1,4 +1,4 @@
-// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`.
+// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`.
// This crate has no such attribute, therefore this crate does link to libstd.
-#![cfg(FALSE)]
+#![cfg(false)]
diff --git a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs
index 3cfa6c5..cd3170f 100644
--- a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs
+++ b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs
@@ -1,5 +1,5 @@
-// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`.
+// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`.
// Therefore this crate does link to libstd.
-#![cfg(FALSE)]
+#![cfg(false)]
#![no_std]
diff --git a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs
index a5c14be..ce4e169 100644
--- a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs
+++ b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs
@@ -1,8 +1,8 @@
-// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`.
+// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`.
// Therefore this crate doesn't link to libstd.
//@ no-prefer-dynamic
#![no_std]
#![crate_type = "lib"]
-#![cfg(FALSE)]
+#![cfg(false)]
diff --git a/tests/ui/cfg/auxiliary/cfged_out.rs b/tests/ui/cfg/auxiliary/cfged_out.rs
index f6a9089..564280b 100644
--- a/tests/ui/cfg/auxiliary/cfged_out.rs
+++ b/tests/ui/cfg/auxiliary/cfged_out.rs
@@ -1,8 +1,8 @@
pub mod inner {
- #[cfg(FALSE)]
+ #[cfg(false)]
pub fn uwu() {}
- #[cfg(FALSE)]
+ #[cfg(false)]
pub mod doesnt_exist {
pub fn hello() {}
}
diff --git a/tests/ui/cfg/both-true-false.rs b/tests/ui/cfg/both-true-false.rs
new file mode 100644
index 0000000..5fca8f6
--- /dev/null
+++ b/tests/ui/cfg/both-true-false.rs
@@ -0,0 +1,14 @@
+/// Test that placing a `cfg(true)` and `cfg(false)` on the same item result in
+//. it being disabled.`
+
+#[cfg(false)]
+#[cfg(true)]
+fn foo() {}
+
+#[cfg(true)]
+#[cfg(false)]
+fn foo() {}
+
+fn main() {
+ foo(); //~ ERROR cannot find function `foo` in this scope
+}
diff --git a/tests/ui/cfg/both-true-false.stderr b/tests/ui/cfg/both-true-false.stderr
new file mode 100644
index 0000000..1526cc2
--- /dev/null
+++ b/tests/ui/cfg/both-true-false.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/both-true-false.rs:13:5
+ |
+LL | foo();
+ | ^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/cfg/cfg-false-feature.rs b/tests/ui/cfg/cfg-false-feature.rs
index 716b184..f66e472 100644
--- a/tests/ui/cfg/cfg-false-feature.rs
+++ b/tests/ui/cfg/cfg-false-feature.rs
@@ -1,10 +1,10 @@
-// Features above `cfg(FALSE)` are in effect in a fully unconfigured crate (issue #104633).
+// Features above `cfg(false)` are in effect in a fully unconfigured crate (issue #104633).
//@ check-pass
//@ compile-flags: --crate-type lib
#![feature(decl_macro)]
-#![cfg(FALSE)]
+#![cfg(false)]
#![feature(box_patterns)]
macro mac() {} // OK
diff --git a/tests/ui/cfg/cfg-macros-notfoo.rs b/tests/ui/cfg/cfg-macros-notfoo.rs
index 9feb06b..c25cf1c 100644
--- a/tests/ui/cfg/cfg-macros-notfoo.rs
+++ b/tests/ui/cfg/cfg-macros-notfoo.rs
@@ -3,7 +3,7 @@
// check that cfg correctly chooses between the macro impls (see also
// cfg-macros-foo.rs)
-#[cfg(FALSE)]
+#[cfg(false)]
#[macro_use]
mod foo {
macro_rules! bar {
diff --git a/tests/ui/cfg/cfg-match-arm.rs b/tests/ui/cfg/cfg-match-arm.rs
index f6cd52c..cb5bf0a 100644
--- a/tests/ui/cfg/cfg-match-arm.rs
+++ b/tests/ui/cfg/cfg-match-arm.rs
@@ -11,7 +11,7 @@ fn foo(f: Foo) {
Foo::Bar => {},
#[cfg(not(FALSE))]
Foo::Baz => {},
- #[cfg(FALSE)]
+ #[cfg(false)]
Basdfwe => {}
}
}
diff --git a/tests/ui/cfg/cfg-stmt-recovery.rs b/tests/ui/cfg/cfg-stmt-recovery.rs
index 2e0839d..f0f9a64 100644
--- a/tests/ui/cfg/cfg-stmt-recovery.rs
+++ b/tests/ui/cfg/cfg-stmt-recovery.rs
@@ -6,7 +6,7 @@
#[cfg_eval]
fn main() {
#[cfg_eval]
- let _ = #[cfg(FALSE)] 0;
+ let _ = #[cfg(false)] 0;
//~^ ERROR removing an expression is not supported in this position
//~| ERROR expected expression, found `;`
//~| ERROR removing an expression is not supported in this position
diff --git a/tests/ui/cfg/cfg-stmt-recovery.stderr b/tests/ui/cfg/cfg-stmt-recovery.stderr
index cb15e21..e34da72 100644
--- a/tests/ui/cfg/cfg-stmt-recovery.stderr
+++ b/tests/ui/cfg/cfg-stmt-recovery.stderr
@@ -1,19 +1,19 @@
error: removing an expression is not supported in this position
--> $DIR/cfg-stmt-recovery.rs:9:13
|
-LL | let _ = #[cfg(FALSE)] 0;
+LL | let _ = #[cfg(false)] 0;
| ^^^^^^^^^^^^^
error: expected expression, found `;`
--> $DIR/cfg-stmt-recovery.rs:9:28
|
-LL | let _ = #[cfg(FALSE)] 0;
+LL | let _ = #[cfg(false)] 0;
| ^ expected expression
error: removing an expression is not supported in this position
--> $DIR/cfg-stmt-recovery.rs:9:13
|
-LL | let _ = #[cfg(FALSE)] 0;
+LL | let _ = #[cfg(false)] 0;
| ^^^^^^^^^^^^^
error: aborting due to 3 previous errors
diff --git a/tests/ui/cfg/cfg_false_no_std-2.rs b/tests/ui/cfg/cfg_false_no_std-2.rs
index 349c494..18b2c69 100644
--- a/tests/ui/cfg/cfg_false_no_std-2.rs
+++ b/tests/ui/cfg/cfg_false_no_std-2.rs
@@ -1,6 +1,6 @@
// Error, the linked empty library is `no_std` and doesn't provide a panic handler.
-//@ dont-require-annotations:ERROR
+//@ dont-require-annotations: ERROR
//@ dont-check-compiler-stderr
//@ aux-build: cfg_false_lib_no_std_before.rs
diff --git a/tests/ui/cfg/cfg_stmt_expr.rs b/tests/ui/cfg/cfg_stmt_expr.rs
index 9245f6d..361b159 100644
--- a/tests/ui/cfg/cfg_stmt_expr.rs
+++ b/tests/ui/cfg/cfg_stmt_expr.rs
@@ -7,47 +7,47 @@
fn main() {
let a = 413;
- #[cfg(FALSE)]
+ #[cfg(false)]
let a = ();
assert_eq!(a, 413);
let mut b = 612;
- #[cfg(FALSE)]
+ #[cfg(false)]
{
b = 1111;
}
assert_eq!(b, 612);
- #[cfg(FALSE)]
+ #[cfg(false)]
undefined_fn();
- #[cfg(FALSE)]
+ #[cfg(false)]
undefined_macro!();
- #[cfg(FALSE)]
+ #[cfg(false)]
undefined_macro![];
- #[cfg(FALSE)]
+ #[cfg(false)]
undefined_macro!{};
// pretty printer bug...
- // #[cfg(FALSE)]
+ // #[cfg(false)]
// undefined_macro!{}
- let () = (#[cfg(FALSE)] 341,); // Should this also work on parens?
- let t = (1, #[cfg(FALSE)] 3, 4);
+ let () = (#[cfg(false)] 341,); // Should this also work on parens?
+ let t = (1, #[cfg(false)] 3, 4);
assert_eq!(t, (1, 4));
let f = |_: u32, _: u32| ();
- f(2, 1, #[cfg(FALSE)] 6);
+ f(2, 1, #[cfg(false)] 6);
- let _: u32 = a.clone(#[cfg(FALSE)] undefined);
+ let _: u32 = a.clone(#[cfg(false)] undefined);
- let _: [(); 0] = [#[cfg(FALSE)] 126];
- let t = [#[cfg(FALSE)] 1, 2, 6];
+ let _: [(); 0] = [#[cfg(false)] 126];
+ let t = [#[cfg(false)] 1, 2, 6];
assert_eq!(t, [2, 6]);
{
let r;
- #[cfg(FALSE)]
+ #[cfg(false)]
(r = 5);
#[cfg(not(FALSE))]
(r = 10);
@@ -75,7 +75,7 @@ macro_rules! if_cfg {
612
});
- assert_eq!((#[cfg(FALSE)] 1, #[cfg(not(FALSE))] 2), (2,));
+ assert_eq!((#[cfg(false)] 1, #[cfg(not(FALSE))] 2), (2,));
assert_eq!(n, 612);
// check that lints work
diff --git a/tests/ui/cfg/cmdline-false.rs b/tests/ui/cfg/cmdline-false.rs
new file mode 100644
index 0000000..d4b7d3b
--- /dev/null
+++ b/tests/ui/cfg/cmdline-false.rs
@@ -0,0 +1,9 @@
+/// Test that `--cfg false` doesn't cause `cfg(false)` to evaluate to `true`
+//@ compile-flags: --cfg false
+
+#[cfg(false)]
+fn foo() {}
+
+fn main() {
+ foo(); //~ ERROR cannot find function `foo` in this scope
+}
diff --git a/tests/ui/cfg/cmdline-false.stderr b/tests/ui/cfg/cmdline-false.stderr
new file mode 100644
index 0000000..5f57c75
--- /dev/null
+++ b/tests/ui/cfg/cmdline-false.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/cmdline-false.rs:8:5
+ |
+LL | foo();
+ | ^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/cfg/conditional-compile.rs b/tests/ui/cfg/conditional-compile.rs
index dff2800..0739e87 100644
--- a/tests/ui/cfg/conditional-compile.rs
+++ b/tests/ui/cfg/conditional-compile.rs
@@ -6,16 +6,16 @@
// Crate use statements
-#[cfg(FALSE)]
+#[cfg(false)]
use flippity;
-#[cfg(FALSE)]
+#[cfg(false)]
static b: bool = false;
static b: bool = true;
mod rustrt {
- #[cfg(FALSE)]
+ #[cfg(false)]
extern "C" {
// This symbol doesn't exist and would be a link error if this
// module was codegened
@@ -25,12 +25,12 @@ mod rustrt {
extern "C" {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
type t = isize;
type t = bool;
-#[cfg(FALSE)]
+#[cfg(false)]
enum tg {
foo,
}
@@ -39,12 +39,12 @@ enum tg {
bar,
}
-#[cfg(FALSE)]
+#[cfg(false)]
struct r {
i: isize,
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn r(i: isize) -> r {
r { i: i }
}
@@ -57,7 +57,7 @@ fn r(i: isize) -> r {
r { i: i }
}
-#[cfg(FALSE)]
+#[cfg(false)]
mod m {
// This needs to parse but would fail in typeck. Since it's not in
// the current config it should not be typechecked.
@@ -69,7 +69,7 @@ pub fn FALSE() {
mod m {
// Submodules have slightly different code paths than the top-level
// module, so let's make sure this jazz works here as well
- #[cfg(FALSE)]
+ #[cfg(false)]
pub fn f() {}
pub fn f() {}
@@ -77,7 +77,7 @@ pub fn f() {}
// Since the FALSE configuration isn't defined main will just be
// parsed, but nothing further will be done with it
-#[cfg(FALSE)]
+#[cfg(false)]
pub fn main() {
panic!()
}
@@ -93,14 +93,14 @@ pub fn main() {
}
fn test_in_fn_ctxt() {
- #[cfg(FALSE)]
+ #[cfg(false)]
fn f() {
panic!()
}
fn f() {}
f();
- #[cfg(FALSE)]
+ #[cfg(false)]
static i: isize = 0;
static i: isize = 1;
assert_eq!(i, 1);
@@ -109,7 +109,7 @@ fn f() {}
mod test_foreign_items {
pub mod rustrt {
extern "C" {
- #[cfg(FALSE)]
+ #[cfg(false)]
pub fn write() -> String;
pub fn write() -> String;
}
@@ -117,7 +117,7 @@ pub mod rustrt {
}
mod test_use_statements {
- #[cfg(FALSE)]
+ #[cfg(false)]
use flippity_foo;
}
@@ -127,24 +127,24 @@ struct Foo {
}
impl Fooable for Foo {
- #[cfg(FALSE)]
+ #[cfg(false)]
fn what(&self) {}
fn what(&self) {}
- #[cfg(FALSE)]
+ #[cfg(false)]
fn the(&self) {}
fn the(&self) {}
}
trait Fooable {
- #[cfg(FALSE)]
+ #[cfg(false)]
fn what(&self);
fn what(&self);
- #[cfg(FALSE)]
+ #[cfg(false)]
fn the(&self);
fn the(&self);
diff --git a/tests/ui/cfg/diagnostics-cross-crate.stderr b/tests/ui/cfg/diagnostics-cross-crate.stderr
index 07ad4e3..3e32a85 100644
--- a/tests/ui/cfg/diagnostics-cross-crate.stderr
+++ b/tests/ui/cfg/diagnostics-cross-crate.stderr
@@ -12,7 +12,7 @@
note: the item is gated here
--> $DIR/auxiliary/cfged_out.rs:5:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0425]: cannot find function `uwu` in crate `cfged_out`
@@ -35,7 +35,7 @@
note: the item is gated here
--> $DIR/auxiliary/cfged_out.rs:2:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0425]: cannot find function `meow` in module `cfged_out::inner::right`
diff --git a/tests/ui/cfg/diagnostics-reexport.rs b/tests/ui/cfg/diagnostics-reexport.rs
index 9ae7d93..56fac56 100644
--- a/tests/ui/cfg/diagnostics-reexport.rs
+++ b/tests/ui/cfg/diagnostics-reexport.rs
@@ -1,10 +1,10 @@
pub mod inner {
- #[cfg(FALSE)]
+ #[cfg(false)]
mod gone {
pub fn uwu() {}
}
- #[cfg(FALSE)] //~ NOTE the item is gated here
+ #[cfg(false)] //~ NOTE the item is gated here
pub use super::uwu;
//~^ NOTE found an item that was configured out
}
@@ -14,7 +14,7 @@ pub fn uwu() {}
//~| NOTE no `x` in `a`
mod a {
- #[cfg(FALSE)] //~ NOTE the item is gated here
+ #[cfg(false)] //~ NOTE the item is gated here
pub fn x() {}
//~^ NOTE found an item that was configured out
}
@@ -25,10 +25,10 @@ pub fn x() {}
//~| NOTE no `y` in `b`
mod b {
- #[cfg(FALSE)] //~ NOTE the item is gated here
+ #[cfg(false)] //~ NOTE the item is gated here
pub fn x() {}
//~^ NOTE found an item that was configured out
- #[cfg(FALSE)] //~ NOTE the item is gated here
+ #[cfg(false)] //~ NOTE the item is gated here
pub fn y() {}
//~^ NOTE found an item that was configured out
}
diff --git a/tests/ui/cfg/diagnostics-reexport.stderr b/tests/ui/cfg/diagnostics-reexport.stderr
index 737202f..95dc4fa 100644
--- a/tests/ui/cfg/diagnostics-reexport.stderr
+++ b/tests/ui/cfg/diagnostics-reexport.stderr
@@ -12,7 +12,7 @@
note: the item is gated here
--> $DIR/diagnostics-reexport.rs:17:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0432]: unresolved imports `b::x`, `b::y`
@@ -31,7 +31,7 @@
note: the item is gated here
--> $DIR/diagnostics-reexport.rs:28:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
note: found an item that was configured out
--> $DIR/diagnostics-reexport.rs:32:12
@@ -41,7 +41,7 @@
note: the item is gated here
--> $DIR/diagnostics-reexport.rs:31:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0425]: cannot find function `uwu` in module `inner`
@@ -58,7 +58,7 @@
note: the item is gated here
--> $DIR/diagnostics-reexport.rs:7:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error: aborting due to 3 previous errors
diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs
index d6f8dd2..9153f20 100644
--- a/tests/ui/cfg/diagnostics-same-crate.rs
+++ b/tests/ui/cfg/diagnostics-same-crate.rs
@@ -1,11 +1,11 @@
#![allow(unexpected_cfgs)] // since we want to recognize them as unexpected
pub mod inner {
- #[cfg(FALSE)] //~ NOTE the item is gated here
+ #[cfg(false)] //~ NOTE the item is gated here
pub fn uwu() {}
//~^ NOTE found an item that was configured out
- #[cfg(FALSE)] //~ NOTE the item is gated here
+ #[cfg(false)] //~ NOTE the item is gated here
//~^ NOTE the item is gated here
//~| NOTE the item is gated here
pub mod doesnt_exist {
diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr
index dd0d10c..75a1bc3 100644
--- a/tests/ui/cfg/diagnostics-same-crate.stderr
+++ b/tests/ui/cfg/diagnostics-same-crate.stderr
@@ -12,7 +12,7 @@
note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:8:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0432]: unresolved import `super::inner::doesnt_exist`
@@ -29,7 +29,7 @@
note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:8:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner`
@@ -46,7 +46,7 @@
note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:8:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0425]: cannot find function `uwu` in module `inner`
@@ -63,7 +63,7 @@
note: the item is gated here
--> $DIR/diagnostics-same-crate.rs:4:5
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ^^^^^^^^^^^^^
error[E0425]: cannot find function `meow` in module `inner::right`
diff --git a/tests/ui/cfg/true-false.rs b/tests/ui/cfg/true-false.rs
index 03d96fb..0bd1cf4 100644
--- a/tests/ui/cfg/true-false.rs
+++ b/tests/ui/cfg/true-false.rs
@@ -1,7 +1,6 @@
//@ run-pass
#![feature(link_cfg)]
-#![feature(cfg_boolean_literals)]
#[cfg(true)]
fn foo() -> bool {
diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs
index 8260b57..3f673cb 100644
--- a/tests/ui/check-cfg/allow-same-level.rs
+++ b/tests/ui/check-cfg/allow-same-level.rs
@@ -12,7 +12,7 @@
//@ compile-flags: --check-cfg=cfg() --cfg=unknown_but_active_cfg
#[allow(unexpected_cfgs)]
-#[cfg(FALSE)]
+#[cfg(unknown_and_inactive_cfg)]
//~^ WARNING unexpected `cfg` condition name
fn bar() {}
diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr
index a705cd4..cfff030 100644
--- a/tests/ui/check-cfg/allow-same-level.stderr
+++ b/tests/ui/check-cfg/allow-same-level.stderr
@@ -1,10 +1,10 @@
-warning: unexpected `cfg` condition name: `FALSE`
+warning: unexpected `cfg` condition name: `unknown_and_inactive_cfg`
--> $DIR/allow-same-level.rs:15:7
|
-LL | #[cfg(FALSE)]
- | ^^^^^
+LL | #[cfg(unknown_and_inactive_cfg)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: to expect this configuration use `--check-cfg=cfg(FALSE)`
+ = help: to expect this configuration use `--check-cfg=cfg(unknown_and_inactive_cfg)`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/allow-top-level.rs b/tests/ui/check-cfg/allow-top-level.rs
index cf94ed5..7ccecd2 100644
--- a/tests/ui/check-cfg/allow-top-level.rs
+++ b/tests/ui/check-cfg/allow-top-level.rs
@@ -6,7 +6,7 @@
#![allow(unexpected_cfgs)]
-#[cfg(FALSE)]
+#[cfg(false)]
fn bar() {}
fn foo() {
diff --git a/tests/ui/check-cfg/allow-upper-level.rs b/tests/ui/check-cfg/allow-upper-level.rs
index 2e6664c..657a476 100644
--- a/tests/ui/check-cfg/allow-upper-level.rs
+++ b/tests/ui/check-cfg/allow-upper-level.rs
@@ -6,7 +6,7 @@
#[allow(unexpected_cfgs)]
mod aa {
- #[cfg(FALSE)]
+ #[cfg(false)]
fn bar() {}
}
diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs
index a9380dd..a02b043 100644
--- a/tests/ui/check-cfg/cargo-feature.rs
+++ b/tests/ui/check-cfg/cargo-feature.rs
@@ -10,7 +10,7 @@
//@ [none]compile-flags: --check-cfg=cfg(feature,values())
//@ [some]compile-flags: --check-cfg=cfg(feature,values("bitcode"))
//@ [some]compile-flags: --check-cfg=cfg(CONFIG_NVME,values("y"))
-//@ [none]error-pattern:Cargo.toml
+//@ dont-require-annotations: HELP
#[cfg(feature = "serde")]
//~^ WARNING unexpected `cfg` condition value
@@ -27,6 +27,7 @@ fn tokio() {}
#[cfg(CONFIG_NVME = "m")]
//[none]~^ WARNING unexpected `cfg` condition name
//[some]~^^ WARNING unexpected `cfg` condition value
+//[none]~| HELP Cargo.toml
fn tokio() {}
fn main() {}
diff --git a/tests/ui/check-cfg/raw-keywords.edition2015.stderr b/tests/ui/check-cfg/raw-keywords.edition2015.stderr
index 8ca33e0..29c1a71 100644
--- a/tests/ui/check-cfg/raw-keywords.edition2015.stderr
+++ b/tests/ui/check-cfg/raw-keywords.edition2015.stderr
@@ -1,5 +1,5 @@
warning: unexpected `cfg` condition name: `tru`
- --> $DIR/raw-keywords.rs:14:7
+ --> $DIR/raw-keywords.rs:15:7
|
LL | #[cfg(tru)]
| ^^^ help: there is a config with a similar name: `r#true`
@@ -9,7 +9,7 @@
= note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition name: `r#false`
- --> $DIR/raw-keywords.rs:19:7
+ --> $DIR/raw-keywords.rs:20:7
|
LL | #[cfg(r#false)]
| ^^^^^^^
@@ -19,7 +19,7 @@
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition name: `await`
- --> $DIR/raw-keywords.rs:27:29
+ --> $DIR/raw-keywords.rs:28:29
|
LL | #[cfg_attr(edition2015, cfg(await))]
| ^^^^^
@@ -28,7 +28,7 @@
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition name: `raw`
- --> $DIR/raw-keywords.rs:33:7
+ --> $DIR/raw-keywords.rs:34:7
|
LL | #[cfg(r#raw)]
| ^^^^^
diff --git a/tests/ui/check-cfg/raw-keywords.edition2021.stderr b/tests/ui/check-cfg/raw-keywords.edition2021.stderr
index cce5572..cc37026 100644
--- a/tests/ui/check-cfg/raw-keywords.edition2021.stderr
+++ b/tests/ui/check-cfg/raw-keywords.edition2021.stderr
@@ -1,5 +1,5 @@
warning: unexpected `cfg` condition name: `tru`
- --> $DIR/raw-keywords.rs:14:7
+ --> $DIR/raw-keywords.rs:15:7
|
LL | #[cfg(tru)]
| ^^^ help: there is a config with a similar name: `r#true`
@@ -9,7 +9,7 @@
= note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition name: `r#false`
- --> $DIR/raw-keywords.rs:19:7
+ --> $DIR/raw-keywords.rs:20:7
|
LL | #[cfg(r#false)]
| ^^^^^^^
@@ -19,7 +19,7 @@
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition name: `r#await`
- --> $DIR/raw-keywords.rs:28:29
+ --> $DIR/raw-keywords.rs:29:29
|
LL | #[cfg_attr(edition2021, cfg(r#await))]
| ^^^^^^^
@@ -28,7 +28,7 @@
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition name: `raw`
- --> $DIR/raw-keywords.rs:33:7
+ --> $DIR/raw-keywords.rs:34:7
|
LL | #[cfg(r#raw)]
| ^^^^^
diff --git a/tests/ui/check-cfg/raw-keywords.rs b/tests/ui/check-cfg/raw-keywords.rs
index 5de1324..b82eb5a 100644
--- a/tests/ui/check-cfg/raw-keywords.rs
+++ b/tests/ui/check-cfg/raw-keywords.rs
@@ -6,7 +6,8 @@
//@ compile-flags: --cfg=true --cfg=async --check-cfg=cfg(r#true,r#async,edition2015,edition2021)
//
//@ revisions: edition2015 edition2021
-//@ [edition2021] compile-flags: --edition 2021
+//@ [edition2015] edition: 2015
+//@ [edition2021] edition: 2021
#[cfg(r#true)]
fn foo() {}
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index aa5fd09..4f7b834 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -49,6 +49,7 @@
`avxvnni`
`avxvnniint16`
`avxvnniint8`
+`b`
`backchain`
`bf16`
`bmi1`
@@ -318,17 +319,25 @@
`zbkc`
`zbkx`
`zbs`
+`zca`
+`zcb`
+`zcmop`
`zdinx`
+`zfa`
`zfh`
`zfhmin`
`zfinx`
`zhinx`
`zhinxmin`
+`zicboz`
`zicntr`
+`zicond`
`zicsr`
`zifencei`
+`zihintntl`
`zihintpause`
`zihpm`
+`zimop`
`zk`
`zkn`
`zknd`
@@ -339,6 +348,7 @@
`zksed`
`zksh`
`zkt`
+`ztso`
`zvbb`
`zvbc`
`zve32f`
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 4636b69..7cda6c2e 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -201,7 +201,7 @@
LL | target_os = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
+ = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -274,7 +274,7 @@
| |
| help: there is a expected value with a similar name: `"linux"`
|
- = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
+ = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: 28 warnings emitted
diff --git a/tests/ui/closures/2229_closure_analysis/issue-89606.rs b/tests/ui/closures/2229_closure_analysis/issue-89606.rs
index 8c88a4b..5494686 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-89606.rs
+++ b/tests/ui/closures/2229_closure_analysis/issue-89606.rs
@@ -2,8 +2,8 @@
//
//@ check-pass
//@ revisions: twenty_eighteen twenty_twentyone
-//@ [twenty_eighteen]compile-flags: --edition 2018
-//@ [twenty_twentyone]compile-flags: --edition 2021
+//@ [twenty_eighteen] edition: 2018
+//@ [twenty_twentyone] edition: 2021
struct S<'a>(Option<&'a mut i32>);
diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs
index 4fc2e6c..a771b81 100644
--- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs
+++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs
@@ -1,8 +1,8 @@
//@ run-pass
//@ check-run-results
//@ revisions: twenty_eighteen twenty_twentyone
-//@ [twenty_eighteen]compile-flags: --edition 2018
-//@ [twenty_twentyone]compile-flags: --edition 2021
+//@ [twenty_eighteen] edition: 2018
+//@ [twenty_twentyone] edition: 2021
#[derive(Debug)]
struct Dropable(&'static str);
diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs
index 81af030..a615cdf 100644
--- a/tests/ui/closures/issue-78720.rs
+++ b/tests/ui/closures/issue-78720.rs
@@ -1,5 +1,6 @@
fn server() -> impl {
//~^ ERROR at least one trait must be specified
+ //~^^ ERROR type annotations needed
().map2(|| "")
}
diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr
index 90672cd..3e95fab 100644
--- a/tests/ui/closures/issue-78720.stderr
+++ b/tests/ui/closures/issue-78720.stderr
@@ -5,7 +5,7 @@
| ^^^^
error[E0412]: cannot find type `F` in this scope
- --> $DIR/issue-78720.rs:13:12
+ --> $DIR/issue-78720.rs:14:12
|
LL | _func: F,
| ^
@@ -22,8 +22,14 @@
LL | struct Map2<Segment2, F> {
| +++
+error[E0282]: type annotations needed
+ --> $DIR/issue-78720.rs:1:16
+ |
+LL | fn server() -> impl {
+ | ^^^^ cannot infer type
+
error[E0308]: mismatched types
- --> $DIR/issue-78720.rs:7:39
+ --> $DIR/issue-78720.rs:8:39
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
| ^^ expected `Map2<F>`, found `()`
@@ -32,7 +38,7 @@
found unit type `()`
error[E0277]: the size for values of type `Self` cannot be known at compilation time
- --> $DIR/issue-78720.rs:7:16
+ --> $DIR/issue-78720.rs:8:16
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
| ^^^^ doesn't have a size known at compile-time
@@ -47,7 +53,7 @@
LL | fn map2<F>(&self, f: F) -> Map2<F> {}
| +
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
-Some errors have detailed explanations: E0277, E0308, E0412.
+Some errors have detailed explanations: E0277, E0282, E0308, E0412.
For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/codegen/empty-static-libs-issue-108825.rs b/tests/ui/codegen/empty-static-libs-issue-108825.rs
index 46bd6d6..4c644be 100644
--- a/tests/ui/codegen/empty-static-libs-issue-108825.rs
+++ b/tests/ui/codegen/empty-static-libs-issue-108825.rs
@@ -3,7 +3,6 @@
//@ compile-flags: -Cpanic=abort --print=native-static-libs
//@ build-pass
-//@ error-pattern: note: native-static-libs:
//@ dont-check-compiler-stderr (libcore links `/defaultlib:msvcrt` or `/defaultlib:libcmt` on MSVC)
//@ ignore-pass (the note is emitted later in the compilation pipeline, needs build)
@@ -14,3 +13,6 @@
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
+
+//~? NOTE native-static-libs:
+//~? NOTE Link against the following native artifacts when linking against this static library
diff --git a/tests/ui/codegen/overflow-during-mono.rs b/tests/ui/codegen/overflow-during-mono.rs
index 83a8b6b..a904584 100644
--- a/tests/ui/codegen/overflow-during-mono.rs
+++ b/tests/ui/codegen/overflow-during-mono.rs
@@ -1,4 +1,4 @@
-//~ ERROR overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
+//~ ERROR overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)`
//@ build-fail
#![recursion_limit = "32"]
diff --git a/tests/ui/codegen/overflow-during-mono.stderr b/tests/ui/codegen/overflow-during-mono.stderr
index f7a3e2d..74d98fd 100644
--- a/tests/ui/codegen/overflow-during-mono.stderr
+++ b/tests/ui/codegen/overflow-during-mono.stderr
@@ -1,4 +1,4 @@
-error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
+error[E0275]: overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`)
= note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
diff --git a/tests/ui/codemap_tests/two_files_data.rs b/tests/ui/codemap_tests/two_files_data.rs
index a4e4cf7..82852f6 100644
--- a/tests/ui/codemap_tests/two_files_data.rs
+++ b/tests/ui/codemap_tests/two_files_data.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `./two_files.rs`)
trait Foo { }
diff --git a/tests/ui/codemap_tests/unicode.expanded.stdout b/tests/ui/codemap_tests/unicode.expanded.stdout
index eb53d12..c88035d 100644
--- a/tests/ui/codemap_tests/unicode.expanded.stdout
+++ b/tests/ui/codemap_tests/unicode.expanded.stdout
@@ -7,6 +7,7 @@
//@ revisions: normal expanded
//@[expanded] check-pass
//@[expanded]compile-flags: -Zunpretty=expanded
+//@ edition: 2015
extern "路濫狼á́́" fn foo() {}
diff --git a/tests/ui/codemap_tests/unicode.normal.stderr b/tests/ui/codemap_tests/unicode.normal.stderr
index 0f254e0..10cb34f 100644
--- a/tests/ui/codemap_tests/unicode.normal.stderr
+++ b/tests/ui/codemap_tests/unicode.normal.stderr
@@ -1,5 +1,5 @@
error[E0703]: invalid ABI: found `路濫狼á́́`
- --> $DIR/unicode.rs:5:8
+ --> $DIR/unicode.rs:6:8
|
LL | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^^ invalid ABI
diff --git a/tests/ui/codemap_tests/unicode.rs b/tests/ui/codemap_tests/unicode.rs
index 73023e3..4b93ef0 100644
--- a/tests/ui/codemap_tests/unicode.rs
+++ b/tests/ui/codemap_tests/unicode.rs
@@ -1,6 +1,7 @@
//@ revisions: normal expanded
//@[expanded] check-pass
//@[expanded]compile-flags: -Zunpretty=expanded
+//@ edition: 2015
extern "路濫狼á́́" fn foo() {} //[normal]~ ERROR invalid ABI
diff --git a/tests/ui/coercion/codegen-smart-pointer-with-alias.rs b/tests/ui/coercion/codegen-smart-pointer-with-alias.rs
new file mode 100644
index 0000000..a68952b
--- /dev/null
+++ b/tests/ui/coercion/codegen-smart-pointer-with-alias.rs
@@ -0,0 +1,32 @@
+//@ build-pass
+
+// Regression test for <https://github.com/rust-lang/rust/issues/139812>.
+
+// Make sure that the unsize coercion we collect in mono for `Signal<i32> -> Signal<dyn Any>`
+// doesn't choke on the fact that the inner unsized field of `Signal<T>` is a (trivial) alias.
+// This exercises a normalize call that is necessary since we're getting a type from the type
+// system, which isn't guaranteed to be normalized after substitution.
+
+#![feature(coerce_unsized)]
+
+use std::ops::CoerceUnsized;
+
+trait Mirror {
+ type Assoc: ?Sized;
+}
+impl<T: ?Sized> Mirror for T {
+ type Assoc = T;
+}
+
+trait Any {}
+impl<T> Any for T {}
+
+struct Signal<'a, T: ?Sized>(<&'a T as Mirror>::Assoc);
+
+// This `CoerceUnsized` impl isn't special; it's a bit more restricted than we'd see in the wild,
+// but this ICE also reproduces if we were to make it general over `Signal<T> -> Signal<U>`.
+impl<'a> CoerceUnsized<Signal<'a, dyn Any>> for Signal<'a, i32> {}
+
+fn main() {
+ Signal(&1i32) as Signal<dyn Any>;
+}
diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs
index cd181f4..28d2d26 100644
--- a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs
+++ b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs
@@ -1,3 +1,5 @@
-//@ compile-flags: --error-format=human --cfg a(b=c)
-//@ error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")
+//@ compile-flags: --cfg a(b=c)
+
fn main() {}
+
+//~? ERROR invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")
diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs
index a0c16bd..a460226 100644
--- a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs
+++ b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs
@@ -1,3 +1,5 @@
-//@ compile-flags: --error-format=human --cfg a{b}
-//@ error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`)
+//@ compile-flags: --cfg a{b}
+
fn main() {}
+
+//~? ERROR invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`)
diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs
index 30402d5..ba34708 100644
--- a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs
+++ b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs
@@ -1,3 +1,5 @@
-//@ compile-flags: --error-format=human --cfg a(b)
-//@ error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`)
+//@ compile-flags: --cfg a(b)
+
fn main() {}
+
+//~? ERROR invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`)
diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs
index e0ce66e..2c2fc10 100644
--- a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs
+++ b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs
@@ -1,3 +1,5 @@
-//@ compile-flags: --error-format=human --cfg a{
-//@ error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
+//@ compile-flags: --cfg a{
+
fn main() {}
+
+//~? ERROR invalid `--cfg` argument: `a{` (expected `key` or `key="value"`)
diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs
index 33f8da2..c9185fc 100644
--- a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs
+++ b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs
@@ -1,3 +1,5 @@
-//@ compile-flags: --error-format=human --cfg )
-//@ error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`)
+//@ compile-flags: --cfg )
+
fn main() {}
+
+//~? ERROR invalid `--cfg` argument: `)` (expected `key` or `key="value"`)
diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs
index 8ab3b10..8d07165 100644
--- a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs
+++ b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs
@@ -1,4 +1,6 @@
// Test for missing quotes around value, issue #66450.
-//@ compile-flags: --error-format=human --cfg key=value
-//@ error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")
+//@ compile-flags: --cfg key=value
+
fn main() {}
+
+//~? ERROR invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\")
diff --git a/tests/ui/conditional-compilation/cfg-empty-codemap.rs b/tests/ui/conditional-compilation/cfg-empty-codemap.rs
index d8fc027..9f7ef1b 100644
--- a/tests/ui/conditional-compilation/cfg-empty-codemap.rs
+++ b/tests/ui/conditional-compilation/cfg-empty-codemap.rs
@@ -1,8 +1,8 @@
// Tests that empty source_maps don't ICE (#23301)
-//@ compile-flags: --error-format=human --cfg ""
-
-//@ error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`)
+//@ compile-flags: --cfg ""
pub fn main() {
}
+
+//~? ERROR invalid `--cfg` argument: `""` (expected `key` or `key="value"`)
diff --git a/tests/ui/conditional-compilation/cfg-generic-params.rs b/tests/ui/conditional-compilation/cfg-generic-params.rs
index 4bb8f8a..6480a0f 100644
--- a/tests/ui/conditional-compilation/cfg-generic-params.rs
+++ b/tests/ui/conditional-compilation/cfg-generic-params.rs
@@ -1,18 +1,18 @@
//@ compile-flags:--cfg yes --check-cfg=cfg(yes,no)
-fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(FALSE)] T>() {}
-fn f_ty<#[cfg(FALSE)] 'a: 'a, #[cfg(yes)] T>() {}
+fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(false)] T>() {}
+fn f_ty<#[cfg(false)] 'a: 'a, #[cfg(yes)] T>() {}
-type FnGood = for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> fn(); // OK
-type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn();
+type FnGood = for<#[cfg(yes)] 'a, #[cfg(false)] T> fn(); // OK
+type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn();
//~^ ERROR only lifetime parameters can be used in this context
-type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> Copy; // OK
-type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy;
+type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(false)] T> Copy; // OK
+type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy;
//~^ ERROR only lifetime parameters can be used in this context
-struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> u8: Copy; // OK
-struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy;
+struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(false)] T> u8: Copy; // OK
+struct WhereBad where for<#[cfg(false)] 'a, #[cfg(yes)] T> u8: Copy;
//~^ ERROR only lifetime parameters can be used in this context
fn f_lt_no<#[cfg_attr(FALSE, unknown)] 'a>() {} // OK
diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr
index 563616b..bae75dd 100644
--- a/tests/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr
@@ -31,7 +31,7 @@
error[E0658]: only lifetime parameters can be used in this context
--> $DIR/cfg-generic-params.rs:7:48
|
-LL | type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn();
+LL | type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn();
| ^
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
@@ -41,7 +41,7 @@
error[E0658]: only lifetime parameters can be used in this context
--> $DIR/cfg-generic-params.rs:11:54
|
-LL | type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy;
+LL | type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy;
| ^
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
@@ -51,7 +51,7 @@
error[E0658]: only lifetime parameters can be used in this context
--> $DIR/cfg-generic-params.rs:15:57
|
-LL | struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy;
+LL | struct WhereBad where for<#[cfg(false)] 'a, #[cfg(yes)] T> u8: Copy;
| ^
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.rs b/tests/ui/conditional-compilation/cfg-in-crate-1.rs
index a1faa23..b9efa32 100644
--- a/tests/ui/conditional-compilation/cfg-in-crate-1.rs
+++ b/tests/ui/conditional-compilation/cfg-in-crate-1.rs
@@ -1 +1 @@
-#![cfg(FALSE)] //~ ERROR `main` function not found in crate `cfg_in_crate_1`
+#![cfg(false)] //~ ERROR `main` function not found in crate `cfg_in_crate_1`
diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr
index 126e10cf..352baf3 100644
--- a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr
+++ b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr
@@ -1,7 +1,7 @@
error[E0601]: `main` function not found in crate `cfg_in_crate_1`
--> $DIR/cfg-in-crate-1.rs:1:15
|
-LL | #![cfg(FALSE)]
+LL | #![cfg(false)]
| ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
error: aborting due to 1 previous error
diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.rs b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs
index ae85f38..cae07ae 100644
--- a/tests/ui/conditional-compilation/cfg-non-opt-expr.rs
+++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs
@@ -2,10 +2,10 @@
#![feature(custom_test_frameworks)]
fn main() {
- let _ = #[cfg(FALSE)] ();
+ let _ = #[cfg(false)] ();
//~^ ERROR removing an expression is not supported in this position
- let _ = 1 + 2 + #[cfg(FALSE)] 3;
+ let _ = 1 + 2 + #[cfg(false)] 3;
//~^ ERROR removing an expression is not supported in this position
- let _ = [1, 2, 3][#[cfg(FALSE)] 1];
+ let _ = [1, 2, 3][#[cfg(false)] 1];
//~^ ERROR removing an expression is not supported in this position
}
diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr
index 06eaa59..bd1bfeb 100644
--- a/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr
+++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr
@@ -1,19 +1,19 @@
error: removing an expression is not supported in this position
--> $DIR/cfg-non-opt-expr.rs:5:13
|
-LL | let _ = #[cfg(FALSE)] ();
+LL | let _ = #[cfg(false)] ();
| ^^^^^^^^^^^^^
error: removing an expression is not supported in this position
--> $DIR/cfg-non-opt-expr.rs:7:21
|
-LL | let _ = 1 + 2 + #[cfg(FALSE)] 3;
+LL | let _ = 1 + 2 + #[cfg(false)] 3;
| ^^^^^^^^^^^^^
error: removing an expression is not supported in this position
--> $DIR/cfg-non-opt-expr.rs:9:23
|
-LL | let _ = [1, 2, 3][#[cfg(FALSE)] 1];
+LL | let _ = [1, 2, 3][#[cfg(false)] 1];
| ^^^^^^^^^^^^^
error: aborting due to 3 previous errors
diff --git a/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs
index 2ac57f3..7753b7d 100644
--- a/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs
+++ b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs
@@ -1,6 +1,6 @@
//@ revisions: edition2015 edition2021
-//@ [edition2015]compile-flags: --edition=2015
-//@ [edition2021]compile-flags: --edition=2021
+//@ [edition2015] edition: 2015
+//@ [edition2021] edition: 2021
#![feature(extern_types)]
#![feature(cfg_accessible)]
diff --git a/tests/ui/conditional-compilation/module_with_cfg.rs b/tests/ui/conditional-compilation/module_with_cfg.rs
index 778379f..a96f8a3 100644
--- a/tests/ui/conditional-compilation/module_with_cfg.rs
+++ b/tests/ui/conditional-compilation/module_with_cfg.rs
@@ -1,3 +1,3 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `./inner-cfg-non-inline-mod.rs`)
-#![cfg_attr(all(), cfg(FALSE))]
+#![cfg_attr(all(), cfg(false))]
diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.rs b/tests/ui/const-generics/defaults/pretty-printing-ast.rs
index 20bf900..f7a166d 100644
--- a/tests/ui/const-generics/defaults/pretty-printing-ast.rs
+++ b/tests/ui/const-generics/defaults/pretty-printing-ast.rs
@@ -1,6 +1,7 @@
// Test the AST pretty printer correctly handles default values for const generics
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
#![crate_type = "lib"]
diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout
index f1cd145..b6cb7fa 100644
--- a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout
+++ b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout
@@ -3,6 +3,7 @@
// Test the AST pretty printer correctly handles default values for const generics
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
#![crate_type = "lib"]
#[prelude_import]
diff --git a/tests/ui/const-generics/generic_const_exprs/const-generics-closure.rs b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.rs
new file mode 100644
index 0000000..aad8cef
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.rs
@@ -0,0 +1,13 @@
+// Regression test for issue #127424
+
+fn bar() -> impl Into<
+ [u8; {
+ //~^ ERROR mismatched types [E0308]
+ let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { *x };
+ //~^ ERROR `for<...>` binders for closures are experimental [E0658]
+ }],
+> {
+ [89]
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr
new file mode 100644
index 0000000..5410bbd
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr
@@ -0,0 +1,26 @@
+error[E0658]: `for<...>` binders for closures are experimental
+ --> $DIR/const-generics-closure.rs:6:17
+ |
+LL | let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { *x };
+ | ^^^^^^^^^^^
+ |
+ = note: see issue #97362 <https://github.com/rust-lang/rust/issues/97362> for more information
+ = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+ = help: consider removing `for<...>`
+
+error[E0308]: mismatched types
+ --> $DIR/const-generics-closure.rs:4:10
+ |
+LL | [u8; {
+ | __________^
+LL | |
+LL | | let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { *x };
+LL | |
+LL | | }],
+ | |_____^ expected `usize`, found `()`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const-blocks/const-block-in-array-size.rs b/tests/ui/consts/const-blocks/const-block-in-array-size.rs
new file mode 100644
index 0000000..ecab2432
--- /dev/null
+++ b/tests/ui/consts/const-blocks/const-block-in-array-size.rs
@@ -0,0 +1,5 @@
+//@ check-pass
+
+type A = [u32; const { 2 }];
+
+fn main() {}
diff --git a/tests/ui/consts/const-cast-wrong-type.rs b/tests/ui/consts/const-cast-wrong-type.rs
index 6e055a2..9936a66 100644
--- a/tests/ui/consts/const-cast-wrong-type.rs
+++ b/tests/ui/consts/const-cast-wrong-type.rs
@@ -1,5 +1,5 @@
const a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8];
-const b: *const i8 = &a as *const i8; //~ ERROR mismatched types
+const b: *const i8 = &a as *const i8; //~ ERROR casting `&[u8; 3]` as `*const i8` is invalid
fn main() {
}
diff --git a/tests/ui/consts/const-cast-wrong-type.stderr b/tests/ui/consts/const-cast-wrong-type.stderr
index 44361f1..0730bac 100644
--- a/tests/ui/consts/const-cast-wrong-type.stderr
+++ b/tests/ui/consts/const-cast-wrong-type.stderr
@@ -1,9 +1,9 @@
-error[E0308]: mismatched types
+error[E0606]: casting `&[u8; 3]` as `*const i8` is invalid
--> $DIR/const-cast-wrong-type.rs:2:22
|
LL | const b: *const i8 = &a as *const i8;
- | ^^^^^^^^^^^^^^^ expected `u8`, found `i8`
+ | ^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs
index 7ced248..5072897 100644
--- a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs
+++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs
@@ -1,6 +1,6 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn container() {
const unsafe WhereIsFerris Now() {}
//~^ ERROR expected one of `extern` or `fn`
diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs
index 6f575d0..20e79ca 100644
--- a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs
+++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs
@@ -1,6 +1,6 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn container() {
const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 }
//~^ ERROR expected `fn`
diff --git a/tests/ui/consts/const-suggest-feature.rs b/tests/ui/consts/const-suggest-feature.rs
index 0c94036..dbb166d 100644
--- a/tests/ui/consts/const-suggest-feature.rs
+++ b/tests/ui/consts/const-suggest-feature.rs
@@ -1,4 +1,4 @@
-//@compile-flags: --edition 2018
+//@ edition: 2018
use std::cell::Cell;
const WRITE: () = unsafe {
diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
index d6f0799..8f2bcd8 100644
--- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
+++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![unstable(feature = "humans",
reason = "who ever let humans program computers,
we're apparently really bad at it",
diff --git a/tests/ui/consts/miri_unleashed/drop.rs b/tests/ui/consts/miri_unleashed/drop.rs
index 17d0892..190072d 100644
--- a/tests/ui/consts/miri_unleashed/drop.rs
+++ b/tests/ui/consts/miri_unleashed/drop.rs
@@ -1,5 +1,4 @@
//@ compile-flags: -Zunleash-the-miri-inside-of-you
-//@ error-pattern: calling non-const function `<Vec<i32> as Drop>::drop`
use std::mem::ManuallyDrop;
@@ -15,5 +14,7 @@ fn main() {}
static TEST_BAD: () = {
let _v: Vec<i32> = Vec::new();
}; //~ ERROR could not evaluate static initializer
+ //~| NOTE calling non-const function `<Vec<i32> as Drop>::drop`
+ //~| NOTE inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))`
//~? WARN skipping const checks
diff --git a/tests/ui/consts/miri_unleashed/drop.stderr b/tests/ui/consts/miri_unleashed/drop.stderr
index 40a29d5..f9ff549 100644
--- a/tests/ui/consts/miri_unleashed/drop.stderr
+++ b/tests/ui/consts/miri_unleashed/drop.stderr
@@ -1,5 +1,5 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/drop.rs:17:1
+ --> $DIR/drop.rs:16:1
|
LL | };
| ^ calling non-const function `<Vec<i32> as Drop>::drop`
@@ -10,7 +10,7 @@
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/drop.rs:16:9
+ --> $DIR/drop.rs:15:9
|
LL | let _v: Vec<i32> = Vec::new();
| ^^
diff --git a/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr
index 4a47671..b6f2e01 100644
--- a/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr
+++ b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr
@@ -16,6 +16,7 @@
| | within this `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}`
| | this tail expression is of type `{closure@contract-captures-via-closure-noncopy.rs:12:42}`
| unsatisfied trait bound
+ | required by a bound introduced by this call
|
= help: within `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}`, the trait `std::marker::Copy` is not implemented for `Baz`
note: required because it's used within this closure
diff --git a/tests/ui/contracts/contract-const-fn.all_pass.stderr b/tests/ui/contracts/contract-const-fn.all_pass.stderr
new file mode 100644
index 0000000..e5b1df6
--- /dev/null
+++ b/tests/ui/contracts/contract-const-fn.all_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/contract-const-fn.rs:17:12
+ |
+LL | #![feature(contracts)]
+ | ^^^^^^^^^
+ |
+ = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-const-fn.rs b/tests/ui/contracts/contract-const-fn.rs
new file mode 100644
index 0000000..733a06a
--- /dev/null
+++ b/tests/ui/contracts/contract-const-fn.rs
@@ -0,0 +1,56 @@
+//! Check if we can annotate a constant function with contracts.
+//!
+//! The contract is only checked at runtime, and it will not fail if evaluated statically.
+//! This is an existing limitation due to the existing architecture and the lack of constant
+//! closures.
+//!
+//@ revisions: all_pass runtime_fail_pre runtime_fail_post
+//
+//@ [all_pass] run-pass
+//
+//@ [runtime_fail_pre] run-fail
+//@ [runtime_fail_post] run-fail
+//
+//@ [all_pass] compile-flags: -Zcontract-checks=yes
+//@ [runtime_fail_pre] compile-flags: -Zcontract-checks=yes
+//@ [runtime_fail_post] compile-flags: -Zcontract-checks=yes
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+extern crate core;
+use core::contracts::*;
+
+#[requires(x < 100)]
+const fn less_than_100(x: u8) -> u8 {
+ x
+}
+
+// This is wrong on purpose.
+#[ensures(|ret| *ret)]
+const fn always_true(b: bool) -> bool {
+ b
+}
+
+const ZERO: u8 = less_than_100(0);
+// This is no-op because the contract cannot be checked at compilation time.
+const TWO_HUNDRED: u8 = less_than_100(200);
+
+/// Example from <https://github.com/rust-lang/rust/issues/136925>.
+#[ensures(move |ret: &u32| *ret > x)]
+const fn broken_sum(x: u32, y: u32) -> u32 {
+ x + y
+}
+
+fn main() {
+ assert_eq!(ZERO, 0);
+ assert_eq!(TWO_HUNDRED, 200);
+ assert_eq!(broken_sum(0, 1), 1);
+ assert_eq!(always_true(true), true);
+
+ #[cfg(runtime_fail_post)]
+ let _ok = always_true(false);
+
+ // Runtime check should fail.
+ #[cfg(runtime_fail_pre)]
+ let _200 = less_than_100(200);
+}
diff --git a/tests/ui/contracts/contract-const-fn.runtime_fail_post.stderr b/tests/ui/contracts/contract-const-fn.runtime_fail_post.stderr
new file mode 100644
index 0000000..e5b1df6
--- /dev/null
+++ b/tests/ui/contracts/contract-const-fn.runtime_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/contract-const-fn.rs:17:12
+ |
+LL | #![feature(contracts)]
+ | ^^^^^^^^^
+ |
+ = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-const-fn.runtime_fail_pre.stderr b/tests/ui/contracts/contract-const-fn.runtime_fail_pre.stderr
new file mode 100644
index 0000000..e5b1df6
--- /dev/null
+++ b/tests/ui/contracts/contract-const-fn.runtime_fail_pre.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/contract-const-fn.rs:17:12
+ |
+LL | #![feature(contracts)]
+ | ^^^^^^^^^
+ |
+ = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
index ae692af..c62b8cc 100644
--- a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
+++ b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
@@ -26,11 +26,11 @@ fn main() {
#[cfg(any(default, unchk_pass, chk_fail_requires))]
core::intrinsics::contract_check_requires(|| false);
- let doubles_to_two = { let old = 2; move |ret| ret + ret == old };
+ let doubles_to_two = { let old = 2; move |ret: &u32 | ret + ret == old };
// Always pass
- core::intrinsics::contract_check_ensures(&1, doubles_to_two);
+ core::intrinsics::contract_check_ensures(doubles_to_two, 1);
// Fail if enabled
#[cfg(any(default, unchk_pass, chk_fail_ensures))]
- core::intrinsics::contract_check_ensures(&2, doubles_to_two);
+ core::intrinsics::contract_check_ensures(doubles_to_two, 2);
}
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.rs b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
index e91bbed..73c5919 100644
--- a/tests/ui/contracts/internal_machinery/contract-lang-items.rs
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
@@ -15,14 +15,14 @@
#![feature(contracts)] // to access core::contracts
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
#![feature(contracts_internals)] // to access check_requires lang item
-
+#![feature(core_intrinsics)]
fn foo(x: Baz) -> i32 {
let injected_checker = {
core::contracts::build_check_ensures(|ret| *ret > 100)
};
let ret = x.baz + 50;
- injected_checker(ret)
+ core::intrinsics::contract_check_ensures(injected_checker, ret)
}
struct Baz { baz: i32 }
diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.rs b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs
index 1b76eef..6e5a7a3 100644
--- a/tests/ui/contracts/internal_machinery/internal-feature-gating.rs
+++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs
@@ -6,7 +6,7 @@ fn main() {
//~^ ERROR use of unstable library feature `contracts_internals`
core::intrinsics::contract_check_requires(|| true);
//~^ ERROR use of unstable library feature `contracts_internals`
- core::intrinsics::contract_check_ensures(&1, |_|true);
+ core::intrinsics::contract_check_ensures( |_|true, &1);
//~^ ERROR use of unstable library feature `contracts_internals`
core::contracts::build_check_ensures(|_: &()| true);
diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr
index 7302694..1e39bd6 100644
--- a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr
+++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr
@@ -41,7 +41,7 @@
error[E0658]: use of unstable library feature `contracts_internals`
--> $DIR/internal-feature-gating.rs:9:5
|
-LL | core::intrinsics::contract_check_ensures(&1, |_|true);
+LL | core::intrinsics::contract_check_ensures( |_|true, &1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
diff --git a/tests/ui/coroutine/async-gen-deduce-yield.rs b/tests/ui/coroutine/async-gen-deduce-yield.rs
index f85e4a5..a9572ee 100644
--- a/tests/ui/coroutine/async-gen-deduce-yield.rs
+++ b/tests/ui/coroutine/async-gen-deduce-yield.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2024
+//@ edition: 2024
//@ check-pass
#![feature(async_iterator, gen_blocks)]
diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs
index 583820c..53e3ce7 100644
--- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs
+++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2024
+//@ edition: 2024
//@ check-pass
#![feature(async_iterator, gen_blocks)]
diff --git a/tests/ui/coroutine/higher-ranked-rigid.rs b/tests/ui/coroutine/higher-ranked-rigid.rs
new file mode 100644
index 0000000..23a7d51
--- /dev/null
+++ b/tests/ui/coroutine/higher-ranked-rigid.rs
@@ -0,0 +1,41 @@
+//@ edition: 2024
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/177>.
+// Coroutines erase all free lifetimes from their interior types, replacing them with higher-
+// ranked regions which act as universals, to properly represent the fact that we don't know what
+// the value of the region is within the coroutine.
+//
+// In the future in `from_request`, that means that the `'r` lifetime is being replaced in
+// `<T as FromRequest<'r>>::Assoc`, which is in present in the existential bounds of the
+// `dyn Future` that it's awaiting. Normalizing this associated type, with its free lifetimes
+// replaced, means proving `T: FromRequest<'!0>`, which doesn't hold without constraining the
+// `'!0` lifetime, which we don't do today.
+
+// Proving `T: Trait` holds when `<T as Trait>::Assoc` is rigid is not necessary for soundness,
+// at least not *yet*, and it's not even necessary for diagnostics since we have other special
+// casing for, e.g., AliasRelate goals failing in the BestObligation folder.
+
+// The old solver unintentioanlly avoids this by never checking that `T: Trait` holds when
+// `<T as Trait>::Assoc` is rigid. Introducing this additional requirement when projecting rigidly
+// in the old solver causes this (and tons of production crates) to fail. See the fallout from the
+// crater run at <https://github.com/rust-lang/rust/pull/139763>.
+
+use std::future::Future;
+use std::pin::Pin;
+
+pub trait FromRequest<'r> {
+ type Assoc;
+ fn from_request() -> Pin<Box<dyn Future<Output = Self::Assoc> + Send>>;
+}
+
+fn test<'r, T: FromRequest<'r>>() -> Pin<Box<dyn Future<Output = ()> + Send>> {
+ Box::pin(async move {
+ T::from_request().await;
+ })
+}
+
+fn main() {}
diff --git a/tests/ui/coroutine/postfix-yield.rs b/tests/ui/coroutine/postfix-yield.rs
index ff84313..f2fdceb 100644
--- a/tests/ui/coroutine/postfix-yield.rs
+++ b/tests/ui/coroutine/postfix-yield.rs
@@ -3,7 +3,7 @@
//@ run-pass
//@ edition: 2024
-#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)]
+#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr, stmt_expr_attributes)]
use std::ops::{Coroutine, CoroutineState};
use std::pin::pin;
diff --git a/tests/ui/cross/cross-file-errors/underscore.rs b/tests/ui/cross/cross-file-errors/underscore.rs
index 9d07573..73eb36c 100644
--- a/tests/ui/cross/cross-file-errors/underscore.rs
+++ b/tests/ui/cross/cross-file-errors/underscore.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `./main.rs`)
#![crate_type = "lib"]
macro_rules! underscore {
diff --git a/tests/ui/debuginfo/dwarf-versions.rs b/tests/ui/debuginfo/dwarf-versions.rs
index 6030b2f..8f731f1 100644
--- a/tests/ui/debuginfo/dwarf-versions.rs
+++ b/tests/ui/debuginfo/dwarf-versions.rs
@@ -1,26 +1,25 @@
// This test verifies the expected behavior of various options passed to
-// `-Zdwarf-version`: 2 - 5 (valid) with all other options being invalid.
+// `-Cdwarf-version`: 2 - 5 (valid) with all other options being invalid.
//@ revisions: zero one two three four five six
-//@[zero] compile-flags: -Zdwarf-version=0
+//@[zero] compile-flags: -Cdwarf-version=0
-//@[one] compile-flags: -Zdwarf-version=1
-//@[one] error-pattern: requested DWARF version 1 is not supported
+//@[one] compile-flags: -Cdwarf-version=1
-//@[two] compile-flags: -Zdwarf-version=2
+//@[two] compile-flags: -Cdwarf-version=2
//@[two] check-pass
-//@[three] compile-flags: -Zdwarf-version=3
+//@[three] compile-flags: -Cdwarf-version=3
//@[three] check-pass
-//@[four] compile-flags: -Zdwarf-version=4
+//@[four] compile-flags: -Cdwarf-version=4
//@[four] check-pass
-//@[five] compile-flags: -Zdwarf-version=5
+//@[five] compile-flags: -Cdwarf-version=5
//@[five] check-pass
-//@[six] compile-flags: -Zdwarf-version=6
+//@[six] compile-flags: -Cdwarf-version=6
//@ compile-flags: -g --target x86_64-unknown-linux-gnu --crate-type cdylib
//@ needs-llvm-components: x86
diff --git a/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs
index 7b850f3..e926a33 100644
--- a/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs
+++ b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs
@@ -1,5 +1,6 @@
//@ run-pass
-//@ compile-flags: --edition 2021 -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3
+//@ compile-flags: -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3
+//@ edition: 2021
fn main() {
TranslatorI.visit_pre();
diff --git a/tests/ui/delegation/explicit-paths-signature-pass.rs b/tests/ui/delegation/explicit-paths-signature-pass.rs
index 8c16ad9..11bc8a7 100644
--- a/tests/ui/delegation/explicit-paths-signature-pass.rs
+++ b/tests/ui/delegation/explicit-paths-signature-pass.rs
@@ -6,7 +6,7 @@
mod to_reuse {
use crate::S;
- pub fn foo<'a>(#[cfg(FALSE)] a: u8, _b: &'a S) -> u32 {
+ pub fn foo<'a>(#[cfg(false)] a: u8, _b: &'a S) -> u32 {
1
}
}
diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr
index 2b0bcf9..cb14d9f 100644
--- a/tests/ui/delegation/unsupported.stderr
+++ b/tests/ui/delegation/unsupported.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{synthetic#0}`
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`
--> $DIR/unsupported.rs:22:25
|
LL | reuse to_reuse::opaque_ret;
@@ -9,7 +9,7 @@
|
LL | reuse to_reuse::opaque_ret;
| ^^^^^^^^^^
- = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{synthetic#0}`, completing the cycle
+ = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>` is well-formed
--> $DIR/unsupported.rs:21:5
|
@@ -17,7 +17,7 @@
| ^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{synthetic#0}`
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`
--> $DIR/unsupported.rs:25:24
|
LL | reuse ToReuse::opaque_ret;
@@ -28,7 +28,7 @@
|
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
- = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{synthetic#0}`, completing the cycle
+ = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>` is well-formed
--> $DIR/unsupported.rs:24:5
|
diff --git a/tests/ui/deprecation/try-macro-suggestion.rs b/tests/ui/deprecation/try-macro-suggestion.rs
index 1e477ab..0775f00 100644
--- a/tests/ui/deprecation/try-macro-suggestion.rs
+++ b/tests/ui/deprecation/try-macro-suggestion.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
fn foo() -> Result<(), ()> {
Ok(try!()); //~ ERROR use of deprecated `try` macro
Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
diff --git a/tests/ui/deriving/built-in-proc-macro-scope.rs b/tests/ui/deriving/built-in-proc-macro-scope.rs
index e67197b..69128a0 100644
--- a/tests/ui/deriving/built-in-proc-macro-scope.rs
+++ b/tests/ui/deriving/built-in-proc-macro-scope.rs
@@ -1,6 +1,7 @@
//@ check-pass
//@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded
+//@ edition:2015
#![feature(derive_coerce_pointee)]
diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout
index fa4e509..2697618 100644
--- a/tests/ui/deriving/built-in-proc-macro-scope.stdout
+++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout
@@ -3,6 +3,7 @@
//@ check-pass
//@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded
+//@ edition:2015
#![feature(derive_coerce_pointee)]
#[prelude_import]
diff --git a/tests/ui/deriving/deriving-coerce-pointee-expanded.rs b/tests/ui/deriving/deriving-coerce-pointee-expanded.rs
index 94be703..9394ae4 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-expanded.rs
+++ b/tests/ui/deriving/deriving-coerce-pointee-expanded.rs
@@ -1,5 +1,6 @@
//@ check-pass
//@ compile-flags: -Zunpretty=expanded
+//@ edition: 2015
#![feature(derive_coerce_pointee)]
use std::marker::CoercePointee;
diff --git a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout
index a774efb..84f8e9a 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout
+++ b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout
@@ -2,6 +2,7 @@
#![no_std]
//@ check-pass
//@ compile-flags: -Zunpretty=expanded
+//@ edition: 2015
#![feature(derive_coerce_pointee)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.rs b/tests/ui/deriving/proc-macro-attribute-mixing.rs
index 2c11c3f..c9e123d 100644
--- a/tests/ui/deriving/proc-macro-attribute-mixing.rs
+++ b/tests/ui/deriving/proc-macro-attribute-mixing.rs
@@ -7,6 +7,7 @@
//@ check-pass
//@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded
+//@ edition: 2015
#![feature(derive_coerce_pointee)]
diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.stdout b/tests/ui/deriving/proc-macro-attribute-mixing.stdout
index ad743d0..faa9c02 100644
--- a/tests/ui/deriving/proc-macro-attribute-mixing.stdout
+++ b/tests/ui/deriving/proc-macro-attribute-mixing.stdout
@@ -9,6 +9,7 @@
//@ check-pass
//@ proc-macro: another-proc-macro.rs
//@ compile-flags: -Zunpretty=expanded
+//@ edition: 2015
#![feature(derive_coerce_pointee)]
#[prelude_import]
diff --git a/tests/ui/did_you_mean/E0178.stderr b/tests/ui/did_you_mean/E0178.stderr
index 5f289da..36e4dbd 100644
--- a/tests/ui/did_you_mean/E0178.stderr
+++ b/tests/ui/did_you_mean/E0178.stderr
@@ -1,41 +1,43 @@
-error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:6:8
|
LL | w: &'a Foo + Copy,
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try adding parentheses
|
LL | w: &'a (Foo + Copy),
| + +
-error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:7:8
|
LL | x: &'a Foo + 'a,
- | ^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try adding parentheses
|
LL | x: &'a (Foo + 'a),
| + +
-error[E0178]: expected a path on the left-hand side of `+`, not `&'a mut Foo`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:8:8
|
LL | y: &'a mut Foo + 'a,
- | ^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^
|
help: try adding parentheses
|
LL | y: &'a mut (Foo + 'a),
| + +
-error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:9:8
|
LL | z: fn() -> Foo + 'a,
- | ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses?
+ | ^^^^^^^^^^^-----
+ | |
+ | perhaps you forgot parentheses?
error: aborting due to 4 previous errors
diff --git a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
index d4812d4..c74cb89 100644
--- a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
+++ b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
@@ -66,7 +66,6 @@
LL | let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
| ^
|
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: try adding parentheses to match on a tuple
|
LL | let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
index 4fee6cc..762b37b 100644
--- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
+++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
@@ -1,19 +1,19 @@
-error[E0178]: expected a path on the left-hand side of `+`, not `&Copy`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
|
LL | let _: &Copy + 'static;
- | ^^^^^^^^^^^^^^^
+ | ^^^^^
|
help: try adding parentheses
|
LL | let _: &(Copy + 'static);
| + +
-error[E0178]: expected a path on the left-hand side of `+`, not `&'static Copy`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-reference-without-parens-suggestion.rs:6:12
|
LL | let _: &'static Copy + 'static;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^
|
help: try adding parentheses
|
diff --git a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs
index 1d832a3..2ccdd79 100644
--- a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs
+++ b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs
@@ -1 +1 @@
-//@ ignore-test not a test, auxiliary
+//@ ignore-auxiliary (used by `../../macro-expanded-mod.rs`)
diff --git a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs
index 08349ba..9009f80 100644
--- a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs
+++ b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs
@@ -1,3 +1,3 @@
-//@ ignore-test not a test, auxiliary
+//@ ignore-auxiliary (used by `../../macro-expanded-mod.rs`)
mod_decl!(bar);
diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs
deleted file mode 100644
index 6d6884f..0000000
--- a/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//@ ignore-test this is not a test
-
-macro_rules! m {
- () => { mod mod_file_not_owning_aux2; }
-}
-m!();
diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs
deleted file mode 100644
index 76f1c1a..0000000
--- a/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs
+++ /dev/null
@@ -1 +0,0 @@
-//@ ignore-test this is not a test
diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs
deleted file mode 100644
index 96a5780..0000000
--- a/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//@ ignore-test this is not a test
-
-mod mod_file_not_owning_aux2;
diff --git a/tests/crashes/137287.rs b/tests/ui/drop/drop_elaboration_with_errors2.rs
similarity index 67%
rename from tests/crashes/137287.rs
rename to tests/ui/drop/drop_elaboration_with_errors2.rs
index 59fdf56..946c253 100644
--- a/tests/crashes/137287.rs
+++ b/tests/ui/drop/drop_elaboration_with_errors2.rs
@@ -1,11 +1,14 @@
-//@ known-bug: #137287
+// Regression test for #137287
mod defining_scope {
use super::*;
pub type Alias<T> = impl Sized;
+ //~^ ERROR unconstrained opaque type
+ //~| ERROR `impl Trait` in type aliases is unstable
pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
x
+ //~^ ERROR mismatched types
}
}
@@ -21,6 +24,7 @@ impl<T> Trait<T> for T {
type Assoc = Box<u32>;
}
impl<T> Trait<T> for defining_scope::Alias<T> {
+ //~^ ERROR conflicting implementations of trait `Trait<_>`
type Assoc = usize;
}
diff --git a/tests/ui/drop/drop_elaboration_with_errors2.stderr b/tests/ui/drop/drop_elaboration_with_errors2.stderr
new file mode 100644
index 0000000..15fe3f6
--- /dev/null
+++ b/tests/ui/drop/drop_elaboration_with_errors2.stderr
@@ -0,0 +1,47 @@
+error[E0658]: `impl Trait` in type aliases is unstable
+ --> $DIR/drop_elaboration_with_errors2.rs:5:25
+ |
+LL | pub type Alias<T> = impl Sized;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+ = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0119]: conflicting implementations of trait `Trait<_>`
+ --> $DIR/drop_elaboration_with_errors2.rs:26:1
+ |
+LL | impl<T> Trait<T> for T {
+ | ---------------------- first implementation here
+...
+LL | impl<T> Trait<T> for defining_scope::Alias<T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: unconstrained opaque type
+ --> $DIR/drop_elaboration_with_errors2.rs:5:25
+ |
+LL | pub type Alias<T> = impl Sized;
+ | ^^^^^^^^^^
+ |
+ = note: `Alias` must be used in combination with a concrete type within the same crate
+
+error[E0308]: mismatched types
+ --> $DIR/drop_elaboration_with_errors2.rs:10:9
+ |
+LL | pub type Alias<T> = impl Sized;
+ | ---------- the found opaque type
+...
+LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
+ | - expected this type parameter --------------- expected `Container<T, T>` because of return type
+LL | x
+ | ^ expected `Container<T, T>`, found `Container<Alias<T>, T>`
+ |
+ = note: expected struct `Container<T, _>`
+ found struct `Container<Alias<T>, _>`
+ = help: type parameters must be constrained to match other types
+ = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0119, E0308, E0658.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/crashes/135668.rs b/tests/ui/drop/drop_elaboration_with_errors3.rs
similarity index 84%
rename from tests/crashes/135668.rs
rename to tests/ui/drop/drop_elaboration_with_errors3.rs
index 8126a65..c5ed63e 100644
--- a/tests/crashes/135668.rs
+++ b/tests/ui/drop/drop_elaboration_with_errors3.rs
@@ -1,5 +1,6 @@
-//@ known-bug: #135668
-//@ compile-flags: --edition=2021
+// Regression test for #135668
+//@ edition: 2021
+
use std::future::Future;
pub async fn foo() {
@@ -11,7 +12,8 @@ async fn create_task() -> impl Sized {
}
async fn documentation() {
- include_str!("nonexistent");
+ compile_error!("bonjour");
+ //~^ ERROR bonjour
}
fn bind<F>(_filter: F) -> impl Sized
@@ -36,3 +38,5 @@ impl<F, R> FilterBase for F
{
type Assoc = F;
}
+
+fn main() {}
diff --git a/tests/ui/drop/drop_elaboration_with_errors3.stderr b/tests/ui/drop/drop_elaboration_with_errors3.stderr
new file mode 100644
index 0000000..2d44e7c
--- /dev/null
+++ b/tests/ui/drop/drop_elaboration_with_errors3.stderr
@@ -0,0 +1,8 @@
+error: bonjour
+ --> $DIR/drop_elaboration_with_errors3.rs:15:5
+ |
+LL | compile_error!("bonjour");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/error-codes/E0152-duplicate-lang-items.rs b/tests/ui/error-codes/E0152-duplicate-lang-items.rs
index 089810b..f707b72 100644
--- a/tests/ui/error-codes/E0152-duplicate-lang-items.rs
+++ b/tests/ui/error-codes/E0152-duplicate-lang-items.rs
@@ -3,8 +3,9 @@
//!
//! Issue: <https://github.com/rust-lang/rust/issues/31788>
-//@ error-pattern: first defined in crate `std`
//@ normalize-stderr: "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib"
+//@ dont-require-annotations: NOTE
+
#![feature(lang_items)]
extern crate core;
@@ -14,6 +15,7 @@
#[lang = "panic_impl"]
fn panic_impl(info: &PanicInfo) -> ! {
//~^ ERROR: found duplicate lang item `panic_impl`
+ //~| NOTE first defined in crate `std`
loop {}
}
diff --git a/tests/ui/error-codes/E0152-duplicate-lang-items.stderr b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr
index 3c3d643..2fe0d18 100644
--- a/tests/ui/error-codes/E0152-duplicate-lang-items.stderr
+++ b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr
@@ -1,8 +1,9 @@
error[E0152]: found duplicate lang item `panic_impl`
- --> $DIR/E0152-duplicate-lang-items.rs:15:1
+ --> $DIR/E0152-duplicate-lang-items.rs:16:1
|
LL | / fn panic_impl(info: &PanicInfo) -> ! {
LL | |
+LL | |
LL | | loop {}
LL | | }
| |_^
diff --git a/tests/ui/error-codes/E0602.rs b/tests/ui/error-codes/E0602.rs
index cba15bb9..381bd1f 100644
--- a/tests/ui/error-codes/E0602.rs
+++ b/tests/ui/error-codes/E0602.rs
@@ -1,11 +1,11 @@
//@ compile-flags:-D bogus
//@ check-pass
-
-//@ error-pattern:requested on the command line with `-D bogus`
-//@ error-pattern:`#[warn(unknown_lints)]` on by default
+//@ dont-require-annotations: NOTE
fn main() {}
//~? WARN unknown lint: `bogus`
//~? WARN unknown lint: `bogus`
//~? WARN unknown lint: `bogus`
+//~? NOTE requested on the command line with `-D bogus`
+//~? NOTE `#[warn(unknown_lints)]` on by default
diff --git a/tests/ui/errors/pic-linker.rs b/tests/ui/errors/pic-linker.rs
index d909899..36495ca 100644
--- a/tests/ui/errors/pic-linker.rs
+++ b/tests/ui/errors/pic-linker.rs
@@ -5,6 +5,7 @@
//@ ignore-windows
//@ ignore-macos
//@ ignore-cross-compile
+//@ ignore-aix
//@ compile-flags: -Clink-args=-Wl,-z,text
//@ run-pass
diff --git a/tests/ui/expr/if/attrs/bad-cfg.rs b/tests/ui/expr/if/attrs/bad-cfg.rs
index 3f84929..6e7f4b0 100644
--- a/tests/ui/expr/if/attrs/bad-cfg.rs
+++ b/tests/ui/expr/if/attrs/bad-cfg.rs
@@ -1,5 +1,5 @@
#![feature(stmt_expr_attributes)]
fn main() {
- let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression
+ let _ = #[cfg(false)] if true {}; //~ ERROR removing an expression
}
diff --git a/tests/ui/expr/if/attrs/bad-cfg.stderr b/tests/ui/expr/if/attrs/bad-cfg.stderr
index ca0eced..d12f5ee 100644
--- a/tests/ui/expr/if/attrs/bad-cfg.stderr
+++ b/tests/ui/expr/if/attrs/bad-cfg.stderr
@@ -1,7 +1,7 @@
error: removing an expression is not supported in this position
--> $DIR/bad-cfg.rs:4:13
|
-LL | let _ = #[cfg(FALSE)] if true {};
+LL | let _ = #[cfg(false)] if true {};
| ^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/expr/if/attrs/cfg-false-if-attr.rs b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs
index c139b347..e6c83b8 100644
--- a/tests/ui/expr/if/attrs/cfg-false-if-attr.rs
+++ b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs
@@ -1,12 +1,12 @@
//@ check-pass
-#[cfg(FALSE)]
+#[cfg(false)]
fn simple_attr() {
#[attr] if true {}
#[allow_warnings] if true {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn if_else_chain() {
#[first_attr] if true {
} else if false {
@@ -14,20 +14,20 @@ fn if_else_chain() {
}
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn if_let() {
#[attr] if let Some(_) = Some(true) {}
}
fn bar() {
- #[cfg(FALSE)]
+ #[cfg(false)]
if true {
- let x: () = true; // Should not error due to the #[cfg(FALSE)]
+ let x: () = true; // Should not error due to the #[cfg(false)]
}
- #[cfg_attr(not(FALSE), cfg(FALSE))]
+ #[cfg_attr(not(FALSE), cfg(false))]
if true {
- let a: () = true; // Should not error due to the applied #[cfg(FALSE)]
+ let a: () = true; // Should not error due to the applied #[cfg(false)]
}
}
diff --git a/tests/ui/expr/if/attrs/else-attrs.rs b/tests/ui/expr/if/attrs/else-attrs.rs
index 85da7cf..4010d9d 100644
--- a/tests/ui/expr/if/attrs/else-attrs.rs
+++ b/tests/ui/expr/if/attrs/else-attrs.rs
@@ -1,11 +1,11 @@
-#[cfg(FALSE)]
+#[cfg(false)]
fn if_else_parse_error() {
if true {
} #[attr] else if false { //~ ERROR expected
}
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn else_attr_ifparse_error() {
if true {
} else #[attr] if false { //~ ERROR outer attributes are not allowed
@@ -13,7 +13,7 @@ fn else_attr_ifparse_error() {
}
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn else_parse_error() {
if true {
} else if false {
diff --git a/tests/ui/expr/if/attrs/gate-whole-expr.rs b/tests/ui/expr/if/attrs/gate-whole-expr.rs
index bab0159..8859090 100644
--- a/tests/ui/expr/if/attrs/gate-whole-expr.rs
+++ b/tests/ui/expr/if/attrs/gate-whole-expr.rs
@@ -3,7 +3,7 @@
fn main() {
let x = 1;
- #[cfg(FALSE)]
+ #[cfg(false)]
if false {
x = 2;
} else if true {
diff --git a/tests/ui/expr/if/attrs/let-chains-attr.rs b/tests/ui/expr/if/attrs/let-chains-attr.rs
index b3dbd53..2cf1b16 100644
--- a/tests/ui/expr/if/attrs/let-chains-attr.rs
+++ b/tests/ui/expr/if/attrs/let-chains-attr.rs
@@ -2,7 +2,7 @@
#![feature(let_chains)]
-#[cfg(FALSE)]
+#[cfg(false)]
fn foo() {
#[attr]
if let Some(_) = Some(true) && let Ok(_) = Ok(1) {
diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.rs b/tests/ui/extern-flag/invalid-crate-name-dashed.rs
index b336cc8..bbf473c 100644
--- a/tests/ui/extern-flag/invalid-crate-name-dashed.rs
+++ b/tests/ui/extern-flag/invalid-crate-name-dashed.rs
@@ -1,5 +1,4 @@
//@ compile-flags: --extern=my-awesome-library=libawesome.rlib
-//@ error-pattern: consider replacing the dashes with underscores: `my_awesome_library`
// In a sense, this is a regression test for issue #113035. We no longer suggest
// `pub use my-awesome-library::*;` (sic!) as we outright ban this crate name.
@@ -9,3 +8,4 @@
fn main() {}
//~? ERROR crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier
+//~? HELP consider replacing the dashes with underscores: `my_awesome_library`
diff --git a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs b/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs
deleted file mode 100644
index 6784b44..0000000
--- a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#[cfg(true)] //~ ERROR `cfg(true)` is experimental
-fn foo() {}
-
-#[cfg_attr(true, cfg(false))] //~ ERROR `cfg(true)` is experimental
-//~^ ERROR `cfg(false)` is experimental
-fn foo() {}
-
-fn main() {
- cfg!(false); //~ ERROR `cfg(false)` is experimental
-}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.stderr b/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.stderr
deleted file mode 100644
index 6449146..0000000
--- a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error[E0658]: `cfg(true)` is experimental and subject to change
- --> $DIR/feature-gate-cfg-boolean-literals.rs:1:7
- |
-LL | #[cfg(true)]
- | ^^^^
- |
- = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
- = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `cfg(true)` is experimental and subject to change
- --> $DIR/feature-gate-cfg-boolean-literals.rs:4:12
- |
-LL | #[cfg_attr(true, cfg(false))]
- | ^^^^
- |
- = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
- = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `cfg(false)` is experimental and subject to change
- --> $DIR/feature-gate-cfg-boolean-literals.rs:4:22
- |
-LL | #[cfg_attr(true, cfg(false))]
- | ^^^^^
- |
- = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
- = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `cfg(false)` is experimental and subject to change
- --> $DIR/feature-gate-cfg-boolean-literals.rs:9:10
- |
-LL | cfg!(false);
- | ^^^^^
- |
- = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
- = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-coroutines.rs b/tests/ui/feature-gates/feature-gate-coroutines.rs
index f20dc56..b37a61d 100644
--- a/tests/ui/feature-gates/feature-gate-coroutines.rs
+++ b/tests/ui/feature-gates/feature-gate-coroutines.rs
@@ -12,7 +12,7 @@ fn main() {
//~^^ ERROR `yield` can only be used
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn foo() {
// Ok in 2024 edition
yield; //~ ERROR yield syntax is experimental
diff --git a/tests/ui/feature-gates/feature-gate-deref_patterns.rs b/tests/ui/feature-gates/feature-gate-deref_patterns.rs
index b43001f..53b4301 100644
--- a/tests/ui/feature-gates/feature-gate-deref_patterns.rs
+++ b/tests/ui/feature-gates/feature-gate-deref_patterns.rs
@@ -4,6 +4,6 @@
println!("x: {}", x);
// `box` syntax is allowed to be cfg-ed out for historical reasons (#65742).
- #[cfg(FALSE)]
+ #[cfg(false)]
let box _x = Box::new('c');
}
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed
new file mode 100644
index 0000000..525f78d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed
@@ -0,0 +1,45 @@
+// The purpose of this feature gate is to make something into a hard error in a
+// future edition. Consequently, this test differs from most other feature gate
+// tests. Instead of verifying that an error occurs when the feature gate is
+// missing, it ensures that the hard error is only produced with the feature
+// gate is present in the `future` edition -- and otherwise that only a warning
+// is emitted.
+
+//@ revisions: current current_feature future future_feature
+
+//@ [current] run-rustfix
+//@ [current] check-pass
+
+//@ [current_feature] run-rustfix
+//@ [current_feature] check-pass
+
+//@ [future] edition: future
+//@ [future] compile-flags: -Z unstable-options
+//@ [future] run-rustfix
+//@ [future] check-pass
+
+//@ [future_feature] edition: future
+//@ [future_feature] compile-flags: -Z unstable-options
+
+#![cfg_attr(future_feature, feature(explicit_extern_abis))]
+#![cfg_attr(current_feature, feature(explicit_extern_abis))]
+
+extern "C" fn _foo() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern "C" fn _bar() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern "C" {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr
new file mode 100644
index 0000000..cf92780
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr
@@ -0,0 +1,22 @@
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:27:1
+ |
+LL | extern fn _foo() {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+ |
+ = note: `#[warn(missing_abi)]` on by default
+
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:33:8
+ |
+LL | unsafe extern fn _bar() {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:39:8
+ |
+LL | unsafe extern {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed
new file mode 100644
index 0000000..525f78d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed
@@ -0,0 +1,45 @@
+// The purpose of this feature gate is to make something into a hard error in a
+// future edition. Consequently, this test differs from most other feature gate
+// tests. Instead of verifying that an error occurs when the feature gate is
+// missing, it ensures that the hard error is only produced with the feature
+// gate is present in the `future` edition -- and otherwise that only a warning
+// is emitted.
+
+//@ revisions: current current_feature future future_feature
+
+//@ [current] run-rustfix
+//@ [current] check-pass
+
+//@ [current_feature] run-rustfix
+//@ [current_feature] check-pass
+
+//@ [future] edition: future
+//@ [future] compile-flags: -Z unstable-options
+//@ [future] run-rustfix
+//@ [future] check-pass
+
+//@ [future_feature] edition: future
+//@ [future_feature] compile-flags: -Z unstable-options
+
+#![cfg_attr(future_feature, feature(explicit_extern_abis))]
+#![cfg_attr(current_feature, feature(explicit_extern_abis))]
+
+extern "C" fn _foo() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern "C" fn _bar() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern "C" {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr
new file mode 100644
index 0000000..cf92780
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr
@@ -0,0 +1,22 @@
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:27:1
+ |
+LL | extern fn _foo() {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+ |
+ = note: `#[warn(missing_abi)]` on by default
+
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:33:8
+ |
+LL | unsafe extern fn _bar() {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:39:8
+ |
+LL | unsafe extern {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed
new file mode 100644
index 0000000..525f78d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed
@@ -0,0 +1,45 @@
+// The purpose of this feature gate is to make something into a hard error in a
+// future edition. Consequently, this test differs from most other feature gate
+// tests. Instead of verifying that an error occurs when the feature gate is
+// missing, it ensures that the hard error is only produced with the feature
+// gate is present in the `future` edition -- and otherwise that only a warning
+// is emitted.
+
+//@ revisions: current current_feature future future_feature
+
+//@ [current] run-rustfix
+//@ [current] check-pass
+
+//@ [current_feature] run-rustfix
+//@ [current_feature] check-pass
+
+//@ [future] edition: future
+//@ [future] compile-flags: -Z unstable-options
+//@ [future] run-rustfix
+//@ [future] check-pass
+
+//@ [future_feature] edition: future
+//@ [future_feature] compile-flags: -Z unstable-options
+
+#![cfg_attr(future_feature, feature(explicit_extern_abis))]
+#![cfg_attr(current_feature, feature(explicit_extern_abis))]
+
+extern "C" fn _foo() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern "C" fn _bar() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern "C" {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr
new file mode 100644
index 0000000..cf92780
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr
@@ -0,0 +1,22 @@
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:27:1
+ |
+LL | extern fn _foo() {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+ |
+ = note: `#[warn(missing_abi)]` on by default
+
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:33:8
+ |
+LL | unsafe extern fn _bar() {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/feature-gate-explicit-extern-abis.rs:39:8
+ |
+LL | unsafe extern {}
+ | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr
new file mode 100644
index 0000000..096a6f4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr
@@ -0,0 +1,26 @@
+error: `extern` declarations without an explicit ABI are disallowed
+ --> $DIR/feature-gate-explicit-extern-abis.rs:27:1
+ |
+LL | extern fn _foo() {}
+ | ^^^^^^ help: specify an ABI: `extern "<abi>"`
+ |
+ = help: prior to Rust 2024, a default ABI was inferred
+
+error: `extern` declarations without an explicit ABI are disallowed
+ --> $DIR/feature-gate-explicit-extern-abis.rs:33:8
+ |
+LL | unsafe extern fn _bar() {}
+ | ^^^^^^ help: specify an ABI: `extern "<abi>"`
+ |
+ = help: prior to Rust 2024, a default ABI was inferred
+
+error: `extern` declarations without an explicit ABI are disallowed
+ --> $DIR/feature-gate-explicit-extern-abis.rs:39:8
+ |
+LL | unsafe extern {}
+ | ^^^^^^ help: specify an ABI: `extern "<abi>"`
+ |
+ = help: prior to Rust 2024, a default ABI was inferred
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs
new file mode 100644
index 0000000..379c45f
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs
@@ -0,0 +1,45 @@
+// The purpose of this feature gate is to make something into a hard error in a
+// future edition. Consequently, this test differs from most other feature gate
+// tests. Instead of verifying that an error occurs when the feature gate is
+// missing, it ensures that the hard error is only produced with the feature
+// gate is present in the `future` edition -- and otherwise that only a warning
+// is emitted.
+
+//@ revisions: current current_feature future future_feature
+
+//@ [current] run-rustfix
+//@ [current] check-pass
+
+//@ [current_feature] run-rustfix
+//@ [current_feature] check-pass
+
+//@ [future] edition: future
+//@ [future] compile-flags: -Z unstable-options
+//@ [future] run-rustfix
+//@ [future] check-pass
+
+//@ [future_feature] edition: future
+//@ [future_feature] compile-flags: -Z unstable-options
+
+#![cfg_attr(future_feature, feature(explicit_extern_abis))]
+#![cfg_attr(current_feature, feature(explicit_extern_abis))]
+
+extern fn _foo() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern fn _bar() {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+unsafe extern {}
+//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated
+//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
+//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.rs b/tests/ui/feature-gates/feature-gate-ffi_const.rs
index 9f3d783..35f91b99 100644
--- a/tests/ui/feature-gates/feature-gate-ffi_const.rs
+++ b/tests/ui/feature-gates/feature-gate-ffi_const.rs
@@ -1,6 +1,6 @@
#![crate_type = "lib"]
extern "C" {
- #[ffi_const] //~ ERROR the `#[ffi_const]` attribute is an experimental feature
+ #[unsafe(ffi_const)] //~ ERROR the `#[ffi_const]` attribute is an experimental feature
pub fn foo();
}
diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.stderr b/tests/ui/feature-gates/feature-gate-ffi_const.stderr
index d083b82..7e8c941 100644
--- a/tests/ui/feature-gates/feature-gate-ffi_const.stderr
+++ b/tests/ui/feature-gates/feature-gate-ffi_const.stderr
@@ -1,8 +1,8 @@
error[E0658]: the `#[ffi_const]` attribute is an experimental feature
--> $DIR/feature-gate-ffi_const.rs:4:5
|
-LL | #[ffi_const]
- | ^^^^^^^^^^^^
+LL | #[unsafe(ffi_const)]
+ | ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #58328 <https://github.com/rust-lang/rust/issues/58328> for more information
= help: add `#![feature(ffi_const)]` to the crate attributes to enable
diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.rs b/tests/ui/feature-gates/feature-gate-ffi_pure.rs
index b0dfa01..0f1288b 100644
--- a/tests/ui/feature-gates/feature-gate-ffi_pure.rs
+++ b/tests/ui/feature-gates/feature-gate-ffi_pure.rs
@@ -1,6 +1,6 @@
#![crate_type = "lib"]
extern "C" {
- #[ffi_pure] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature
+ #[unsafe(ffi_pure)] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature
pub fn foo();
}
diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr
index 6544d45..cf92353 100644
--- a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr
+++ b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr
@@ -1,8 +1,8 @@
error[E0658]: the `#[ffi_pure]` attribute is an experimental feature
--> $DIR/feature-gate-ffi_pure.rs:4:5
|
-LL | #[ffi_pure]
- | ^^^^^^^^^^^
+LL | #[unsafe(ffi_pure)]
+ | ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #58329 <https://github.com/rust-lang/rust/issues/58329> for more information
= help: add `#![feature(ffi_pure)]` to the crate attributes to enable
diff --git a/tests/ui/feature-gates/feature-gate-gen_blocks.rs b/tests/ui/feature-gates/feature-gate-gen_blocks.rs
index 01fd922..989daf4 100644
--- a/tests/ui/feature-gates/feature-gate-gen_blocks.rs
+++ b/tests/ui/feature-gates/feature-gate-gen_blocks.rs
@@ -17,7 +17,7 @@ fn test_async_gen() {
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn foo() {
gen {};
//[e2024]~^ ERROR: gen blocks are experimental
diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.rs b/tests/ui/feature-gates/feature-gate-guard-patterns.rs
index 52ed89e..74fb581 100644
--- a/tests/ui/feature-gates/feature-gate-guard-patterns.rs
+++ b/tests/ui/feature-gates/feature-gate-guard-patterns.rs
@@ -30,7 +30,7 @@ fn other_guards_dont() {
while let (x if guard(x)) = 0 {}
//~^ ERROR: guard patterns are experimental
- #[cfg(FALSE)]
+ #[cfg(false)]
while let (x if guard(x)) = 0 {}
//~^ ERROR: guard patterns are experimental
}
diff --git a/tests/ui/feature-gates/feature-gate-mut-ref.rs b/tests/ui/feature-gates/feature-gate-mut-ref.rs
index 806b25d..752ae35 100644
--- a/tests/ui/feature-gates/feature-gate-mut-ref.rs
+++ b/tests/ui/feature-gates/feature-gate-mut-ref.rs
@@ -6,8 +6,8 @@
let mut ref mut z = 14; //~ ERROR [E0658]
z = &mut 15;
- #[cfg(FALSE)]
+ #[cfg(false)]
let mut ref x = 10; //~ ERROR [E0658]
- #[cfg(FALSE)]
+ #[cfg(false)]
let mut ref mut y = 10; //~ ERROR [E0658]
}
diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs
new file mode 100644
index 0000000..c91d833
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs
@@ -0,0 +1,26 @@
+//@ needs-asm-support
+//@ only-x86_64
+
+#![feature(naked_functions, rust_cold_cc)]
+
+use std::arch::naked_asm;
+
+#[naked]
+pub unsafe fn rust_implicit() {
+ //~^ ERROR `#[naked]` is currently unstable on `extern "Rust"` functions
+ naked_asm!("ret");
+}
+
+#[naked]
+pub unsafe extern "Rust" fn rust_explicit() {
+ //~^ ERROR `#[naked]` is currently unstable on `extern "Rust"` functions
+ naked_asm!("ret");
+}
+
+#[naked]
+pub unsafe extern "rust-cold" fn rust_cold() {
+ //~^ ERROR `#[naked]` is currently unstable on `extern "rust-cold"` functions
+ naked_asm!("ret");
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.stderr
new file mode 100644
index 0000000..ba45e15
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.stderr
@@ -0,0 +1,33 @@
+error[E0658]: `#[naked]` is currently unstable on `extern "Rust"` functions
+ --> $DIR/feature-gate-naked_functions_rustic_abi.rs:9:1
+ |
+LL | pub unsafe fn rust_implicit() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #138997 <https://github.com/rust-lang/rust/issues/138997> for more information
+ = help: add `#![feature(naked_functions_rustic_abi)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `#[naked]` is currently unstable on `extern "Rust"` functions
+ --> $DIR/feature-gate-naked_functions_rustic_abi.rs:15:1
+ |
+LL | pub unsafe extern "Rust" fn rust_explicit() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #138997 <https://github.com/rust-lang/rust/issues/138997> for more information
+ = help: add `#![feature(naked_functions_rustic_abi)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `#[naked]` is currently unstable on `extern "rust-cold"` functions
+ --> $DIR/feature-gate-naked_functions_rustic_abi.rs:21:1
+ |
+LL | pub unsafe extern "rust-cold" fn rust_cold() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #138997 <https://github.com/rust-lang/rust/issues/138997> for more information
+ = help: add `#![feature(naked_functions_rustic_abi)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs
index d23405a..2cb0b5a 100644
--- a/tests/ui/feature-gates/feature-gate-never_patterns.rs
+++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs
@@ -15,12 +15,12 @@ fn main() {
//~^ ERROR `!` patterns are experimental
}
// Check that the gate operates even behind `cfg`.
- #[cfg(FALSE)]
+ #[cfg(false)]
match *ptr {
!
//~^ ERROR `!` patterns are experimental
}
- #[cfg(FALSE)]
+ #[cfg(false)]
match *ptr {
! => {}
//~^ ERROR `!` patterns are experimental
@@ -60,13 +60,13 @@ fn main() {
// Check that the gate operates even behind `cfg`.
match Some(0) {
None => {}
- #[cfg(FALSE)]
+ #[cfg(false)]
Some(_)
//~^ ERROR `match` arm with no body
}
match Some(0) {
_ => {}
- #[cfg(FALSE)]
+ #[cfg(false)]
Some(_) if false
//~^ ERROR `match` arm with no body
}
diff --git a/tests/ui/feature-gates/feature-gate-postfix_match.rs b/tests/ui/feature-gates/feature-gate-postfix_match.rs
index dce7e81..2226816 100644
--- a/tests/ui/feature-gates/feature-gate-postfix_match.rs
+++ b/tests/ui/feature-gates/feature-gate-postfix_match.rs
@@ -9,7 +9,7 @@ fn main() {
};
// Test that the gate works behind a cfg
- #[cfg(FALSE)]
+ #[cfg(false)]
val.match { //~ ERROR postfix match is experimental
Some(42) => "the answer to life, the universe, and everything",
_ => "might be the answer to something"
diff --git a/tests/ui/feature-gates/feature-gate-try_blocks.rs b/tests/ui/feature-gates/feature-gate-try_blocks.rs
index f565dd0..9081629 100644
--- a/tests/ui/feature-gates/feature-gate-try_blocks.rs
+++ b/tests/ui/feature-gates/feature-gate-try_blocks.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
pub fn main() {
let try_result: Option<_> = try { //~ ERROR `try` expression is experimental
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
deleted file mode 100644
index deb5a2f..0000000
--- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ edition:2018
-#![forbid(internal_features, unsafe_code)]
-#![feature(unsafe_pin_internals)]
-//~^ ERROR the feature `unsafe_pin_internals` is internal to the compiler or standard library
-
-use core::{marker::PhantomPinned, pin::Pin};
-
-/// The `unsafe_pin_internals` is indeed unsound.
-fn non_unsafe_pin_new_unchecked<T>(pointer: &mut T) -> Pin<&mut T> {
- Pin { __pointer: pointer }
-}
-
-fn main() {
- let mut self_referential = PhantomPinned;
- let _: Pin<&mut PhantomPinned> = non_unsafe_pin_new_unchecked(&mut self_referential);
-}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr
deleted file mode 100644
index fc9bcd9..0000000
--- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: the feature `unsafe_pin_internals` is internal to the compiler or standard library
- --> $DIR/feature-gate-unsafe_pin_internals.rs:3:12
- |
-LL | #![feature(unsafe_pin_internals)]
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: using it is strongly discouraged
-note: the lint level is defined here
- --> $DIR/feature-gate-unsafe_pin_internals.rs:2:11
- |
-LL | #![forbid(internal_features, unsafe_code)]
- | ^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs
index 33fda82..73a17c1 100644
--- a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs
+++ b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs
@@ -1,7 +1,7 @@
-//@ compile-flags: --edition 2021
+//@ edition: 2021
pub fn demo() -> Option<i32> {
- #[cfg(FALSE)]
+ #[cfg(false)]
{
do yeet //~ ERROR `do yeet` expression is experimental
}
@@ -9,7 +9,7 @@ pub fn demo() -> Option<i32> {
Some(1)
}
-#[cfg(FALSE)]
+#[cfg(false)]
pub fn alternative() -> Result<(), String> {
do yeet "hello"; //~ ERROR `do yeet` expression is experimental
}
diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr.rs b/tests/ui/feature-gates/feature-gate-yeet_expr.rs
index 12cc17e..6604f49 100644
--- a/tests/ui/feature-gates/feature-gate-yeet_expr.rs
+++ b/tests/ui/feature-gates/feature-gate-yeet_expr.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
pub fn demo() -> Option<i32> {
do yeet //~ ERROR `do yeet` expression is experimental
diff --git a/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs b/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs
index 2aa2ed3..87629a5 100644
--- a/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs
+++ b/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs
@@ -5,7 +5,7 @@
macro a() {}
//~^ ERROR: `macro` is experimental
-#[cfg(FALSE)]
+#[cfg(false)]
macro b() {}
macro_rules! identity {
@@ -17,13 +17,13 @@ macro_rules! identity {
//~^ ERROR: `macro` is experimental
}
-#[cfg(FALSE)]
+#[cfg(false)]
identity! {
macro d() {} // No error
}
identity! {
- #[cfg(FALSE)]
+ #[cfg(false)]
macro e() {}
}
diff --git a/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs b/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs
index 056c8fb..72d0bf1 100644
--- a/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs
+++ b/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs
@@ -2,7 +2,7 @@
// This file is used to test the behavior of the early-pass syntax warnings.
// If macro syntax is stabilized, replace with a different unstable syntax.
-#[cfg(FALSE)]
+#[cfg(false)]
macro b() {}
//~^ WARN: `macro` is experimental
//~| WARN: unstable syntax
@@ -11,13 +11,13 @@ macro_rules! identity {
($($x:tt)*) => ($($x)*);
}
-#[cfg(FALSE)]
+#[cfg(false)]
identity! {
macro d() {} // No error
}
identity! {
- #[cfg(FALSE)]
+ #[cfg(false)]
macro e() {}
//~^ WARN: `macro` is experimental
//~| WARN: unstable syntax
diff --git a/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs
index a160a9b..4523afa 100644
--- a/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs
+++ b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs
@@ -25,7 +25,7 @@ fn a() {}
// Check that cfg works right
-#[cfg(FALSE)]
+#[cfg(false)]
fn c() {
#[rustc_dummy]
5;
@@ -37,7 +37,7 @@ fn j() {
5;
}
-#[cfg_attr(not(FALSE), cfg(FALSE))]
+#[cfg_attr(not(FALSE), cfg(false))]
fn d() {
#[rustc_dummy]
8;
@@ -57,7 +57,7 @@ fn $e() {
#[rustc_dummy]
42;
- #[cfg(FALSE)]
+ #[cfg(false)]
fn f() {
#[rustc_dummy]
5;
@@ -69,7 +69,7 @@ fn k() {
5;
}
- #[cfg_attr(not(FALSE), cfg(FALSE))]
+ #[cfg_attr(not(FALSE), cfg(false))]
fn g() {
#[rustc_dummy]
8;
@@ -90,42 +90,42 @@ fn h() {
// check that the gate visitor works right:
extern "C" {
- #[cfg(FALSE)]
+ #[cfg(false)]
fn x(a: [u8; #[rustc_dummy] 5]);
fn y(a: [u8; #[rustc_dummy] 5]); //~ ERROR attributes on expressions are experimental
}
struct Foo;
impl Foo {
- #[cfg(FALSE)]
+ #[cfg(false)]
const X: u8 = #[rustc_dummy] 5;
const Y: u8 = #[rustc_dummy] 5; //~ ERROR attributes on expressions are experimental
}
trait Bar {
- #[cfg(FALSE)]
+ #[cfg(false)]
const X: [u8; #[rustc_dummy] 5];
const Y: [u8; #[rustc_dummy] 5]; //~ ERROR attributes on expressions are experimental
}
struct Joyce {
- #[cfg(FALSE)]
+ #[cfg(false)]
field: [u8; #[rustc_dummy] 5],
field2: [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental
}
struct Walky(
- #[cfg(FALSE)] [u8; #[rustc_dummy] 5],
+ #[cfg(false)] [u8; #[rustc_dummy] 5],
[u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental
);
enum Mike {
Happy(
- #[cfg(FALSE)] [u8; #[rustc_dummy] 5],
+ #[cfg(false)] [u8; #[rustc_dummy] 5],
[u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental
),
Angry {
- #[cfg(FALSE)]
+ #[cfg(false)]
field: [u8; #[rustc_dummy] 5],
field2: [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental
}
@@ -133,7 +133,7 @@ enum Mike {
fn pat() {
match 5 {
- #[cfg(FALSE)]
+ #[cfg(false)]
5 => #[rustc_dummy] (),
6 => #[rustc_dummy] (), //~ ERROR attributes on expressions are experimental
_ => (),
diff --git a/tests/ui/ffi-attrs/ffi_const.rs b/tests/ui/ffi-attrs/ffi_const.rs
index aa20a4d..dddc862 100644
--- a/tests/ui/ffi-attrs/ffi_const.rs
+++ b/tests/ui/ffi-attrs/ffi_const.rs
@@ -1,15 +1,18 @@
#![feature(ffi_const)]
#![crate_type = "lib"]
-#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
pub fn foo() {}
-#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
macro_rules! bar {
- () => ()
+ () => {};
}
extern "C" {
- #[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+ #[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
static INT: i32;
+
+ #[ffi_const] //~ ERROR unsafe attribute used without unsafe
+ fn bar();
}
diff --git a/tests/ui/ffi-attrs/ffi_const.stderr b/tests/ui/ffi-attrs/ffi_const.stderr
index 394b98f..7f31237 100644
--- a/tests/ui/ffi-attrs/ffi_const.stderr
+++ b/tests/ui/ffi-attrs/ffi_const.stderr
@@ -1,21 +1,32 @@
+error: unsafe attribute used without unsafe
+ --> $DIR/ffi_const.rs:16:7
+ |
+LL | #[ffi_const]
+ | ^^^^^^^^^ usage of unsafe attribute
+ |
+help: wrap the attribute in `unsafe(...)`
+ |
+LL | #[unsafe(ffi_const)]
+ | +++++++ +
+
error[E0756]: `#[ffi_const]` may only be used on foreign functions
--> $DIR/ffi_const.rs:4:1
|
-LL | #[ffi_const]
- | ^^^^^^^^^^^^
+LL | #[unsafe(ffi_const)]
+ | ^^^^^^^^^^^^^^^^^^^^
error[E0756]: `#[ffi_const]` may only be used on foreign functions
--> $DIR/ffi_const.rs:7:1
|
-LL | #[ffi_const]
- | ^^^^^^^^^^^^
+LL | #[unsafe(ffi_const)]
+ | ^^^^^^^^^^^^^^^^^^^^
error[E0756]: `#[ffi_const]` may only be used on foreign functions
--> $DIR/ffi_const.rs:13:5
|
-LL | #[ffi_const]
- | ^^^^^^^^^^^^
+LL | #[unsafe(ffi_const)]
+ | ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0756`.
diff --git a/tests/ui/ffi-attrs/ffi_const2.rs b/tests/ui/ffi-attrs/ffi_const2.rs
index 82fe8a9..8a8de13 100644
--- a/tests/ui/ffi-attrs/ffi_const2.rs
+++ b/tests/ui/ffi-attrs/ffi_const2.rs
@@ -1,8 +1,8 @@
#![feature(ffi_const, ffi_pure)]
extern "C" {
- #[ffi_pure] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]`
- #[ffi_const]
+ #[unsafe(ffi_pure)] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]`
+ #[unsafe(ffi_const)]
pub fn baz();
}
diff --git a/tests/ui/ffi-attrs/ffi_const2.stderr b/tests/ui/ffi-attrs/ffi_const2.stderr
index b8cbc29..d4c9bc4 100644
--- a/tests/ui/ffi-attrs/ffi_const2.stderr
+++ b/tests/ui/ffi-attrs/ffi_const2.stderr
@@ -1,8 +1,8 @@
error[E0757]: `#[ffi_const]` function cannot be `#[ffi_pure]`
--> $DIR/ffi_const2.rs:4:5
|
-LL | #[ffi_pure]
- | ^^^^^^^^^^^
+LL | #[unsafe(ffi_pure)]
+ | ^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/ffi-attrs/ffi_pure.rs b/tests/ui/ffi-attrs/ffi_pure.rs
index 6d2f3a6..1f4812f 100644
--- a/tests/ui/ffi-attrs/ffi_pure.rs
+++ b/tests/ui/ffi-attrs/ffi_pure.rs
@@ -1,15 +1,18 @@
#![feature(ffi_pure)]
#![crate_type = "lib"]
-#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
pub fn foo() {}
-#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
macro_rules! bar {
- () => ()
+ () => {};
}
extern "C" {
- #[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+ #[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
static INT: i32;
+
+ #[ffi_pure] //~ ERROR unsafe attribute used without unsafe
+ fn bar();
}
diff --git a/tests/ui/ffi-attrs/ffi_pure.stderr b/tests/ui/ffi-attrs/ffi_pure.stderr
index 8b61a4b..bd1177c 100644
--- a/tests/ui/ffi-attrs/ffi_pure.stderr
+++ b/tests/ui/ffi-attrs/ffi_pure.stderr
@@ -1,21 +1,32 @@
+error: unsafe attribute used without unsafe
+ --> $DIR/ffi_pure.rs:16:7
+ |
+LL | #[ffi_pure]
+ | ^^^^^^^^ usage of unsafe attribute
+ |
+help: wrap the attribute in `unsafe(...)`
+ |
+LL | #[unsafe(ffi_pure)]
+ | +++++++ +
+
error[E0755]: `#[ffi_pure]` may only be used on foreign functions
--> $DIR/ffi_pure.rs:4:1
|
-LL | #[ffi_pure]
- | ^^^^^^^^^^^
+LL | #[unsafe(ffi_pure)]
+ | ^^^^^^^^^^^^^^^^^^^
error[E0755]: `#[ffi_pure]` may only be used on foreign functions
--> $DIR/ffi_pure.rs:7:1
|
-LL | #[ffi_pure]
- | ^^^^^^^^^^^
+LL | #[unsafe(ffi_pure)]
+ | ^^^^^^^^^^^^^^^^^^^
error[E0755]: `#[ffi_pure]` may only be used on foreign functions
--> $DIR/ffi_pure.rs:13:5
|
-LL | #[ffi_pure]
- | ^^^^^^^^^^^
+LL | #[unsafe(ffi_pure)]
+ | ^^^^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0755`.
diff --git a/tests/ui/filter-block-view-items.rs b/tests/ui/filter-block-view-items.rs
index 975ab19..cb599c2 100644
--- a/tests/ui/filter-block-view-items.rs
+++ b/tests/ui/filter-block-view-items.rs
@@ -3,5 +3,5 @@
pub fn main() {
// Make sure that this view item is filtered out because otherwise it would
// trigger a compilation error
- #[cfg(FALSE)] use bar as foo;
+ #[cfg(false)] use bar as foo;
}
diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs
index 30e25ca8..67be8de 100644
--- a/tests/ui/fn/suggest-return-closure.rs
+++ b/tests/ui/fn/suggest-return-closure.rs
@@ -19,6 +19,7 @@ fn fn_mut() -> _ {
let x = String::new();
//~^ HELP: consider changing this to be mutable
//~| NOTE binding `x` declared here
+ //~| SUGGESTION mut
|c| { //~ NOTE: value captured here
x.push(c);
//~^ ERROR: does not live long enough
diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr
index 45c12b5..1860d1c 100644
--- a/tests/ui/fn/suggest-return-closure.stderr
+++ b/tests/ui/fn/suggest-return-closure.stderr
@@ -21,7 +21,7 @@
= note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
- --> $DIR/suggest-return-closure.rs:32:13
+ --> $DIR/suggest-return-closure.rs:33:13
|
LL | fn fun() -> _ {
| ^
@@ -32,7 +32,7 @@
= note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
- --> $DIR/suggest-return-closure.rs:23:9
+ --> $DIR/suggest-return-closure.rs:24:9
|
LL | x.push(c);
| ^ cannot borrow as mutable
@@ -43,7 +43,7 @@
| +++
error[E0597]: `x` does not live long enough
- --> $DIR/suggest-return-closure.rs:23:9
+ --> $DIR/suggest-return-closure.rs:24:9
|
LL | let x = String::new();
| - binding `x` declared here
diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
index 85661c1..294fb67 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
+++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
@@ -3,7 +3,7 @@
}
fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
- //~^ ERROR: lifetime in trait object type must be followed by `+`
+ //~^ ERROR: lifetimes must be followed by `+` to form a trait object type
//~| ERROR: parenthesized generic arguments cannot be used
//~| ERROR associated type takes 0 generic arguments but 1 generic argument
//~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments
diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
index 99300ea..e18d819 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
@@ -1,8 +1,13 @@
-error: lifetime in trait object type must be followed by `+`
+error: lifetimes must be followed by `+` to form a trait object type
--> $DIR/gat-trait-path-parenthesised-args.rs:5:29
|
LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
| ^^
+ |
+help: consider adding a trait bound after the potential lifetime bound
+ |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a + /* Trait */) = &'a ()>>) {}
+ | +++++++++++++
error: parenthesized generic arguments cannot be used in associated type constraints
--> $DIR/gat-trait-path-parenthesised-args.rs:5:27
diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr
index 231c0dd..7847bbd 100644
--- a/tests/ui/generic-associated-types/impl_bounds.stderr
+++ b/tests/ui/generic-associated-types/impl_bounds.stderr
@@ -57,14 +57,14 @@
|
LL | #[derive(Copy, Clone)]
| ^^^^ unsatisfied trait bound introduced in this `derive` macro
-note: the requirement `Fooy<T>: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method
+note: the requirement `Fooy<T>: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function
--> $DIR/impl_bounds.rs:7:8
|
LL | trait Foo {
| --- in this trait
...
LL | fn d() where Self: Clone;
- | ^ this trait's method doesn't have the requirement `Fooy<T>: Copy`
+ | ^ this trait's associated function doesn't have the requirement `Fooy<T>: Copy`
help: consider restricting type parameter `T` with trait `Copy`
|
LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
diff --git a/tests/ui/generics/single-colon-path-not-const-generics.stderr b/tests/ui/generics/single-colon-path-not-const-generics.stderr
index c14a5e6..9eb62de 100644
--- a/tests/ui/generics/single-colon-path-not-const-generics.stderr
+++ b/tests/ui/generics/single-colon-path-not-const-generics.stderr
@@ -4,7 +4,6 @@
LL | a: Vec<foo::bar:A>,
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | a: Vec<foo::bar::A>,
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
index 33506a5..01f4340 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
@@ -9,7 +9,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
match scrutinee {
...X => {} //~ ERROR range-to patterns with `...` are not allowed
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
index 2f1ec65..24eb993 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
@@ -3,7 +3,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn foo() {
if let 0... = 1 {} //~ ERROR inclusive range with no end
if let 0..= = 1 {} //~ ERROR inclusive range with no end
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
index 2d63fe0..6b33ead 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
@@ -1,6 +1,6 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
match &0 {
&0.. | _ => {}
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
index 4e3fffb..02699e7 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
@@ -4,7 +4,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
match scrutinee {
X.. | 0.. | 'a'.. | 0.0f32.. => {}
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs
index 53b28c2..f334697 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs
@@ -1,5 +1,6 @@
//@ check-pass
-//@ compile-flags: --edition=2021 --crate-type=lib
+//@ compile-flags: --crate-type=lib
+//@ edition: 2021
use std::{
future::Future,
diff --git a/tests/ui/hygiene/rustc-macro-transparency.rs b/tests/ui/hygiene/rustc-macro-transparency.rs
index 5f36993..1a78a75 100644
--- a/tests/ui/hygiene/rustc-macro-transparency.rs
+++ b/tests/ui/hygiene/rustc-macro-transparency.rs
@@ -6,9 +6,9 @@
let transparent = 0;
}
#[rustc_macro_transparency = "semitransparent"]
-macro semitransparent() {
- struct SemiTransparent;
- let semitransparent = 0;
+macro semiopaque() {
+ struct SemiOpaque;
+ let semiopaque = 0;
}
#[rustc_macro_transparency = "opaque"]
macro opaque() {
@@ -18,14 +18,14 @@
fn main() {
transparent!();
- semitransparent!();
+ semiopaque!();
opaque!();
Transparent; // OK
- SemiTransparent; // OK
+ SemiOpaque; // OK
Opaque; //~ ERROR cannot find value `Opaque` in this scope
transparent; // OK
- semitransparent; //~ ERROR expected value, found macro `semitransparent`
+ semiopaque; //~ ERROR expected value, found macro `semiopaque`
opaque; //~ ERROR expected value, found macro `opaque`
}
diff --git a/tests/ui/hygiene/rustc-macro-transparency.stderr b/tests/ui/hygiene/rustc-macro-transparency.stderr
index 1d2a1e1..1bea8a0 100644
--- a/tests/ui/hygiene/rustc-macro-transparency.stderr
+++ b/tests/ui/hygiene/rustc-macro-transparency.stderr
@@ -4,17 +4,17 @@
LL | Opaque;
| ^^^^^^ not found in this scope
-error[E0423]: expected value, found macro `semitransparent`
+error[E0423]: expected value, found macro `semiopaque`
--> $DIR/rustc-macro-transparency.rs:29:5
|
-LL | struct SemiTransparent;
- | ----------------------- similarly named unit struct `SemiTransparent` defined here
+LL | struct SemiOpaque;
+ | ------------------ similarly named unit struct `SemiOpaque` defined here
...
-LL | semitransparent;
- | ^^^^^^^^^^^^^^^
+LL | semiopaque;
+ | ^^^^^^^^^^
| |
| not a value
- | help: a unit struct with a similar name exists: `SemiTransparent`
+ | help: a unit struct with a similar name exists (notice the capitalization): `SemiOpaque`
error[E0423]: expected value, found macro `opaque`
--> $DIR/rustc-macro-transparency.rs:30:5
diff --git a/tests/ui/hygiene/unpretty-debug.stdout b/tests/ui/hygiene/unpretty-debug.stdout
index e475cfa..f35bd7a 100644
--- a/tests/ui/hygiene/unpretty-debug.stdout
+++ b/tests/ui/hygiene/unpretty-debug.stdout
@@ -24,5 +24,5 @@
SyntaxContexts:
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
-#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiTransparent)
+#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiOpaque)
*/
diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.rs
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-coherence.rs
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.rs
diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.stderr
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-coherence.stderr
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.stderr
diff --git a/tests/ui/impl-trait/auto-trait-contains-err.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.rs
similarity index 92%
rename from tests/ui/impl-trait/auto-trait-contains-err.rs
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.rs
index d7f0942..8a2ebe3 100644
--- a/tests/ui/impl-trait/auto-trait-contains-err.rs
+++ b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2021
+//@ edition: 2021
use std::future::Future;
diff --git a/tests/ui/impl-trait/auto-trait-contains-err.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.stderr
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-contains-err.stderr
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.stderr
diff --git a/tests/ui/impl-trait/auto-trait-leak-rpass.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak-rpass.rs
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-leak-rpass.rs
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak-rpass.rs
diff --git a/tests/ui/impl-trait/auto-trait-leak.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-leak.rs
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs
diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-leak.stderr
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr
diff --git a/tests/ui/impl-trait/auto-trait-leak2.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-leak2.rs
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
diff --git a/tests/ui/impl-trait/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
similarity index 100%
rename from tests/ui/impl-trait/auto-trait-leak2.stderr
rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
diff --git a/tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs b/tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs
new file mode 100644
index 0000000..7f366fd
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs
@@ -0,0 +1,33 @@
+//@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+
+// When proving auto trait bounds, make sure that we depend on auto trait
+// leakage if we can also prove it via an item bound.
+fn is_send<T: Send>(_: T) {}
+
+fn direct() -> impl Send {
+ is_send(check(false)); // leaks auto traits, depends on `check`
+ 1u16
+}
+
+trait Indir: Send {}
+impl Indir for u32 {}
+fn indir() -> impl Indir {
+ is_send(check(false)); // leaks auto traits, depends on `check`
+ 1u32
+}
+
+fn check(b: bool) -> impl Sized {
+ if b {
+ // must not leak auto traits, as we otherwise get a query cycle.
+ is_send(direct());
+ is_send(indir());
+ }
+ 1u64
+}
+
+fn main() {
+ check(true);
+}
diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.rs b/tests/ui/impl-trait/impl-trait-plus-priority.rs
index 5575493..8f76d41 100644
--- a/tests/ui/impl-trait/impl-trait-plus-priority.rs
+++ b/tests/ui/impl-trait/impl-trait-plus-priority.rs
@@ -27,7 +27,7 @@ fn f(self) -> A + B { // OK
type A = fn() -> dyn A + B;
//~^ ERROR ambiguous `+` in a type
type A = fn() -> A + B;
-//~^ ERROR expected a path on the left-hand side of `+`, not `fn() -> A`
+//~^ ERROR expected a path on the left-hand side of `+`
type A = Fn() -> impl A +;
//~^ ERROR ambiguous `+` in a type
@@ -44,6 +44,6 @@ fn f(self) -> A + B { // OK
type A = &dyn A + B;
//~^ ERROR ambiguous `+` in a type
type A = &A + B;
-//~^ ERROR expected a path on the left-hand side of `+`, not `&A`
+//~^ ERROR expected a path on the left-hand side of `+`
fn main() {}
diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.stderr b/tests/ui/impl-trait/impl-trait-plus-priority.stderr
index 03e7910..1612065 100644
--- a/tests/ui/impl-trait/impl-trait-plus-priority.stderr
+++ b/tests/ui/impl-trait/impl-trait-plus-priority.stderr
@@ -31,11 +31,13 @@
LL | type A = fn() -> (dyn A + B);
| + +
-error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> A`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/impl-trait-plus-priority.rs:29:10
|
LL | type A = fn() -> A + B;
- | ^^^^^^^^^^^^^ perhaps you forgot parentheses?
+ | ^^^^^^^^^----
+ | |
+ | perhaps you forgot parentheses?
error: ambiguous `+` in a type
--> $DIR/impl-trait-plus-priority.rs:32:18
@@ -103,11 +105,11 @@
LL | type A = &(dyn A + B);
| + +
-error[E0178]: expected a path on the left-hand side of `+`, not `&A`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/impl-trait-plus-priority.rs:46:10
|
LL | type A = &A + B;
- | ^^^^^^
+ | ^^
|
help: try adding parentheses
|
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
index fc3efb4..a9dfac2 100644
--- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
@@ -6,11 +6,11 @@
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-note: required by a bound in `Foo::{synthetic#0}`
+note: required by a bound in `Foo::{anon_assoc#0}`
--> $DIR/doesnt-satisfy.rs:2:22
|
LL | fn bar() -> impl std::fmt::Display;
- | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{synthetic#0}`
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
error: aborting due to 1 previous error
diff --git a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.rs b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.rs
new file mode 100644
index 0000000..450f41e
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.rs
@@ -0,0 +1,12 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/139873>.
+
+// Test that we don't try to get the (nonexistent) name of the RPITIT in `Trait::foo`
+// when emitting an error for a missing associated item `Trait::Output`.
+
+trait Trait {
+ fn foo() -> impl Sized;
+ fn bar() -> Self::Output;
+ //~^ ERROR associated type `Output` not found for `Self`
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.stderr b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.stderr
new file mode 100644
index 0000000..74e1578
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.stderr
@@ -0,0 +1,9 @@
+error[E0220]: associated type `Output` not found for `Self`
+ --> $DIR/dont-probe-missing-item-name.rs:8:23
+ |
+LL | fn bar() -> Self::Output;
+ | ^^^^^^ associated type `Output` not found
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/impl-trait/in-trait/dump.rs b/tests/ui/impl-trait/in-trait/dump.rs
index 20b0e60..da3cfd0 100644
--- a/tests/ui/impl-trait/in-trait/dump.rs
+++ b/tests/ui/impl-trait/in-trait/dump.rs
@@ -8,7 +8,7 @@ trait Foo {
}
fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {
-//~^ ERROR <T as Foo>::{synthetic#0}<'s/#1>
+//~^ ERROR <T as Foo>::{anon_assoc#0}<'s/#1>
x.hello()
}
diff --git a/tests/ui/impl-trait/in-trait/dump.stderr b/tests/ui/impl-trait/in-trait/dump.stderr
index 9580584..15b6f18 100644
--- a/tests/ui/impl-trait/in-trait/dump.stderr
+++ b/tests/ui/impl-trait/in-trait/dump.stderr
@@ -1,4 +1,4 @@
-error: <T as Foo>::{synthetic#0}<'s/#1>
+error: <T as Foo>::{anon_assoc#0}<'s/#1>
--> $DIR/dump.rs:10:35
|
LL | fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {
diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr
new file mode 100644
index 0000000..bf598d6
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr
@@ -0,0 +1,58 @@
+error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+ |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+ = note: ...which requires evaluating trait selection obligation `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}: core::marker::Send`...
+note: ...which requires computing type of opaque `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+note: ...which requires borrow-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires checking if `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo` contains FFI-unwind calls...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
+note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
+ --> $DIR/method-compatability-via-leakage-cycle.rs:17:1
+ |
+LL | impl Trait for u32 {
+ | ^^^^^^^^^^^^^^^^^^
+ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr
new file mode 100644
index 0000000..6bec5bb
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr
@@ -0,0 +1,122 @@
+error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+ |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+note: ...which requires computing type of opaque `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+note: ...which requires borrow-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires checking if `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo` contains FFI-unwind calls...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
+note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
+ --> $DIR/method-compatability-via-leakage-cycle.rs:17:1
+ |
+LL | impl Trait for u32 {
+ | ^^^^^^^^^^^^^^^^^^
+ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+ |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+note: ...which requires computing type of opaque `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{opaque#0}`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^
+note: ...which requires borrow-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires checking if `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo` contains FFI-unwind calls...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires building MIR for `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires type-checking `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo`...
+ --> $DIR/method-compatability-via-leakage-cycle.rs:21:5
+ |
+LL | fn foo(b: bool) -> impl Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
+note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
+ --> $DIR/method-compatability-via-leakage-cycle.rs:17:1
+ |
+LL | impl Trait for u32 {
+ | ^^^^^^^^^^^^^^^^^^
+ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.rs b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.rs
new file mode 100644
index 0000000..917820d
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.rs
@@ -0,0 +1,30 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ known-bug: #139788
+
+// Recursively using the trait method inside of an impl in case checking
+// method compatability relies on opaque type leakage currently causes a
+// cycle error.
+
+trait Trait {
+ // desugars to
+ // type Assoc: Sized + Send;
+ // fn foo(b: bool) -> Self::Assoc;
+ fn foo(b: bool) -> impl Sized + Send;
+}
+
+impl Trait for u32 {
+ // desugars to
+ // type Assoc = impl_rpit::<Self>;
+ // fn foo(b: bool) -> Self::Assoc { .. }
+ fn foo(b: bool) -> impl Sized {
+ if b {
+ u32::foo(false)
+ } else {
+ 1u32
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage.rs b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage.rs
new file mode 100644
index 0000000..249ec07
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+
+trait Trait {
+ fn foo() -> impl Sized + Send;
+}
+
+impl Trait for u32 {
+ fn foo() -> impl Sized {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/refine-cycle.rs b/tests/ui/impl-trait/in-trait/refine-cycle.rs
index 78d672a..d97f982 100644
--- a/tests/ui/impl-trait/in-trait/refine-cycle.rs
+++ b/tests/ui/impl-trait/in-trait/refine-cycle.rs
@@ -1,4 +1,7 @@
//@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
// Make sure that refinement checking doesn't cause a cycle in `Instance::resolve`
// which calls `compare_impl_item`.
diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
index 5cb8038..6571ce2 100644
--- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
@@ -14,11 +14,11 @@
| ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>`
|
= help: the trait `Foo<char>` is implemented for `Bar`
-note: required by a bound in `Foo::{synthetic#0}`
+note: required by a bound in `Foo::{anon_assoc#0}`
--> $DIR/return-dont-satisfy-bounds.rs:2:30
|
LL | fn foo<F2>(self) -> impl Foo<T>;
- | ^^^^^^ required by this bound in `Foo::{synthetic#0}`
+ | ^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
--> $DIR/return-dont-satisfy-bounds.rs:8:34
diff --git a/tests/ui/imports/redundant-import-extern-prelude.rs b/tests/ui/imports/redundant-import-extern-prelude.rs
index 0064eaa..b573b8f 100644
--- a/tests/ui/imports/redundant-import-extern-prelude.rs
+++ b/tests/ui/imports/redundant-import-extern-prelude.rs
@@ -5,7 +5,8 @@
// See also the discussion in <https://github.com/rust-lang/rust/pull/122954>.
-//@ compile-flags: --extern aux_issue_121915 --edition 2018
+//@ compile-flags: --extern aux_issue_121915
+//@ edition: 2018
//@ aux-build: aux-issue-121915.rs
#[deny(redundant_imports)]
diff --git a/tests/ui/imports/redundant-import-extern-prelude.stderr b/tests/ui/imports/redundant-import-extern-prelude.stderr
index 6d2518c..06cce7e 100644
--- a/tests/ui/imports/redundant-import-extern-prelude.stderr
+++ b/tests/ui/imports/redundant-import-extern-prelude.stderr
@@ -1,11 +1,11 @@
error: the item `aux_issue_121915` is imported redundantly
- --> $DIR/redundant-import-extern-prelude.rs:14:9
+ --> $DIR/redundant-import-extern-prelude.rs:15:9
|
LL | use aux_issue_121915;
| ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by the extern prelude
|
note: the lint level is defined here
- --> $DIR/redundant-import-extern-prelude.rs:11:8
+ --> $DIR/redundant-import-extern-prelude.rs:12:8
|
LL | #[deny(redundant_imports)]
| ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs
index dc499bc..7108776 100644
--- a/tests/ui/imports/redundant-import-issue-121915-2015.rs
+++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs
@@ -1,4 +1,5 @@
-//@ compile-flags: --extern aux_issue_121915 --edition 2015
+//@ compile-flags: --extern aux_issue_121915
+//@ edition: 2015
//@ aux-build: aux-issue-121915.rs
extern crate aux_issue_121915;
diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr
index f4e9f60..367a4f1 100644
--- a/tests/ui/imports/redundant-import-issue-121915-2015.stderr
+++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr
@@ -1,5 +1,5 @@
error: the item `aux_issue_121915` is imported redundantly
- --> $DIR/redundant-import-issue-121915-2015.rs:8:9
+ --> $DIR/redundant-import-issue-121915-2015.rs:9:9
|
LL | extern crate aux_issue_121915;
| ------------------------------ the item `aux_issue_121915` is already imported here
@@ -8,7 +8,7 @@
| ^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/redundant-import-issue-121915-2015.rs:6:8
+ --> $DIR/redundant-import-issue-121915-2015.rs:7:8
|
LL | #[deny(redundant_imports)]
| ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs
index ee3ceb6..3c036b8 100644
--- a/tests/ui/imports/suggest-remove-issue-121315.rs
+++ b/tests/ui/imports/suggest-remove-issue-121315.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2021
+//@ edition: 2021
#![deny(unused_imports, redundant_imports)]
#![allow(dead_code)]
diff --git a/tests/ui/inner-attrs-on-impl.rs b/tests/ui/inner-attrs-on-impl.rs
index 75f4062..1dce1cd 100644
--- a/tests/ui/inner-attrs-on-impl.rs
+++ b/tests/ui/inner-attrs-on-impl.rs
@@ -3,7 +3,7 @@
struct Foo;
impl Foo {
- #![cfg(FALSE)]
+ #![cfg(false)]
fn method(&self) -> bool { false }
}
@@ -12,7 +12,7 @@ impl Foo {
#![cfg(not(FALSE))]
// check that we don't eat attributes too eagerly.
- #[cfg(FALSE)]
+ #[cfg(false)]
fn method(&self) -> bool { false }
fn method(&self) -> bool { true }
diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs
index 6bc3f8d..9127cc6 100644
--- a/tests/ui/intrinsics/intrinsic-atomics.rs
+++ b/tests/ui/intrinsics/intrinsic-atomics.rs
@@ -1,53 +1,6 @@
//@ run-pass
-#![feature(intrinsics)]
-
-mod rusti {
-
- #[rustc_intrinsic]
- pub unsafe fn atomic_cxchg_seqcst_seqcst<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- #[rustc_intrinsic]
- pub unsafe fn atomic_cxchg_acquire_acquire<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- #[rustc_intrinsic]
- pub unsafe fn atomic_cxchg_release_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-
- #[rustc_intrinsic]
- pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- #[rustc_intrinsic]
- pub unsafe fn atomic_cxchgweak_acquire_acquire<T>(dst: *mut T, old: T, src: T) -> (T, bool);
- #[rustc_intrinsic]
- pub unsafe fn atomic_cxchgweak_release_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-
- #[rustc_intrinsic]
- pub unsafe fn atomic_load_seqcst<T>(src: *const T) -> T;
- #[rustc_intrinsic]
- pub unsafe fn atomic_load_acquire<T>(src: *const T) -> T;
-
- #[rustc_intrinsic]
- pub unsafe fn atomic_store_seqcst<T>(dst: *mut T, val: T);
- #[rustc_intrinsic]
- pub unsafe fn atomic_store_release<T>(dst: *mut T, val: T);
-
- #[rustc_intrinsic]
- pub unsafe fn atomic_xchg_seqcst<T>(dst: *mut T, src: T) -> T;
- #[rustc_intrinsic]
- pub unsafe fn atomic_xchg_acquire<T>(dst: *mut T, src: T) -> T;
- #[rustc_intrinsic]
- pub unsafe fn atomic_xchg_release<T>(dst: *mut T, src: T) -> T;
-
- #[rustc_intrinsic]
- pub unsafe fn atomic_xadd_seqcst<T>(dst: *mut T, src: T) -> T;
- #[rustc_intrinsic]
- pub unsafe fn atomic_xadd_acquire<T>(dst: *mut T, src: T) -> T;
- #[rustc_intrinsic]
- pub unsafe fn atomic_xadd_release<T>(dst: *mut T, src: T) -> T;
-
- #[rustc_intrinsic]
- pub unsafe fn atomic_xsub_seqcst<T>(dst: *mut T, src: T) -> T;
- #[rustc_intrinsic]
- pub unsafe fn atomic_xsub_acquire<T>(dst: *mut T, src: T) -> T;
- #[rustc_intrinsic]
- pub unsafe fn atomic_xsub_release<T>(dst: *mut T, src: T) -> T;
-}
+#![feature(core_intrinsics)]
+use std::intrinsics as rusti;
pub fn main() {
unsafe {
diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr
index 8abaee5..fd2a36e 100644
--- a/tests/ui/invalid-compile-flags/print-without-arg.stderr
+++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr
@@ -1,5 +1,6 @@
error: Argument to option 'print' missing
Usage:
- --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models]
- Compiler information to print on stdout
+ --print INFO[=FILE] Compiler information to print on stdout (or to a file)
+ INFO may be one of
+ (all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models).
diff --git a/tests/ui/issues/issue-11004.rs b/tests/ui/issues/issue-11004.rs
index 714fa51..0c34554 100644
--- a/tests/ui/issues/issue-11004.rs
+++ b/tests/ui/issues/issue-11004.rs
@@ -9,7 +9,7 @@ unsafe fn access(n:*mut A) -> (i32, f64) {
(x, y)
}
-#[cfg(FALSE)]
+#[cfg(false)]
unsafe fn access(n:*mut A) -> (i32, f64) {
let x : i32 = (*n).x;
let y : f64 = (*n).y;
diff --git a/tests/ui/issues/issue-11085.rs b/tests/ui/issues/issue-11085.rs
index d0703b0..c3f1319 100644
--- a/tests/ui/issues/issue-11085.rs
+++ b/tests/ui/issues/issue-11085.rs
@@ -3,7 +3,7 @@
#![allow(dead_code)]
struct Foo {
- #[cfg(FALSE)]
+ #[cfg(false)]
bar: baz,
foo: isize,
}
@@ -15,18 +15,18 @@ struct Foo2 {
enum Bar1 {
Bar1_1,
- #[cfg(FALSE)]
+ #[cfg(false)]
Bar1_2(NotAType),
}
enum Bar2 {
- #[cfg(FALSE)]
+ #[cfg(false)]
Bar2_1(NotAType),
}
enum Bar3 {
Bar3_1 {
- #[cfg(FALSE)]
+ #[cfg(false)]
foo: isize,
bar: isize,
}
diff --git a/tests/ui/issues/issue-16819.rs b/tests/ui/issues/issue-16819.rs
index e2b1090..2805c82 100644
--- a/tests/ui/issues/issue-16819.rs
+++ b/tests/ui/issues/issue-16819.rs
@@ -3,7 +3,7 @@
// `#[cfg]` on struct field permits empty unusable struct
struct S {
- #[cfg(FALSE)]
+ #[cfg(false)]
a: int,
}
diff --git a/tests/ui/issues/issue-37131.rs b/tests/ui/issues/issue-37131.rs
index 16681ac..e91c76e 100644
--- a/tests/ui/issues/issue-37131.rs
+++ b/tests/ui/issues/issue-37131.rs
@@ -1,4 +1,6 @@
//~ ERROR can't find crate for `std`
+//~| NOTE target may not be installed
+//~| NOTE can't find crate
// Tests that compiling for a target which is not installed will result in a helpful
// error message.
@@ -6,5 +8,4 @@
//@ ignore-arm
//@ needs-llvm-components: arm
-//@ error-pattern:target may not be installed
fn main() { }
diff --git a/tests/ui/label/label_break_value_desugared_break.rs b/tests/ui/label/label_break_value_desugared_break.rs
index b7e7fd4..17ef1ba 100644
--- a/tests/ui/label/label_break_value_desugared_break.rs
+++ b/tests/ui/label/label_break_value_desugared_break.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
//@ run-pass
diff --git a/tests/ui/layout/unknown-when-no-type-parameter.rs b/tests/ui/layout/unknown-when-no-type-parameter.rs
index 500b793..87f90aa 100644
--- a/tests/ui/layout/unknown-when-no-type-parameter.rs
+++ b/tests/ui/layout/unknown-when-no-type-parameter.rs
@@ -1,13 +1,13 @@
#![feature(trivial_bounds)]
-//@ error-pattern: the type `<() as Project>::Assoc` has an unknown layout
-
trait Project {
type Assoc;
}
fn foo() where (): Project {
[(); size_of::<<() as Project>::Assoc>()]; //~ ERROR evaluation of constant value failed
+ //~| NOTE the type `<() as Project>::Assoc` has an unknown layout
+ //~| NOTE inside `std::mem::size_of::<<() as Project>::Assoc>`
}
fn main() {}
diff --git a/tests/ui/layout/unknown-when-no-type-parameter.stderr b/tests/ui/layout/unknown-when-no-type-parameter.stderr
index a2dbb19..35fbb11 100644
--- a/tests/ui/layout/unknown-when-no-type-parameter.stderr
+++ b/tests/ui/layout/unknown-when-no-type-parameter.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/unknown-when-no-type-parameter.rs:10:10
+ --> $DIR/unknown-when-no-type-parameter.rs:8:10
|
LL | [(); size_of::<<() as Project>::Assoc>()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `<() as Project>::Assoc` has an unknown layout
diff --git a/tests/ui/let-else/issue-102317.rs b/tests/ui/let-else/issue-102317.rs
index d94410e..5afcacf 100644
--- a/tests/ui/let-else/issue-102317.rs
+++ b/tests/ui/let-else/issue-102317.rs
@@ -1,6 +1,7 @@
// issue #102317
//@ build-pass
-//@ compile-flags: --edition 2021 -C opt-level=3 -Zvalidate-mir
+//@ compile-flags: -C opt-level=3 -Zvalidate-mir
+//@ edition: 2021
struct SegmentJob;
diff --git a/tests/ui/lexer/error-stage.rs b/tests/ui/lexer/error-stage.rs
index c8d88f7..f0ccb88 100644
--- a/tests/ui/lexer/error-stage.rs
+++ b/tests/ui/lexer/error-stage.rs
@@ -59,7 +59,7 @@ macro_rules! sink {
// The invalid literals used to cause errors, but this was changed by #102944.
// Except for `0b010.0f32`, because it's a lexer error.
-#[cfg(FALSE)]
+#[cfg(false)]
fn configured_out() {
"string"any_suffix; // OK
10u123; // OK
diff --git a/tests/ui/lifetimes/issue-83737-binders-across-types.rs b/tests/ui/lifetimes/issue-83737-binders-across-types.rs
index d20c84d..6f39938 100644
--- a/tests/ui/lifetimes/issue-83737-binders-across-types.rs
+++ b/tests/ui/lifetimes/issue-83737-binders-across-types.rs
@@ -1,5 +1,5 @@
//@ build-pass
-//@ compile-flags: --edition 2018
+//@ edition: 2018
//@ compile-flags: --crate-type rlib
use std::future::Future;
diff --git a/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs
index 466bcdc..dcc8c7e 100644
--- a/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs
+++ b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs
@@ -1,5 +1,5 @@
//@ build-pass
-//@ compile-flags: --edition 2018
+//@ edition: 2018
//@ compile-flags: --crate-type rlib
use std::future::Future;
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.rs b/tests/ui/link-native-libs/link-attr-validation-late.rs
index 34f720d..4eeb8ba 100644
--- a/tests/ui/link-native-libs/link-attr-validation-late.rs
+++ b/tests/ui/link-native-libs/link-attr-validation-late.rs
@@ -9,7 +9,7 @@
#[link(name = "foo", name = "bar")] //~ ERROR multiple `name` arguments
#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR multiple `kind` arguments
#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR multiple `modifiers` arguments
-#[link(name = "...", cfg(FALSE), cfg(FALSE))] //~ ERROR multiple `cfg` arguments
+#[link(name = "...", cfg(false), cfg(false))] //~ ERROR multiple `cfg` arguments
#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR multiple `wasm_import_module` arguments
extern "C" {}
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr
index 1ad5fba..f3989c0 100644
--- a/tests/ui/link-native-libs/link-attr-validation-late.stderr
+++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr
@@ -31,7 +31,7 @@
error: multiple `cfg` arguments in a single `#[link]` attribute
--> $DIR/link-attr-validation-late.rs:12:34
|
-LL | #[link(name = "...", cfg(FALSE), cfg(FALSE))]
+LL | #[link(name = "...", cfg(false), cfg(false))]
| ^^^^^^^^^^
error: multiple `wasm_import_module` arguments in a single `#[link]` attribute
diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.rs b/tests/ui/link-native-libs/suggest-libname-only-1.rs
index 4ccfa08..8699e48 100644
--- a/tests/ui/link-native-libs/suggest-libname-only-1.rs
+++ b/tests/ui/link-native-libs/suggest-libname-only-1.rs
@@ -1,10 +1,11 @@
//@ build-fail
//@ compile-flags: --crate-type rlib
-//@ error-pattern: only provide the library name `foo`, not the full filename
#[link(name = "libfoo.a", kind = "static")]
-extern { } //~ WARN extern declarations without an explicit ABI are deprecated
+extern { } //~ WARN `extern` declarations without an explicit ABI are deprecated
+ //~| HELP explicitly specify the "C" ABI
pub fn main() { }
//~? ERROR could not find native static library `libfoo.a`
+//~? HELP only provide the library name `foo`, not the full filename
diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.stderr b/tests/ui/link-native-libs/suggest-libname-only-1.stderr
index 85a3599..59bd99f 100644
--- a/tests/ui/link-native-libs/suggest-libname-only-1.stderr
+++ b/tests/ui/link-native-libs/suggest-libname-only-1.stderr
@@ -1,5 +1,5 @@
-warning: extern declarations without an explicit ABI are deprecated
- --> $DIR/suggest-libname-only-1.rs:6:1
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/suggest-libname-only-1.rs:5:1
|
LL | extern { }
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.rs b/tests/ui/link-native-libs/suggest-libname-only-2.rs
index c35b4a6..87373f5 100644
--- a/tests/ui/link-native-libs/suggest-libname-only-2.rs
+++ b/tests/ui/link-native-libs/suggest-libname-only-2.rs
@@ -1,10 +1,11 @@
//@ build-fail
//@ compile-flags: --crate-type rlib
-//@ error-pattern: only provide the library name `bar`, not the full filename
#[link(name = "bar.lib", kind = "static")]
-extern { } //~ WARN extern declarations without an explicit ABI are deprecated
+extern { } //~ WARN `extern` declarations without an explicit ABI are deprecated
+ //~| HELP explicitly specify the "C" ABI
pub fn main() { }
//~? ERROR could not find native static library `bar.lib`
+//~? HELP only provide the library name `bar`, not the full filename
diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.stderr b/tests/ui/link-native-libs/suggest-libname-only-2.stderr
index d5c8893..298a9ce 100644
--- a/tests/ui/link-native-libs/suggest-libname-only-2.stderr
+++ b/tests/ui/link-native-libs/suggest-libname-only-2.stderr
@@ -1,5 +1,5 @@
-warning: extern declarations without an explicit ABI are deprecated
- --> $DIR/suggest-libname-only-2.rs:6:1
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/suggest-libname-only-2.rs:5:1
|
LL | extern { }
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
diff --git a/tests/ui/lint/break-with-label-and-unsafe-block.rs b/tests/ui/lint/break-with-label-and-unsafe-block.rs
new file mode 100644
index 0000000..a76a576
--- /dev/null
+++ b/tests/ui/lint/break-with-label-and-unsafe-block.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+
+#![deny(break_with_label_and_loop)]
+
+unsafe fn foo() -> i32 { 42 }
+
+fn main () {
+ 'label: loop {
+ break 'label unsafe { foo() }
+ };
+}
diff --git a/tests/ui/lint/cli-lint-override.forbid_warn.stderr b/tests/ui/lint/cli-lint-override.forbid_warn.stderr
index fb8779a..fe3437a 100644
--- a/tests/ui/lint/cli-lint-override.forbid_warn.stderr
+++ b/tests/ui/lint/cli-lint-override.forbid_warn.stderr
@@ -1,4 +1,4 @@
-error: extern declarations without an explicit ABI are deprecated
+error: `extern` declarations without an explicit ABI are deprecated
--> $DIR/cli-lint-override.rs:12:1
|
LL | extern fn foo() {}
diff --git a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr
index 10fc13e..f48fca4 100644
--- a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr
+++ b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr
@@ -1,4 +1,4 @@
-warning: extern declarations without an explicit ABI are deprecated
+warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/cli-lint-override.rs:12:1
|
LL | extern fn foo() {}
diff --git a/tests/ui/lint/cli-lint-override.rs b/tests/ui/lint/cli-lint-override.rs
index 4b3fd0d..b733872 100644
--- a/tests/ui/lint/cli-lint-override.rs
+++ b/tests/ui/lint/cli-lint-override.rs
@@ -10,8 +10,8 @@
extern fn foo() {}
-//[warn_deny]~^ ERROR extern declarations without an explicit ABI are deprecated
-//[forbid_warn]~^^ ERROR extern declarations without an explicit ABI are deprecated
-//[force_warn_deny]~^^^ WARN extern declarations without an explicit ABI are deprecated
+//[warn_deny]~^ ERROR `extern` declarations without an explicit ABI are deprecated
+//[forbid_warn]~^^ ERROR `extern` declarations without an explicit ABI are deprecated
+//[force_warn_deny]~^^^ WARN `extern` declarations without an explicit ABI are deprecated
fn main() {}
diff --git a/tests/ui/lint/cli-lint-override.warn_deny.stderr b/tests/ui/lint/cli-lint-override.warn_deny.stderr
index 979ca22..91baad1 100644
--- a/tests/ui/lint/cli-lint-override.warn_deny.stderr
+++ b/tests/ui/lint/cli-lint-override.warn_deny.stderr
@@ -1,4 +1,4 @@
-error: extern declarations without an explicit ABI are deprecated
+error: `extern` declarations without an explicit ABI are deprecated
--> $DIR/cli-lint-override.rs:12:1
|
LL | extern fn foo() {}
diff --git a/tests/ui/lint/cli-unknown-force-warn.rs b/tests/ui/lint/cli-unknown-force-warn.rs
index 330d557..0c60f48 100644
--- a/tests/ui/lint/cli-unknown-force-warn.rs
+++ b/tests/ui/lint/cli-unknown-force-warn.rs
@@ -3,12 +3,12 @@
//@ check-pass
//@ compile-flags: --force-warn foo-qux
-
-//@ error-pattern: requested on the command line with `--force-warn foo_qux`
-//@ error-pattern: `#[warn(unknown_lints)]` on by default
+//@ dont-require-annotations: NOTE
fn main() {}
//~? WARN unknown lint: `foo_qux`
//~? WARN unknown lint: `foo_qux`
//~? WARN unknown lint: `foo_qux`
+//~? NOTE requested on the command line with `--force-warn foo_qux`
+//~? NOTE `#[warn(unknown_lints)]` on by default
diff --git a/tests/ui/lint/dead-code/self-assign.rs b/tests/ui/lint/dead-code/self-assign.rs
index 072a899..357846b 100644
--- a/tests/ui/lint/dead-code/self-assign.rs
+++ b/tests/ui/lint/dead-code/self-assign.rs
@@ -1,19 +1,29 @@
-// Test that dead code warnings are issued for superfluous assignments of
-// fields or variables to themselves (issue #75356).
-
-//@ ignore-test FIXME(81658, 83171)
+//! Test that dead code warnings are issued for superfluous assignments of fields or variables to
+//! themselves (issue #75356).
+//!
+//! # History of this test (to aid relanding of a fixed version of #81473)
+//!
+//! - Original lint request was about self-assignments not triggering sth like `dead_code`.
+//! - `dead_code` lint expansion for self-assignments was implemented in #87129.
+//! - Unfortunately implementation components of #87129 had to be disabled as part of reverts
+//! #86212, #83171 (to revert #81473) to address regressions #81626 and #81658.
+//! - Consequently, none of the following warnings are emitted.
//@ check-pass
+
+// Implementation of self-assignment `dead_code` lint expansions disabled due to reverts.
+//@ known-bug: #75356
+
#![allow(unused_assignments)]
#![warn(dead_code)]
fn main() {
let mut x = 0;
x = x;
- //~^ WARNING: useless assignment of variable of type `i32` to itself
+ // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself
x = (x);
- //~^ WARNING: useless assignment of variable of type `i32` to itself
+ // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself
x = {x};
// block expressions don't count as self-assignments
@@ -22,10 +32,10 @@ fn main() {
struct S<'a> { f: &'a str }
let mut s = S { f: "abc" };
s = s;
- //~^ WARNING: useless assignment of variable of type `S` to itself
+ // FIXME ~^ WARNING: useless assignment of variable of type `S` to itself
s.f = s.f;
- //~^ WARNING: useless assignment of field of type `&str` to itself
+ // FIXME ~^ WARNING: useless assignment of field of type `&str` to itself
struct N0 { x: Box<i32> }
@@ -34,11 +44,11 @@ struct N1 { n: N0 }
struct N3 { n: N2 };
let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) };
n3.n.0.n.x = n3.n.0.n.x;
- //~^ WARNING: useless assignment of field of type `Box<i32>` to itself
+ // FIXME ~^ WARNING: useless assignment of field of type `Box<i32>` to itself
let mut t = (1, ((2, 3, (4, 5)),));
t.1.0.2.1 = t.1.0.2.1;
- //~^ WARNING: useless assignment of field of type `i32` to itself
+ // FIXME ~^ WARNING: useless assignment of field of type `i32` to itself
let mut y = 0;
diff --git a/tests/ui/lint/dead-code/self-assign.stderr b/tests/ui/lint/dead-code/self-assign.stderr
deleted file mode 100644
index bb79c0e..0000000
--- a/tests/ui/lint/dead-code/self-assign.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-warning: useless assignment of variable of type `i32` to itself
- --> $DIR/self-assign.rs:10:5
- |
-LL | x = x;
- | ^^^^^
- |
-note: the lint level is defined here
- --> $DIR/self-assign.rs:6:9
- |
-LL | #![warn(dead_code)]
- | ^^^^^^^^^
-
-warning: useless assignment of variable of type `i32` to itself
- --> $DIR/self-assign.rs:13:5
- |
-LL | x = (x);
- | ^^^^^^^
-
-warning: useless assignment of variable of type `S` to itself
- --> $DIR/self-assign.rs:22:5
- |
-LL | s = s;
- | ^^^^^
-
-warning: useless assignment of field of type `&str` to itself
- --> $DIR/self-assign.rs:25:5
- |
-LL | s.f = s.f;
- | ^^^^^^^^^
-
-warning: useless assignment of field of type `Box<i32>` to itself
- --> $DIR/self-assign.rs:34:5
- |
-LL | n3.n.0.n.x = n3.n.0.n.x;
- | ^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: useless assignment of field of type `i32` to itself
- --> $DIR/self-assign.rs:38:5
- |
-LL | t.1.0.2.1 = t.1.0.2.1;
- | ^^^^^^^^^^^^^^^^^^^^^
-
-warning: 6 warnings emitted
-
diff --git a/tests/ui/lint/expansion-time-include.rs b/tests/ui/lint/expansion-time-include.rs
index 3ecc01b..cbe3510 100644
--- a/tests/ui/lint/expansion-time-include.rs
+++ b/tests/ui/lint/expansion-time-include.rs
@@ -1,4 +1,4 @@
-//@ ignore-test auxiliary file for expansion-time.rs
+//@ ignore-auxiliary (used by `./expansion-time.rs`)
1
2
diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs
index 5d4133d..f2d50e3 100644
--- a/tests/ui/lint/inert-attr-macro.rs
+++ b/tests/ui/lint/inert-attr-macro.rs
@@ -1,6 +1,5 @@
//@ check-pass
-#![feature(cfg_boolean_literals)]
#![warn(unused)]
macro_rules! foo {
diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr
index b85b031..5ccb4ff 100644
--- a/tests/ui/lint/inert-attr-macro.stderr
+++ b/tests/ui/lint/inert-attr-macro.stderr
@@ -1,41 +1,41 @@
warning: unused attribute `inline`
- --> $DIR/inert-attr-macro.rs:11:5
+ --> $DIR/inert-attr-macro.rs:10:5
|
LL | #[inline] foo!();
| ^^^^^^^^^
|
note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
- --> $DIR/inert-attr-macro.rs:11:15
+ --> $DIR/inert-attr-macro.rs:10:15
|
LL | #[inline] foo!();
| ^^^
note: the lint level is defined here
- --> $DIR/inert-attr-macro.rs:4:9
+ --> $DIR/inert-attr-macro.rs:3:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
warning: unused attribute `allow`
- --> $DIR/inert-attr-macro.rs:15:5
+ --> $DIR/inert-attr-macro.rs:14:5
|
LL | #[allow(warnings)] #[inline] foo!();
| ^^^^^^^^^^^^^^^^^^
|
note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
- --> $DIR/inert-attr-macro.rs:15:34
+ --> $DIR/inert-attr-macro.rs:14:34
|
LL | #[allow(warnings)] #[inline] foo!();
| ^^^
warning: unused attribute `inline`
- --> $DIR/inert-attr-macro.rs:15:24
+ --> $DIR/inert-attr-macro.rs:14:24
|
LL | #[allow(warnings)] #[inline] foo!();
| ^^^^^^^^^
|
note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
- --> $DIR/inert-attr-macro.rs:15:34
+ --> $DIR/inert-attr-macro.rs:14:34
|
LL | #[allow(warnings)] #[inline] foo!();
| ^^^
diff --git a/tests/ui/lint/known-tool-in-submodule/submodule.rs b/tests/ui/lint/known-tool-in-submodule/submodule.rs
index 0bb2b93..9c24964 100644
--- a/tests/ui/lint/known-tool-in-submodule/submodule.rs
+++ b/tests/ui/lint/known-tool-in-submodule/submodule.rs
@@ -1,4 +1,4 @@
-//@ ignore-test: not a test
+//@ ignore-auxiliary (used by `./root.rs`)
#[allow(tool::lint)]
pub fn foo() {}
diff --git a/tests/ui/lint/lint-removed-cmdline-deny.rs b/tests/ui/lint/lint-removed-cmdline-deny.rs
index 6616781..83bbd24 100644
--- a/tests/ui/lint/lint-removed-cmdline-deny.rs
+++ b/tests/ui/lint/lint-removed-cmdline-deny.rs
@@ -2,9 +2,7 @@
// cc #30346
//@ compile-flags:-D renamed-and-removed-lints -D raw_pointer_derive
-
-//@ error-pattern:requested on the command line with `-D raw_pointer_derive`
-//@ error-pattern:requested on the command line with `-D renamed-and-removed-lints`
+//@ dont-require-annotations: NOTE
#![warn(unused)]
@@ -14,3 +12,5 @@
//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
//~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
+//~? NOTE requested on the command line with `-D raw_pointer_derive`
+//~? NOTE requested on the command line with `-D renamed-and-removed-lints`
diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr
index 27a3504..2fb2373 100644
--- a/tests/ui/lint/lint-removed-cmdline-deny.stderr
+++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr
@@ -14,13 +14,13 @@
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unused variable: `unused`
- --> $DIR/lint-removed-cmdline-deny.rs:12:17
+ --> $DIR/lint-removed-cmdline-deny.rs:10:17
|
LL | fn main() { let unused = (); }
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
|
note: the lint level is defined here
- --> $DIR/lint-removed-cmdline-deny.rs:11:8
+ --> $DIR/lint-removed-cmdline-deny.rs:9:8
|
LL | #[deny(warnings)]
| ^^^^^^^^
diff --git a/tests/ui/lint/lint-removed-cmdline.rs b/tests/ui/lint/lint-removed-cmdline.rs
index 4dde3db..f83747a 100644
--- a/tests/ui/lint/lint-removed-cmdline.rs
+++ b/tests/ui/lint/lint-removed-cmdline.rs
@@ -2,9 +2,7 @@
// cc #30346
//@ compile-flags:-D raw_pointer_derive
-
-//@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default
-//@ error-pattern:requested on the command line with `-D raw_pointer_derive`
+//@ dont-require-annotations: NOTE
#![warn(unused)]
@@ -14,3 +12,5 @@
//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
//~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
+//~? NOTE `#[warn(renamed_and_removed_lints)]` on by default
+//~? NOTE requested on the command line with `-D raw_pointer_derive`
diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr
index 7994f9b..64e7c57 100644
--- a/tests/ui/lint/lint-removed-cmdline.stderr
+++ b/tests/ui/lint/lint-removed-cmdline.stderr
@@ -14,13 +14,13 @@
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unused variable: `unused`
- --> $DIR/lint-removed-cmdline.rs:12:17
+ --> $DIR/lint-removed-cmdline.rs:10:17
|
LL | fn main() { let unused = (); }
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
|
note: the lint level is defined here
- --> $DIR/lint-removed-cmdline.rs:11:8
+ --> $DIR/lint-removed-cmdline.rs:9:8
|
LL | #[deny(warnings)]
| ^^^^^^^^
diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.rs b/tests/ui/lint/lint-renamed-cmdline-deny.rs
index 0ea4ce4..c8b0350 100644
--- a/tests/ui/lint/lint-renamed-cmdline-deny.rs
+++ b/tests/ui/lint/lint-renamed-cmdline-deny.rs
@@ -1,8 +1,6 @@
//@ compile-flags:-D renamed-and-removed-lints -D bare_trait_object
-
-//@ error-pattern:use the new name `bare_trait_objects`
-//@ error-pattern:requested on the command line with `-D bare_trait_object`
-//@ error-pattern:requested on the command line with `-D renamed-and-removed-lints`
+//@ dont-require-annotations: HELP
+//@ dont-require-annotations: NOTE
#[deny(unused)]
fn main() { let unused = (); } //~ ERROR unused variable: `unused`
@@ -10,3 +8,6 @@
//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects`
//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects`
//~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects`
+//~? HELP use the new name `bare_trait_objects`
+//~? NOTE requested on the command line with `-D bare_trait_object`
+//~? NOTE requested on the command line with `-D renamed-and-removed-lints`
diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr
index a49cdc8..b42b828 100644
--- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr
+++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr
@@ -17,13 +17,13 @@
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unused variable: `unused`
- --> $DIR/lint-renamed-cmdline-deny.rs:8:17
+ --> $DIR/lint-renamed-cmdline-deny.rs:6:17
|
LL | fn main() { let unused = (); }
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
|
note: the lint level is defined here
- --> $DIR/lint-renamed-cmdline-deny.rs:7:8
+ --> $DIR/lint-renamed-cmdline-deny.rs:5:8
|
LL | #[deny(unused)]
| ^^^^^^
diff --git a/tests/ui/lint/lint-renamed-cmdline.rs b/tests/ui/lint/lint-renamed-cmdline.rs
index 45df7b6..757cb51 100644
--- a/tests/ui/lint/lint-renamed-cmdline.rs
+++ b/tests/ui/lint/lint-renamed-cmdline.rs
@@ -1,7 +1,5 @@
//@ compile-flags:-D bare_trait_object
-
-//@ error-pattern:requested on the command line with `-D bare_trait_object`
-//@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default
+//@ dont-require-annotations: NOTE
#[deny(unused)]
fn main() { let unused = (); } //~ ERROR unused variable: `unused`
@@ -9,3 +7,5 @@
//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects`
//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects`
//~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects`
+//~? NOTE requested on the command line with `-D bare_trait_object`
+//~? NOTE `#[warn(renamed_and_removed_lints)]` on by default
diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr
index 901e7a6..efd399e 100644
--- a/tests/ui/lint/lint-renamed-cmdline.stderr
+++ b/tests/ui/lint/lint-renamed-cmdline.stderr
@@ -17,13 +17,13 @@
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: unused variable: `unused`
- --> $DIR/lint-renamed-cmdline.rs:7:17
+ --> $DIR/lint-renamed-cmdline.rs:5:17
|
LL | fn main() { let unused = (); }
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
|
note: the lint level is defined here
- --> $DIR/lint-renamed-cmdline.rs:6:8
+ --> $DIR/lint-renamed-cmdline.rs:4:8
|
LL | #[deny(unused)]
| ^^^^^^
diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs
index e2f7c73..ac001e1 100644
--- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs
+++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs
@@ -1,9 +1,6 @@
//@ compile-flags:-D unknown-lints -D bogus -D dead_cod
-
-//@ error-pattern:requested on the command line with `-D bogus`
-//@ error-pattern:requested on the command line with `-D dead_cod`
-//@ error-pattern:requested on the command line with `-D unknown-lints`
-//@ error-pattern:did you mean: `dead_code`
+//@ dont-require-annotations: HELP
+//@ dont-require-annotations: NOTE
fn main() { }
@@ -13,3 +10,7 @@ fn main() { }
//~? ERROR unknown lint: `dead_cod`
//~? ERROR unknown lint: `bogus`
//~? ERROR unknown lint: `dead_cod`
+//~? NOTE requested on the command line with `-D bogus`
+//~? NOTE requested on the command line with `-D dead_cod`
+//~? NOTE requested on the command line with `-D unknown-lints`
+//~? HELP did you mean: `dead_code`
diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.rs b/tests/ui/lint/lint-unknown-lint-cmdline.rs
index 931e945..7eb8c1f 100644
--- a/tests/ui/lint/lint-unknown-lint-cmdline.rs
+++ b/tests/ui/lint/lint-unknown-lint-cmdline.rs
@@ -1,10 +1,7 @@
//@ check-pass
//@ compile-flags:-D bogus -D dead_cod
-
-//@ error-pattern:requested on the command line with `-D bogus`
-//@ error-pattern:`#[warn(unknown_lints)]` on by default
-//@ error-pattern:requested on the command line with `-D dead_cod`
-//@ error-pattern:did you mean: `dead_code`
+//@ dont-require-annotations: HELP
+//@ dont-require-annotations: NOTE
fn main() { }
@@ -14,3 +11,7 @@ fn main() { }
//~? WARN unknown lint: `dead_cod`
//~? WARN unknown lint: `bogus`
//~? WARN unknown lint: `dead_cod`
+//~? NOTE requested on the command line with `-D bogus`
+//~? NOTE `#[warn(unknown_lints)]` on by default
+//~? NOTE requested on the command line with `-D dead_cod`
+//~? HELP did you mean: `dead_code`
diff --git a/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs
index 6e16a79..10e3c0f 100644
--- a/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs
+++ b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs
@@ -1,3 +1,3 @@
-//@ ignore-test: not a test
+//@ ignore-auxiliary (used by `./lint-pre-expansion-extern-module.rs`)
pub fn try() {}
diff --git a/tests/ui/lint/non-local-defs/cargo-update.rs b/tests/ui/lint/non-local-defs/cargo-update.rs
index 8b8c157..f778752 100644
--- a/tests/ui/lint/non-local-defs/cargo-update.rs
+++ b/tests/ui/lint/non-local-defs/cargo-update.rs
@@ -8,7 +8,7 @@
//
// and since we specifically want to check the presence
// of the `cargo update` suggestion we assert it here.
-//@ error-pattern: `cargo update -p non_local_macro`
+//@ dont-require-annotations: NOTE
extern crate non_local_macro;
@@ -16,5 +16,6 @@
non_local_macro::non_local_impl!(LocalStruct);
//~^ WARN non-local `impl` definition
+//~| NOTE `cargo update -p non_local_macro`
fn main() {}
diff --git a/tests/ui/lint/removed-lints/undefined_naked_function_abi.rs b/tests/ui/lint/removed-lints/undefined_naked_function_abi.rs
new file mode 100644
index 0000000..cf3ac66
--- /dev/null
+++ b/tests/ui/lint/removed-lints/undefined_naked_function_abi.rs
@@ -0,0 +1,5 @@
+//@ check-pass
+
+#![deny(undefined_naked_function_abi)]
+//~^ WARN lint `undefined_naked_function_abi` has been removed
+fn main() {}
diff --git a/tests/ui/lint/removed-lints/undefined_naked_function_abi.stderr b/tests/ui/lint/removed-lints/undefined_naked_function_abi.stderr
new file mode 100644
index 0000000..5a54668
--- /dev/null
+++ b/tests/ui/lint/removed-lints/undefined_naked_function_abi.stderr
@@ -0,0 +1,10 @@
+warning: lint `undefined_naked_function_abi` has been removed: converted into hard error, see PR #139001 <https://github.com/rust-lang/rust/issues/139001> for more information
+ --> $DIR/undefined_naked_function_abi.rs:3:9
+ |
+LL | #![deny(undefined_naked_function_abi)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(renamed_and_removed_lints)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs
index 9e38b94..11ee2bc 100644
--- a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs
+++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs
@@ -1,6 +1,7 @@
// This ensures that ICEs like rust#94953 don't happen
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
// This `expect` will create an expectation with an unstable expectation id
#[expect(while_true)]
diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout
index d804c1d..d63abea 100644
--- a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout
+++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout
@@ -7,6 +7,7 @@
// This ensures that ICEs like rust#94953 don't happen
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
// This `expect` will create an expectation with an unstable expectation id
#[expect(while_true)]
diff --git a/tests/ui/lint/unknown-lints/other.rs b/tests/ui/lint/unknown-lints/other.rs
index f917bff..7770bc5 100644
--- a/tests/ui/lint/unknown-lints/other.rs
+++ b/tests/ui/lint/unknown-lints/other.rs
@@ -1,6 +1,4 @@
-//@ ignore-test
-
-// Companion to allow-in-other-module.rs
+//@ ignore-auxiliary (used by `./allow-in-other-module.rs`)
// This should not warn.
#![allow(not_a_real_lint)]
diff --git a/tests/ui/lint/unqualified_local_imports.rs b/tests/ui/lint/unqualified_local_imports.rs
index 9de7147..b7036f9 100644
--- a/tests/ui/lint/unqualified_local_imports.rs
+++ b/tests/ui/lint/unqualified_local_imports.rs
@@ -1,4 +1,4 @@
-//@compile-flags: --edition 2018
+//@ edition: 2018
#![feature(unqualified_local_imports)]
#![deny(unqualified_local_imports)]
diff --git a/tests/ui/lint/unused/issue-70041.rs b/tests/ui/lint/unused/issue-70041.rs
index 817dfe8..890ba37 100644
--- a/tests/ui/lint/unused/issue-70041.rs
+++ b/tests/ui/lint/unused/issue-70041.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2018
+//@ edition: 2018
//@ run-pass
macro_rules! regex {
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.rs b/tests/ui/lint/unused/unused-attr-macro-rules.rs
index c0fc280..7a8a1bb 100644
--- a/tests/ui/lint/unused/unused-attr-macro-rules.rs
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.rs
@@ -17,7 +17,7 @@ macro_rules! foo2 {
() => {};
}
-#[cfg(FALSE)]
+#[cfg(false)]
macro_rules! foo {
() => {};
}
diff --git a/tests/ui/lint/wasm_c_abi_transition.rs b/tests/ui/lint/wasm_c_abi_transition.rs
index 1fe8167..6a933a0 100644
--- a/tests/ui/lint/wasm_c_abi_transition.rs
+++ b/tests/ui/lint/wasm_c_abi_transition.rs
@@ -39,3 +39,9 @@ pub fn call_other_fun(x: MyType) {
unsafe { other_fun(x) } //~ERROR: wasm ABI transition
//~^WARN: previously accepted
}
+
+// Zero-sized types are safe in both ABIs
+#[repr(C)]
+pub struct MyZstType;
+#[allow(improper_ctypes_definitions)]
+pub extern "C" fn zst_safe(_x: (), _y: MyZstType) {}
diff --git a/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs b/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs
index 3c81127..2f2bf57 100644
--- a/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs
+++ b/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -g --crate-type=rlib -Zdwarf-version=4
+//@ compile-flags: -g --crate-type=rlib -Cdwarf-version=4
pub fn say_hi() {
println!("hello there")
diff --git a/tests/ui/lto/dwarf-mixed-versions-lto.rs b/tests/ui/lto/dwarf-mixed-versions-lto.rs
index 14ef65a..900274e 100644
--- a/tests/ui/lto/dwarf-mixed-versions-lto.rs
+++ b/tests/ui/lto/dwarf-mixed-versions-lto.rs
@@ -4,7 +4,7 @@
//@ ignore-msvc Platform must use DWARF
//@ aux-build:dwarf-mixed-versions-lto-aux.rs
-//@ compile-flags: -C lto -g -Zdwarf-version=5
+//@ compile-flags: -C lto -g -Cdwarf-version=5
//@ no-prefer-dynamic
//@ build-pass
diff --git a/tests/ui/macros/auxiliary/macro-include-items-expr.rs b/tests/ui/macros/auxiliary/macro-include-items-expr.rs
index 7394f19..d00491f 100644
--- a/tests/ui/macros/auxiliary/macro-include-items-expr.rs
+++ b/tests/ui/macros/auxiliary/macro-include-items-expr.rs
@@ -1,3 +1 @@
-// ignore-test: this is not a test
-
1
diff --git a/tests/ui/macros/auxiliary/macro-include-items-item.rs b/tests/ui/macros/auxiliary/macro-include-items-item.rs
index 7d54745..761cd00 100644
--- a/tests/ui/macros/auxiliary/macro-include-items-item.rs
+++ b/tests/ui/macros/auxiliary/macro-include-items-item.rs
@@ -1,3 +1 @@
-// ignore-test: this is not a test
-
fn foo() { bar() }
diff --git a/tests/ui/macros/expr_2021_cargo_fix_edition.fixed b/tests/ui/macros/expr_2021_cargo_fix_edition.fixed
index 061a4b9..c0d2760 100644
--- a/tests/ui/macros/expr_2021_cargo_fix_edition.fixed
+++ b/tests/ui/macros/expr_2021_cargo_fix_edition.fixed
@@ -1,6 +1,6 @@
//@ run-rustfix
//@ check-pass
-//@ compile-flags: --edition=2021
+//@ edition: 2021
#![warn(edition_2024_expr_fragment_specifier)]
macro_rules! m {
diff --git a/tests/ui/macros/expr_2021_cargo_fix_edition.rs b/tests/ui/macros/expr_2021_cargo_fix_edition.rs
index cd9cd96..b2c16fc7 100644
--- a/tests/ui/macros/expr_2021_cargo_fix_edition.rs
+++ b/tests/ui/macros/expr_2021_cargo_fix_edition.rs
@@ -1,6 +1,6 @@
//@ run-rustfix
//@ check-pass
-//@ compile-flags: --edition=2021
+//@ edition: 2021
#![warn(edition_2024_expr_fragment_specifier)]
macro_rules! m {
diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.rs b/tests/ui/macros/genercs-in-path-with-prettry-hir.rs
index 84370fc..e6773f6 100644
--- a/tests/ui/macros/genercs-in-path-with-prettry-hir.rs
+++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.rs
@@ -1,4 +1,5 @@
//@ compile-flags: -Zunpretty=hir
+//@ edition: 2015
// issue#97006
diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr b/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr
index 8fcc7c6..173e775 100644
--- a/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr
+++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr
@@ -1,5 +1,5 @@
error: unexpected generic arguments in path
- --> $DIR/genercs-in-path-with-prettry-hir.rs:12:10
+ --> $DIR/genercs-in-path-with-prettry-hir.rs:13:10
|
LL | m!(inline<u8>);
| ^^^^
diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
index e8c88d2..6b41eb5 100644
--- a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
+++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
@@ -3,6 +3,7 @@
#[macro_use]
extern crate std;
//@ compile-flags: -Zunpretty=hir
+//@ edition: 2015
// issue#97006
diff --git a/tests/ui/macros/include-single-expr-helper-1.rs b/tests/ui/macros/include-single-expr-helper-1.rs
index ddeeb98..6802719 100644
--- a/tests/ui/macros/include-single-expr-helper-1.rs
+++ b/tests/ui/macros/include-single-expr-helper-1.rs
@@ -1,4 +1,4 @@
-//@ ignore-test auxiliary file for include-single-expr.rs
+//@ ignore-auxiliary (used by `./include-single-expr.rs`)
0
diff --git a/tests/ui/macros/include-single-expr-helper.rs b/tests/ui/macros/include-single-expr-helper.rs
index e8ad974..bd75bbb 100644
--- a/tests/ui/macros/include-single-expr-helper.rs
+++ b/tests/ui/macros/include-single-expr-helper.rs
@@ -1,4 +1,4 @@
-//@ ignore-test auxiliary file for include-single-expr.rs
+//@ ignore-auxiliary (used by `./include-single-expr.rs`)
0
10
diff --git a/tests/ui/macros/issue-69838-dir/bar.rs b/tests/ui/macros/issue-69838-dir/bar.rs
index 4433005..6f91f8e 100644
--- a/tests/ui/macros/issue-69838-dir/bar.rs
+++ b/tests/ui/macros/issue-69838-dir/bar.rs
@@ -1,3 +1,3 @@
-//@ ignore-test -- this is an auxiliary file as part of another test.
+//@ ignore-auxiliary (used by `../issue-69838-mods-relative-to-included-path.rs`)
pub fn i_am_in_bar() {}
diff --git a/tests/ui/macros/issue-69838-dir/included.rs b/tests/ui/macros/issue-69838-dir/included.rs
index 11fcd3e..328334d 100644
--- a/tests/ui/macros/issue-69838-dir/included.rs
+++ b/tests/ui/macros/issue-69838-dir/included.rs
@@ -1,3 +1,3 @@
-//@ ignore-test -- this is an auxiliary file as part of another test.
+//@ ignore-auxiliary (used by `../issue-69838-mods-relative-to-included-path.rs`)
pub mod bar;
diff --git a/tests/ui/macros/lint-trailing-macro-call.rs b/tests/ui/macros/lint-trailing-macro-call.rs
index 66dce05..78b861f 100644
--- a/tests/ui/macros/lint-trailing-macro-call.rs
+++ b/tests/ui/macros/lint-trailing-macro-call.rs
@@ -6,7 +6,7 @@
macro_rules! expand_it {
() => {
- #[cfg(FALSE)] 25; //~ WARN trailing semicolon in macro
+ #[cfg(false)] 25; //~ WARN trailing semicolon in macro
//~| WARN this was previously
}
}
diff --git a/tests/ui/macros/lint-trailing-macro-call.stderr b/tests/ui/macros/lint-trailing-macro-call.stderr
index 13cecc3..223b85e 100644
--- a/tests/ui/macros/lint-trailing-macro-call.stderr
+++ b/tests/ui/macros/lint-trailing-macro-call.stderr
@@ -1,7 +1,7 @@
warning: trailing semicolon in macro used in expression position
--> $DIR/lint-trailing-macro-call.rs:9:25
|
-LL | #[cfg(FALSE)] 25;
+LL | #[cfg(false)] 25;
| ^
...
LL | expand_it!()
@@ -20,7 +20,7 @@
warning: trailing semicolon in macro used in expression position
--> $DIR/lint-trailing-macro-call.rs:9:25
|
-LL | #[cfg(FALSE)] 25;
+LL | #[cfg(false)] 25;
| ^
...
LL | expand_it!()
diff --git a/tests/ui/macros/macro-as-fn-body.rs b/tests/ui/macros/macro-as-fn-body.rs
index e0542ed..188c7f7 100644
--- a/tests/ui/macros/macro-as-fn-body.rs
+++ b/tests/ui/macros/macro-as-fn-body.rs
@@ -1,7 +1,7 @@
//
//@ run-pass
//
-// Description - ensure Interpolated blocks can act as valid function bodies
+// Description - ensure block metavariables can act as valid function bodies
// Covered cases: free functions, struct methods, and default trait functions
macro_rules! def_fn {
diff --git a/tests/ui/macros/macro-attributes.rs b/tests/ui/macros/macro-attributes.rs
index 8329079..976d2cb 100644
--- a/tests/ui/macros/macro-attributes.rs
+++ b/tests/ui/macros/macro-attributes.rs
@@ -9,7 +9,7 @@ macro_rules! compiles_fine {
// check that the attributes are recognised by requiring this
// to be removed to avoid a compile error
- #[cfg(FALSE)]
+ #[cfg(false)]
static MISTYPED: () = "foo";
}
}
diff --git a/tests/ui/macros/macro-expanded-include/foo/mod.rs b/tests/ui/macros/macro-expanded-include/foo/mod.rs
index 926d84c..4e6d9e4 100644
--- a/tests/ui/macros/macro-expanded-include/foo/mod.rs
+++ b/tests/ui/macros/macro-expanded-include/foo/mod.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `../test.rs`)
macro_rules! m {
() => { include!("file.txt"); }
diff --git a/tests/ui/macros/macro-inner-attributes.rs b/tests/ui/macros/macro-inner-attributes.rs
index a1eb7cd..1a832ca 100644
--- a/tests/ui/macros/macro-inner-attributes.rs
+++ b/tests/ui/macros/macro-inner-attributes.rs
@@ -5,7 +5,7 @@ macro_rules! test { ($nm:ident,
$i:item) => (mod $nm { #![$a] $i }); }
test!(a,
- #[cfg(FALSE)],
+ #[cfg(false)],
pub fn bar() { });
test!(b,
diff --git a/tests/ui/macros/macro-outer-attributes.rs b/tests/ui/macros/macro-outer-attributes.rs
index 8c79683..5b41cf9 100644
--- a/tests/ui/macros/macro-outer-attributes.rs
+++ b/tests/ui/macros/macro-outer-attributes.rs
@@ -5,7 +5,7 @@ macro_rules! test { ($nm:ident,
$i:item) => (mod $nm { #[$a] $i }); }
test!(a,
- #[cfg(FALSE)],
+ #[cfg(false)],
pub fn bar() { });
test!(b,
diff --git a/tests/ui/macros/macro-outer-attributes.stderr b/tests/ui/macros/macro-outer-attributes.stderr
index a8809f3..a894c90 100644
--- a/tests/ui/macros/macro-outer-attributes.stderr
+++ b/tests/ui/macros/macro-outer-attributes.stderr
@@ -16,7 +16,7 @@
| ^^^^^
LL |
LL | / test!(a,
-LL | | #[cfg(FALSE)],
+LL | | #[cfg(false)],
LL | | pub fn bar() { });
| |_______________________- in this macro invocation
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/macros/macro-with-attrs2.rs b/tests/ui/macros/macro-with-attrs2.rs
index 37188e4..7d0bf91 100644
--- a/tests/ui/macros/macro-with-attrs2.rs
+++ b/tests/ui/macros/macro-with-attrs2.rs
@@ -1,6 +1,6 @@
//@ run-pass
-#[cfg(FALSE)]
+#[cfg(false)]
macro_rules! foo { () => (1) }
#[cfg(not(FALSE))]
diff --git a/tests/ui/macros/remove-repetition-issue-139480.rs b/tests/ui/macros/remove-repetition-issue-139480.rs
new file mode 100644
index 0000000..1efb430
--- /dev/null
+++ b/tests/ui/macros/remove-repetition-issue-139480.rs
@@ -0,0 +1,28 @@
+macro_rules! ciallo {
+ ($($v: vis)? $name: ident) => {
+ //~^ error: repetition matches empty token tree
+ };
+}
+
+macro_rules! meow {
+ ($name: ident $($v: vis)?) => {
+ //~^ error: repetition matches empty token tree
+ };
+}
+
+macro_rules! gbc {
+ ($name: ident $/*
+ this comment gets removed by the suggestion
+ */
+ ($v: vis)?) => {
+ //~^ error: repetition matches empty token tree
+ };
+}
+
+ciallo!(hello);
+
+meow!(miaow, pub);
+
+gbc!(mygo,);
+
+fn main() {}
diff --git a/tests/ui/macros/remove-repetition-issue-139480.stderr b/tests/ui/macros/remove-repetition-issue-139480.stderr
new file mode 100644
index 0000000..c247558
--- /dev/null
+++ b/tests/ui/macros/remove-repetition-issue-139480.stderr
@@ -0,0 +1,44 @@
+error: repetition matches empty token tree
+ --> $DIR/remove-repetition-issue-139480.rs:2:7
+ |
+LL | ($($v: vis)? $name: ident) => {
+ | ^^^^^^^^^
+ |
+ = note: a `vis` fragment can already be empty
+help: remove the `$(` and `)?`
+ |
+LL - ($($v: vis)? $name: ident) => {
+LL + ($v: vis $name: ident) => {
+ |
+
+error: repetition matches empty token tree
+ --> $DIR/remove-repetition-issue-139480.rs:8:20
+ |
+LL | ($name: ident $($v: vis)?) => {
+ | ^^^^^^^^^
+ |
+ = note: a `vis` fragment can already be empty
+help: remove the `$(` and `)?`
+ |
+LL - ($name: ident $($v: vis)?) => {
+LL + ($name: ident $v: vis) => {
+ |
+
+error: repetition matches empty token tree
+ --> $DIR/remove-repetition-issue-139480.rs:17:9
+ |
+LL | ($v: vis)?) => {
+ | ^^^^^^^^^
+ |
+ = note: a `vis` fragment can already be empty
+help: remove the `$(` and `)?`
+ |
+LL - ($name: ident $/*
+LL - this comment gets removed by the suggestion
+LL - */
+LL - ($v: vis)?) => {
+LL + ($name: ident $v: vis) => {
+ |
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/macros/reparse-expr-issue-139495.rs b/tests/ui/macros/reparse-expr-issue-139495.rs
new file mode 100644
index 0000000..38d2457
--- /dev/null
+++ b/tests/ui/macros/reparse-expr-issue-139495.rs
@@ -0,0 +1,7 @@
+macro_rules! m {
+ ($abi : expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
+}
+
+fn main() {
+ m!(-2)
+}
diff --git a/tests/ui/macros/reparse-expr-issue-139495.stderr b/tests/ui/macros/reparse-expr-issue-139495.stderr
new file mode 100644
index 0000000..73a8ed8
--- /dev/null
+++ b/tests/ui/macros/reparse-expr-issue-139495.stderr
@@ -0,0 +1,13 @@
+error: expected expression, found keyword `extern`
+ --> $DIR/reparse-expr-issue-139495.rs:2:22
+ |
+LL | ($abi : expr) => { extern $abi }
+ | ^^^^^^ expected expression
+...
+LL | m!(-2)
+ | ------ in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
index cf47a1e..29f71d1 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
@@ -1,5 +1,6 @@
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
#![feature(core_intrinsics, generic_assert)]
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
index 8065d0d..9300f61 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
@@ -2,6 +2,7 @@
#![no_std]
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
#![feature(core_intrinsics, generic_assert)]
#[prelude_import]
diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs
index 6cf9d54..e1681ea 100644
--- a/tests/ui/macros/syntax-error-recovery.rs
+++ b/tests/ui/macros/syntax-error-recovery.rs
@@ -5,14 +5,14 @@ pub enum TokenKind {
$(
#[$attr]
$token $($inner)? = $value,
+ //~^ ERROR expected one of `!` or `::`, found `<eof>`
)*
}
};
}
-//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable
+//~^^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable
//~| ERROR macro expansion ignores `ty` metavariable and any tokens following
values!(STRING(1) as (String) => cfg(test),);
-//~^ ERROR expected one of `!` or `::`, found `<eof>`
fn main() {}
diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr
index 61758fb..a2059aa 100644
--- a/tests/ui/macros/syntax-error-recovery.stderr
+++ b/tests/ui/macros/syntax-error-recovery.stderr
@@ -22,10 +22,10 @@
= note: the usage of `values!` is likely invalid in item context
error: expected one of `!` or `::`, found `<eof>`
- --> $DIR/syntax-error-recovery.rs:15:9
+ --> $DIR/syntax-error-recovery.rs:7:17
|
-LL | values!(STRING(1) as (String) => cfg(test),);
- | ^^^^^^ expected one of `!` or `::`
+LL | $token $($inner)? = $value,
+ | ^^^^^^ expected one of `!` or `::`
error: aborting due to 3 previous errors
diff --git a/tests/ui/match/issue-82392.rs b/tests/ui/match/issue-82392.rs
index 6f9527f..4ae08fe 100644
--- a/tests/ui/match/issue-82392.rs
+++ b/tests/ui/match/issue-82392.rs
@@ -1,6 +1,7 @@
// https://github.com/rust-lang/rust/issues/82329
//@ compile-flags: -Zunpretty=hir,typed
//@ check-pass
+//@ edition:2015
pub fn main() {
if true {
diff --git a/tests/ui/match/issue-82392.stdout b/tests/ui/match/issue-82392.stdout
index 8949611..8b7edab 100644
--- a/tests/ui/match/issue-82392.stdout
+++ b/tests/ui/match/issue-82392.stdout
@@ -5,6 +5,7 @@
// https://github.com/rust-lang/rust/issues/82329
//@ compile-flags: -Zunpretty=hir,typed
//@ check-pass
+//@ edition:2015
fn main() ({
(if (true as bool)
diff --git a/tests/ui/mir-dataflow/README.md b/tests/ui/mir-dataflow/README.md
index a3ab14b..8860202 100644
--- a/tests/ui/mir-dataflow/README.md
+++ b/tests/ui/mir-dataflow/README.md
@@ -42,12 +42,3 @@
on *entry* to each block, as well as the gen- and kill-sets that
were so-called "transfer functions" summarizing the effect of each
basic block.
-
- * (In addition to the `borrowck_graphviz_postflow` attribute-key
- noted above, there is also `borrowck_graphviz_preflow`; it has the
- same interface and generates the same set of files, but it renders
- the dataflow state after building the gen- and kill-sets but
- *before* running the dataflow analysis itself, so each entry-set is
- just the initial default state for that dataflow analysis. This is
- less useful for understanding the error message output in these
- tests.)
diff --git a/tests/ui/mir/issue-105809.rs b/tests/ui/mir/issue-105809.rs
index e7a8fb6..a46dcf3 100644
--- a/tests/ui/mir/issue-105809.rs
+++ b/tests/ui/mir/issue-105809.rs
@@ -1,7 +1,8 @@
// Non-regression test ICE from issue #105809 and duplicates.
//@ build-pass: the ICE is during codegen
-//@ compile-flags: --edition 2018 -Zmir-opt-level=1
+//@ compile-flags: -Zmir-opt-level=1
+//@ edition: 2018
use std::{future::Future, pin::Pin};
diff --git a/tests/ui/missing/missing-return.rs b/tests/ui/missing/missing-return.rs
index 5d9839a..4d48e7c 100644
--- a/tests/ui/missing/missing-return.rs
+++ b/tests/ui/missing/missing-return.rs
@@ -1,5 +1,4 @@
-//@ error-pattern: return
-
fn f() -> isize { } //~ ERROR mismatched types
-
+ //~| NOTE implicitly returns `()` as its body has no tail or `return` expression
+ //~| NOTE expected `isize`, found `()`
fn main() { f(); }
diff --git a/tests/ui/missing/missing-return.stderr b/tests/ui/missing/missing-return.stderr
index 5f7fb50..b2d202b 100644
--- a/tests/ui/missing/missing-return.stderr
+++ b/tests/ui/missing/missing-return.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/missing-return.rs:3:11
+ --> $DIR/missing-return.rs:1:11
|
LL | fn f() -> isize { }
| - ^^^^^ expected `isize`, found `()`
diff --git a/tests/ui/missing_non_modrs_mod/foo.rs b/tests/ui/missing_non_modrs_mod/foo.rs
index dd3e970..afdc5e3 100644
--- a/tests/ui/missing_non_modrs_mod/foo.rs
+++ b/tests/ui/missing_non_modrs_mod/foo.rs
@@ -1,4 +1,3 @@
-//
-//@ ignore-test this is just a helper for the real test in this dir
+//@ ignore-auxiliary (used by `./missing_non_modrs_mod.rs`)
mod missing;
diff --git a/tests/ui/missing_non_modrs_mod/foo_inline.rs b/tests/ui/missing_non_modrs_mod/foo_inline.rs
index 9d46e9b..ed6d3a4 100644
--- a/tests/ui/missing_non_modrs_mod/foo_inline.rs
+++ b/tests/ui/missing_non_modrs_mod/foo_inline.rs
@@ -1,4 +1,4 @@
-//@ ignore-test this is just a helper for the real test in this dir
+//@ ignore-auxiliary (used by `./missing_non_modrs_mod_inline.rs`)
mod inline {
mod missing;
diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
index 4e48799..c084fbf 100644
--- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
+++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr
@@ -1,5 +1,5 @@
error[E0583]: file not found for module `missing`
- --> $DIR/foo.rs:4:1
+ --> $DIR/foo.rs:3:1
|
LL | mod missing;
| ^^^^^^^^^^^^
diff --git a/tests/ui/modules/mod_file_aux.rs b/tests/ui/modules/mod_file_aux.rs
index f37296b..eec38d1 100644
--- a/tests/ui/modules/mod_file_aux.rs
+++ b/tests/ui/modules/mod_file_aux.rs
@@ -1,4 +1,3 @@
-//@ run-pass
-//@ ignore-test Not a test. Used by other tests
+//@ ignore-auxiliary (used by `./mod_file_with_path_attr.rs` and `mod_file.rs`)
pub fn foo() -> isize { 10 }
diff --git a/tests/ui/modules_and_files_visibility/mod_file_aux.rs b/tests/ui/modules_and_files_visibility/mod_file_aux.rs
index 77390da..6fac8da 100644
--- a/tests/ui/modules_and_files_visibility/mod_file_aux.rs
+++ b/tests/ui/modules_and_files_visibility/mod_file_aux.rs
@@ -1,3 +1,3 @@
-//@ ignore-test Not a test. Used by other tests
+//@ ignore-auxiliary (used by `./mod_file_correct_spans.rs`)
pub fn foo() -> isize { 10 }
diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs
index e00b562..9a0b1c4 100644
--- a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs
+++ b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs
@@ -1 +1 @@
-//@ ignore-test not a test. aux file
+//@ ignore-auxiliary (used by `./mod_file_disambig.rs`)
diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs
index e00b562..232c933 100644
--- a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs
+++ b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs
@@ -1 +1 @@
-//@ ignore-test not a test. aux file
+//@ ignore-auxiliary (used by `../mod_file_disambig.rs`)
diff --git a/tests/ui/nested-cfg-attrs.rs b/tests/ui/nested-cfg-attrs.rs
index 0af28fc..941807a 100644
--- a/tests/ui/nested-cfg-attrs.rs
+++ b/tests/ui/nested-cfg-attrs.rs
@@ -1,4 +1,4 @@
-#[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))]
+#[cfg_attr(all(), cfg_attr(all(), cfg(false)))]
fn f() {}
fn main() { f() } //~ ERROR cannot find function `f` in this scope
diff --git a/tests/ui/nested-ty-params.rs b/tests/ui/nested-ty-params.rs
index 866e623..c00c3bc 100644
--- a/tests/ui/nested-ty-params.rs
+++ b/tests/ui/nested-ty-params.rs
@@ -1,4 +1,3 @@
-//@ error-pattern:can't use generic parameters from outer item
fn hd<U>(v: Vec<U> ) -> U {
fn hd1(w: [U]) -> U { return w[0]; }
//~^ ERROR can't use generic parameters from outer item
diff --git a/tests/ui/nested-ty-params.stderr b/tests/ui/nested-ty-params.stderr
index a9cdec6..7ca65b4 100644
--- a/tests/ui/nested-ty-params.stderr
+++ b/tests/ui/nested-ty-params.stderr
@@ -1,5 +1,5 @@
error[E0401]: can't use generic parameters from outer item
- --> $DIR/nested-ty-params.rs:3:16
+ --> $DIR/nested-ty-params.rs:2:16
|
LL | fn hd<U>(v: Vec<U> ) -> U {
| - type parameter from outer item
@@ -9,7 +9,7 @@
| help: try introducing a local generic parameter here: `<U>`
error[E0401]: can't use generic parameters from outer item
- --> $DIR/nested-ty-params.rs:3:23
+ --> $DIR/nested-ty-params.rs:2:23
|
LL | fn hd<U>(v: Vec<U> ) -> U {
| - type parameter from outer item
diff --git a/tests/ui/no_std/no-std-no-start-binary.rs b/tests/ui/no_std/no-std-no-start-binary.rs
index df68b99..6853e2d 100644
--- a/tests/ui/no_std/no-std-no-start-binary.rs
+++ b/tests/ui/no_std/no-std-no-start-binary.rs
@@ -1,5 +1,4 @@
//@ compile-flags: -Cpanic=abort --emit link
-//@ error-pattern:using `fn main` requires the standard library
// Make sure that we don't emit an error message mentioning internal lang items.
diff --git a/tests/ui/non_modrs_mods/foors_mod.rs b/tests/ui/non_modrs_mods/foors_mod.rs
index b215e5f..dfaa11b 100644
--- a/tests/ui/non_modrs_mods/foors_mod.rs
+++ b/tests/ui/non_modrs_mods/foors_mod.rs
@@ -1,6 +1,4 @@
-//@ run-pass
-//
-//@ ignore-test: not a test, used by non_modrs_mods.rs
+//@ ignore-auxiliary (used by `./non_modrs_mods.rs`)
pub mod inner_modrs_mod;
pub mod inner_foors_mod;
diff --git a/tests/ui/non_modrs_mods_and_inline_mods/x.rs b/tests/ui/non_modrs_mods_and_inline_mods/x.rs
index c4548d3..38ff011 100644
--- a/tests/ui/non_modrs_mods_and_inline_mods/x.rs
+++ b/tests/ui/non_modrs_mods_and_inline_mods/x.rs
@@ -1,4 +1,4 @@
-//@ ignore-test: not a test
+//@ ignore-auxiliary (used by `./non_modrs_mods_and_inline_mods.rs`)
pub mod y {
pub mod z;
diff --git a/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs
index ec7b7de..cac5e27 100644
--- a/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs
+++ b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs
@@ -1 +1 @@
-//@ ignore-test: not a test
+//@ ignore-auxiliary (used by `../../../non_modrs_mods_and_inline_mods.rs`)
diff --git a/tests/ui/numbers-arithmetic/int.rs b/tests/ui/numbers-arithmetic/int.rs
deleted file mode 100644
index 42f8e50..0000000
--- a/tests/ui/numbers-arithmetic/int.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//@ run-pass
-
-
-
-
-pub fn main() { let _x: isize = 10; }
diff --git a/tests/ui/numbers-arithmetic/isize-base.rs b/tests/ui/numbers-arithmetic/isize-base.rs
new file mode 100644
index 0000000..412e7ac
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/isize-base.rs
@@ -0,0 +1,25 @@
+//! Tests basic `isize` functionality
+
+//@ run-pass
+
+pub fn main() {
+ // Literal matches assignment type
+ let a: isize = 42isize;
+ // Literal cast
+ let b: isize = 42 as isize;
+ // Literal type inference from assignment type
+ let c: isize = 42;
+ // Assignment type inference from literal (and later comparison)
+ let d = 42isize;
+ // Function return value type inference
+ let e = return_val();
+
+ assert_eq!(a, b);
+ assert_eq!(a, c);
+ assert_eq!(a, d);
+ assert_eq!(a, e);
+}
+
+fn return_val() -> isize {
+ 42
+}
diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs
index 4b176ef..4e578f6 100644
--- a/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs
+++ b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `./saturating-float-casts.rs` and `./saturating-float-casts-wasm.rs`)
// Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction.
//
diff --git a/tests/ui/numbers-arithmetic/uint.rs b/tests/ui/numbers-arithmetic/uint.rs
deleted file mode 100644
index c2087b5..0000000
--- a/tests/ui/numbers-arithmetic/uint.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//@ run-pass
-
-
-
-
-pub fn main() { let _x: usize = 10 as usize; }
diff --git a/tests/ui/numbers-arithmetic/usize-base.rs b/tests/ui/numbers-arithmetic/usize-base.rs
new file mode 100644
index 0000000..833fc04
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/usize-base.rs
@@ -0,0 +1,25 @@
+//! Tests basic `usize` functionality
+
+//@ run-pass
+
+pub fn main() {
+ // Literal matches assignment type
+ let a: usize = 42usize;
+ // Literal cast
+ let b: usize = 42 as usize;
+ // Literal type inference from assignment type
+ let c: usize = 42;
+ // Assignment type inference from literal (and later comparison)
+ let d = 42usize;
+ // Function return value type inference
+ let e = return_val();
+
+ assert_eq!(a, b);
+ assert_eq!(a, c);
+ assert_eq!(a, d);
+ assert_eq!(a, e);
+}
+
+fn return_val() -> usize {
+ 42
+}
diff --git a/tests/ui/optimization-remark.rs b/tests/ui/optimization-remark.rs
index ebcf3b4..165fc63c 100644
--- a/tests/ui/optimization-remark.rs
+++ b/tests/ui/optimization-remark.rs
@@ -12,9 +12,8 @@
//
//@ [merge1] compile-flags: -Cremark=all -Cremark=giraffe
//@ [merge2] compile-flags: -Cremark=inline -Cremark=giraffe
-//
-//@ error-pattern: inline (missed): 'f' not inlined into 'g'
//@ dont-check-compiler-stderr
+//@ dont-require-annotations: NOTE
#[no_mangle]
#[inline(never)]
@@ -25,3 +24,5 @@ pub fn f() {
pub fn g() {
f();
}
+
+//~? NOTE inline (missed): 'f' not inlined into 'g'
diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.fixed b/tests/ui/or-patterns/fn-param-wrap-parens.fixed
index 7b0bbd0..fbf6006 100644
--- a/tests/ui/or-patterns/fn-param-wrap-parens.fixed
+++ b/tests/ui/or-patterns/fn-param-wrap-parens.fixed
@@ -9,5 +9,5 @@
enum E { A, B }
use E::*;
-#[cfg(FALSE)]
+#[cfg(false)]
fn fun1((A | B): E) {} //~ ERROR top-level or-patterns are not allowed
diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.rs b/tests/ui/or-patterns/fn-param-wrap-parens.rs
index dadbb8a..d796f99 100644
--- a/tests/ui/or-patterns/fn-param-wrap-parens.rs
+++ b/tests/ui/or-patterns/fn-param-wrap-parens.rs
@@ -9,5 +9,5 @@ fn main() {}
enum E { A, B }
use E::*;
-#[cfg(FALSE)]
+#[cfg(false)]
fn fun1(A | B: E) {} //~ ERROR top-level or-patterns are not allowed
diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr
index 5608138..74e4cea 100644
--- a/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr
+++ b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr
@@ -6,7 +6,6 @@
| |
| while parsing the body of this closure
|
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: you might have meant to open the body of the closure
|
LL | let _ = |A | { B: E| ();
diff --git a/tests/ui/or-patterns/or-patterns-syntactic-pass.rs b/tests/ui/or-patterns/or-patterns-syntactic-pass.rs
index 6a8d0a5..6fd5840 100644
--- a/tests/ui/or-patterns/or-patterns-syntactic-pass.rs
+++ b/tests/ui/or-patterns/or-patterns-syntactic-pass.rs
@@ -18,7 +18,7 @@ macro_rules! accept_pat {
// Non-macro tests:
-#[cfg(FALSE)]
+#[cfg(false)]
fn or_patterns() {
// Top level of `let`:
let (| A | B);
diff --git a/tests/ui/or-patterns/remove-leading-vert.fixed b/tests/ui/or-patterns/remove-leading-vert.fixed
index 3ec815c..136ca57 100644
--- a/tests/ui/or-patterns/remove-leading-vert.fixed
+++ b/tests/ui/or-patterns/remove-leading-vert.fixed
@@ -6,7 +6,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn leading() {
fn fun1( A: E) {} //~ ERROR top-level or-patterns are not allowed
fn fun2( A: E) {} //~ ERROR unexpected `||` before function parameter
@@ -21,7 +21,7 @@
let NS { f: | A }: NS; //~ ERROR unexpected token `||` in pattern
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn trailing() {
let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
let (a ,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern
diff --git a/tests/ui/or-patterns/remove-leading-vert.rs b/tests/ui/or-patterns/remove-leading-vert.rs
index 2aeeb0e..d9e9c9f 100644
--- a/tests/ui/or-patterns/remove-leading-vert.rs
+++ b/tests/ui/or-patterns/remove-leading-vert.rs
@@ -6,7 +6,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn leading() {
fn fun1( | A: E) {} //~ ERROR top-level or-patterns are not allowed
fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter
@@ -21,7 +21,7 @@ fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter
let NS { f: || A }: NS; //~ ERROR unexpected token `||` in pattern
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn trailing() {
let ( A | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
let (a |,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern
diff --git a/tests/ui/packed/packed-struct-generic-transmute.rs b/tests/ui/packed/packed-struct-generic-transmute.rs
index 17e72be..6697263 100644
--- a/tests/ui/packed/packed-struct-generic-transmute.rs
+++ b/tests/ui/packed/packed-struct-generic-transmute.rs
@@ -3,8 +3,6 @@
// the error points to the start of the file, not the line with the
// transmute
-//@ error-pattern: cannot transmute between types of different sizes, or dependently-sized types
-
use std::mem;
#[repr(packed)]
diff --git a/tests/ui/packed/packed-struct-generic-transmute.stderr b/tests/ui/packed/packed-struct-generic-transmute.stderr
index e91f498..983742b 100644
--- a/tests/ui/packed/packed-struct-generic-transmute.stderr
+++ b/tests/ui/packed/packed-struct-generic-transmute.stderr
@@ -1,5 +1,5 @@
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
- --> $DIR/packed-struct-generic-transmute.rs:24:38
+ --> $DIR/packed-struct-generic-transmute.rs:22:38
|
LL | let oof: Oof<[u8; 5], i32> = mem::transmute(foo);
| ^^^^^^^^^^^^^^
diff --git a/tests/ui/packed/packed-struct-transmute.rs b/tests/ui/packed/packed-struct-transmute.rs
index 5ad6524..24ac1f4 100644
--- a/tests/ui/packed/packed-struct-transmute.rs
+++ b/tests/ui/packed/packed-struct-transmute.rs
@@ -4,7 +4,6 @@
// transmute
//@ normalize-stderr: "\d+ bits" -> "N bits"
-//@ error-pattern: cannot transmute between types of different sizes, or dependently-sized types
use std::mem;
diff --git a/tests/ui/packed/packed-struct-transmute.stderr b/tests/ui/packed/packed-struct-transmute.stderr
index 4d75820..c5f556f 100644
--- a/tests/ui/packed/packed-struct-transmute.stderr
+++ b/tests/ui/packed/packed-struct-transmute.stderr
@@ -1,5 +1,5 @@
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
- --> $DIR/packed-struct-transmute.rs:26:24
+ --> $DIR/packed-struct-transmute.rs:25:24
|
LL | let oof: Oof = mem::transmute(foo);
| ^^^^^^^^^^^^^^
diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs
index 7add07e..80591ed 100644
--- a/tests/ui/panic-runtime/two-panic-runtimes.rs
+++ b/tests/ui/panic-runtime/two-panic-runtimes.rs
@@ -1,6 +1,6 @@
// ignore-tidy-linelength
//@ build-fail
-//@ dont-require-annotations:ERROR
+//@ dont-require-annotations: ERROR
//@ dont-check-compiler-stderr
//@ aux-build:panic-runtime-unwind.rs
//@ aux-build:panic-runtime-unwind2.rs
diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs
index 1ae2e62..42cdf8b 100644
--- a/tests/ui/panic-runtime/want-abort-got-unwind.rs
+++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs
@@ -1,6 +1,6 @@
// ignore-tidy-linelength
//@ build-fail
-//@ dont-require-annotations:ERROR
+//@ dont-require-annotations: ERROR
//@ dont-check-compiler-stderr
//@ aux-build:panic-runtime-unwind.rs
//@ compile-flags:-C panic=abort
diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs
index dc4d3ea..ddf12cd 100644
--- a/tests/ui/panic-runtime/want-abort-got-unwind2.rs
+++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs
@@ -1,6 +1,6 @@
// ignore-tidy-linelength
//@ build-fail
-//@ dont-require-annotations:ERROR
+//@ dont-require-annotations: ERROR
//@ dont-check-compiler-stderr
//@ aux-build:panic-runtime-unwind.rs
//@ aux-build:wants-panic-runtime-unwind.rs
diff --git a/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs b/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs
index 6c04537..63c567b 100644
--- a/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs
+++ b/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs
@@ -4,7 +4,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
const _: () = {
pub trait A {
const _: () = ();
diff --git a/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs b/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs
index 492f2ea..e875d73 100644
--- a/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs
+++ b/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
impl S {
static IA: u8 = 0; //~ ERROR associated `static` items are not allowed
static IB: u8; //~ ERROR associated `static` items are not allowed
@@ -12,7 +12,7 @@ impl S {
//~^ ERROR a static item cannot be `default`
}
-#[cfg(FALSE)]
+#[cfg(false)]
trait T {
static TA: u8 = 0; //~ ERROR associated `static` items are not allowed
static TB: u8; //~ ERROR associated `static` items are not allowed
@@ -22,7 +22,7 @@ trait T {
//~^ ERROR a static item cannot be `default`
}
-#[cfg(FALSE)]
+#[cfg(false)]
impl T for S {
static TA: u8 = 0; //~ ERROR associated `static` items are not allowed
static TB: u8; //~ ERROR associated `static` items are not allowed
diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
index 26761a1..1380974 100644
--- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
+++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
@@ -1,108 +1,108 @@
fn main() {}
-#[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
+#[cfg(false)] fn e() { let _ = [#[attr]]; }
//~^ ERROR expected expression, found `]`
-#[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
+#[cfg(false)] fn e() { let _ = foo#[attr](); }
//~^ ERROR expected one of
-#[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+#[cfg(false)] fn e() { let _ = foo(#![attr]); }
//~^ ERROR an inner attribute is not permitted in this context
//~| ERROR an inner attribute is not permitted in this context
//~| ERROR expected expression, found `)`
-#[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+#[cfg(false)] fn e() { let _ = x.foo(#![attr]); }
//~^ ERROR an inner attribute is not permitted in this context
//~| ERROR expected expression, found `)`
-#[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
+#[cfg(false)] fn e() { let _ = 0 + #![attr] 0; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
+#[cfg(false)] fn e() { let _ = !#![attr] 0; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
+#[cfg(false)] fn e() { let _ = -#![attr] 0; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
+#[cfg(false)] fn e() { let _ = x #![attr] as Y; }
//~^ ERROR expected one of
-#[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
+#[cfg(false)] fn e() { let _ = || #![attr] foo; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
+#[cfg(false)] fn e() { let _ = move || #![attr] foo; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
+#[cfg(false)] fn e() { let _ = || #![attr] {foo}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
+#[cfg(false)] fn e() { let _ = move || #![attr] {foo}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
+#[cfg(false)] fn e() { let _ = #[attr] ..#[attr] 0; }
//~^ ERROR attributes are not allowed on range expressions starting with `..`
-#[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
+#[cfg(false)] fn e() { let _ = #[attr] ..; }
//~^ ERROR attributes are not allowed on range expressions starting with `..`
-#[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
+#[cfg(false)] fn e() { let _ = #[attr] &#![attr] 0; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
+#[cfg(false)] fn e() { let _ = #[attr] &mut #![attr] 0; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
+#[cfg(false)] fn e() { let _ = if 0 #[attr] {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
+#[cfg(false)] fn e() { let _ = if 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
+#[cfg(false)] fn e() { let _ = if 0 {} #[attr] else {}; }
//~^ ERROR expected one of
-#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
+#[cfg(false)] fn e() { let _ = if 0 {} else #[attr] {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
+#[cfg(false)] fn e() { let _ = if 0 {} else {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+#[cfg(false)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
+#[cfg(false)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
+#[cfg(false)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 #[attr] {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
//~^ ERROR expected one of
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
//~^ ERROR outer attributes are not allowed on `if`
-#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
+#[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
//~^ ERROR an inner attribute is not permitted in this context
-#[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
+#[cfg(false)] fn s() { #[attr] #![attr] let _ = 0; }
//~^ ERROR an inner attribute is not permitted following an outer attribute
-#[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
+#[cfg(false)] fn s() { #[attr] #![attr] 0; }
//~^ ERROR an inner attribute is not permitted following an outer attribute
-#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+#[cfg(false)] fn s() { #[attr] #![attr] foo!(); }
//~^ ERROR an inner attribute is not permitted following an outer attribute
-#[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+#[cfg(false)] fn s() { #[attr] #![attr] foo![]; }
//~^ ERROR an inner attribute is not permitted following an outer attribute
-#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+#[cfg(false)] fn s() { #[attr] #![attr] foo!{}; }
//~^ ERROR an inner attribute is not permitted following an outer attribute
// FIXME: Allow attributes in pattern constexprs?
// note: requires parens in patterns to allow disambiguation
-#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+#[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } }
//~^ ERROR inclusive range with no end
//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
-#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+#[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } }
//~^ ERROR inclusive range with no end
//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
-#[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
+#[cfg(false)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
//~^ ERROR unexpected token: `#`
-#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+#[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } }
//~^ ERROR inclusive range with no end
//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
-#[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
+#[cfg(false)] fn e() { let _ = x.#![attr]foo(); }
//~^ ERROR unexpected token: `#`
//~| ERROR expected one of `.`
-#[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
+#[cfg(false)] fn e() { let _ = x.#[attr]foo(); }
//~^ ERROR unexpected token: `#`
//~| ERROR expected one of `.`
// make sure we don't catch this bug again...
-#[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
+#[cfg(false)] fn e() { { fn foo() { #[attr]; } } }
//~^ ERROR expected statement after outer attribute
-#[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
+#[cfg(false)] fn e() { { fn foo() { #[attr] } } }
//~^ ERROR expected statement after outer attribute
diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
index bd86084..5d94a8d 100644
--- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
+++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
@@ -1,19 +1,19 @@
error: expected expression, found `]`
--> $DIR/attr-stmt-expr-attr-bad.rs:3:40
|
-LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
+LL | #[cfg(false)] fn e() { let _ = [#[attr]]; }
| ^ expected expression
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:5:35
|
-LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
+LL | #[cfg(false)] fn e() { let _ = foo#[attr](); }
| ^ expected one of 8 possible tokens
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:7:36
|
-LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+LL | #[cfg(false)] fn e() { let _ = foo(#![attr]); }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -22,7 +22,7 @@
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:7:36
|
-LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+LL | #[cfg(false)] fn e() { let _ = foo(#![attr]); }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -32,13 +32,13 @@
error: expected expression, found `)`
--> $DIR/attr-stmt-expr-attr-bad.rs:7:44
|
-LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
+LL | #[cfg(false)] fn e() { let _ = foo(#![attr]); }
| ^ expected expression
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:11:38
|
-LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+LL | #[cfg(false)] fn e() { let _ = x.foo(#![attr]); }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -47,13 +47,13 @@
error: expected expression, found `)`
--> $DIR/attr-stmt-expr-attr-bad.rs:11:46
|
-LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
+LL | #[cfg(false)] fn e() { let _ = x.foo(#![attr]); }
| ^ expected expression
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:14:36
|
-LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
+LL | #[cfg(false)] fn e() { let _ = 0 + #![attr] 0; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -62,7 +62,7 @@
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:16:33
|
-LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
+LL | #[cfg(false)] fn e() { let _ = !#![attr] 0; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -71,7 +71,7 @@
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:18:33
|
-LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
+LL | #[cfg(false)] fn e() { let _ = -#![attr] 0; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -80,13 +80,13 @@
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:20:34
|
-LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
+LL | #[cfg(false)] fn e() { let _ = x #![attr] as Y; }
| ^ expected one of 8 possible tokens
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:22:35
|
-LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
+LL | #[cfg(false)] fn e() { let _ = || #![attr] foo; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -95,7 +95,7 @@
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:24:40
|
-LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
+LL | #[cfg(false)] fn e() { let _ = move || #![attr] foo; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -104,7 +104,7 @@
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:26:35
|
-LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
+LL | #[cfg(false)] fn e() { let _ = || #![attr] {foo}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -113,7 +113,7 @@
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:28:40
|
-LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
+LL | #[cfg(false)] fn e() { let _ = move || #![attr] {foo}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -122,19 +122,19 @@
error: attributes are not allowed on range expressions starting with `..`
--> $DIR/attr-stmt-expr-attr-bad.rs:30:40
|
-LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
+LL | #[cfg(false)] fn e() { let _ = #[attr] ..#[attr] 0; }
| ^^
error: attributes are not allowed on range expressions starting with `..`
--> $DIR/attr-stmt-expr-attr-bad.rs:32:40
|
-LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
+LL | #[cfg(false)] fn e() { let _ = #[attr] ..; }
| ^^
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:34:41
|
-LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
+LL | #[cfg(false)] fn e() { let _ = #[attr] &#![attr] 0; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -143,7 +143,7 @@
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:36:45
|
-LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
+LL | #[cfg(false)] fn e() { let _ = #[attr] &mut #![attr] 0; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -152,21 +152,21 @@
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:38:37
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
| |
| the branch belongs to this `if`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if 0 {}; }
+LL - #[cfg(false)] fn e() { let _ = if 0 #[attr] {}; }
+LL + #[cfg(false)] fn e() { let _ = if 0 {}; }
|
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:40:38
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 {#![attr]}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -175,27 +175,27 @@
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:42:40
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 {} #[attr] else {}; }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:44:45
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] {}; }
| ---- ^^^^^^^ -- the attributes are attached to this branch
| |
| the branch belongs to this `else`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if 0 {} else {}; }
+LL - #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] {}; }
+LL + #[cfg(false)] fn e() { let _ = if 0 {} else {}; }
|
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:46:46
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 {} else {#![attr]}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -204,35 +204,35 @@
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:48:45
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
| ---- ^^^^^^^ ------- the attributes are attached to this branch
| |
| the branch belongs to this `else`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {}; }
+LL - #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
+LL + #[cfg(false)] fn e() { let _ = if 0 {} else if 0 {}; }
|
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:50:50
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
| |
| the branch belongs to this `if`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {}; }
+LL - #[cfg(false)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
+LL + #[cfg(false)] fn e() { let _ = if 0 {} else if 0 {}; }
|
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:52:51
|
-LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
+LL | #[cfg(false)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -241,21 +241,21 @@
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:54:45
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
| |
| the branch belongs to this `if`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {}; }
+LL - #[cfg(false)] fn e() { let _ = if let _ = 0 #[attr] {}; }
+LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {}; }
|
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:56:46
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {#![attr]}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -264,27 +264,27 @@
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:58:48
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:60:53
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
| ---- ^^^^^^^ -- the attributes are attached to this branch
| |
| the branch belongs to this `else`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {}; }
+LL - #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
+LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {} else {}; }
|
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:62:54
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -293,35 +293,35 @@
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:64:53
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
| ---- ^^^^^^^ --------------- the attributes are attached to this branch
| |
| the branch belongs to this `else`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; }
+LL - #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
+LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; }
|
error: outer attributes are not allowed on `if` and `else` branches
--> $DIR/attr-stmt-expr-attr-bad.rs:66:66
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
| |
| the branch belongs to this `if`
|
help: remove the attributes
|
-LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
-LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; }
+LL - #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
+LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; }
|
error: an inner attribute is not permitted in this context
--> $DIR/attr-stmt-expr-attr-bad.rs:68:67
|
-LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
+LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
| ^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
@@ -330,7 +330,7 @@
error: an inner attribute is not permitted following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:71:32
|
-LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
+LL | #[cfg(false)] fn s() { #[attr] #![attr] let _ = 0; }
| ------- ^^^^^^^^ not permitted following an outer attribute
| |
| previous outer attribute
@@ -341,7 +341,7 @@
error: an inner attribute is not permitted following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:73:32
|
-LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
+LL | #[cfg(false)] fn s() { #[attr] #![attr] 0; }
| ------- ^^^^^^^^ not permitted following an outer attribute
| |
| previous outer attribute
@@ -352,7 +352,7 @@
error: an inner attribute is not permitted following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:75:32
|
-LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+LL | #[cfg(false)] fn s() { #[attr] #![attr] foo!(); }
| ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
| | |
| | not permitted following an outer attribute
@@ -363,7 +363,7 @@
error: an inner attribute is not permitted following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:77:32
|
-LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+LL | #[cfg(false)] fn s() { #[attr] #![attr] foo![]; }
| ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
| | |
| | not permitted following an outer attribute
@@ -374,7 +374,7 @@
error: an inner attribute is not permitted following an outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:79:32
|
-LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+LL | #[cfg(false)] fn s() { #[attr] #![attr] foo!{}; }
| ------- ^^^^^^^^ ------ the inner attribute doesn't annotate this item macro invocation
| | |
| | not permitted following an outer attribute
@@ -385,100 +385,100 @@
error[E0586]: inclusive range with no end
--> $DIR/attr-stmt-expr-attr-bad.rs:85:35
|
-LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } }
| ^^^
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
help: use `..` instead
|
-LL - #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-LL + #[cfg(FALSE)] fn e() { match 0 { 0..#[attr] 10 => () } }
+LL - #[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+LL + #[cfg(false)] fn e() { match 0 { 0..#[attr] 10 => () } }
|
error: expected one of `=>`, `if`, or `|`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:85:38
|
-LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
+LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } }
| ^ expected one of `=>`, `if`, or `|`
error[E0586]: inclusive range with no end
--> $DIR/attr-stmt-expr-attr-bad.rs:88:35
|
-LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } }
| ^^^
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
help: use `..` instead
|
-LL - #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-LL + #[cfg(FALSE)] fn e() { match 0 { 0..#[attr] -10 => () } }
+LL - #[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+LL + #[cfg(false)] fn e() { match 0 { 0..#[attr] -10 => () } }
|
error: expected one of `=>`, `if`, or `|`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:88:38
|
-LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
+LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } }
| ^ expected one of `=>`, `if`, or `|`
error: unexpected token: `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:91:39
|
-LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
+LL | #[cfg(false)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
| ^
error[E0586]: inclusive range with no end
--> $DIR/attr-stmt-expr-attr-bad.rs:93:35
|
-LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } }
| ^^^
|
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
help: use `..` instead
|
-LL - #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-LL + #[cfg(FALSE)] fn e() { match 0 { 0..#[attr] FOO => () } }
+LL - #[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+LL + #[cfg(false)] fn e() { match 0 { 0..#[attr] FOO => () } }
|
error: expected one of `=>`, `if`, or `|`, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:93:38
|
-LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
+LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } }
| ^ expected one of `=>`, `if`, or `|`
error: unexpected token: `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:97:34
|
-LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
+LL | #[cfg(false)] fn e() { let _ = x.#![attr]foo(); }
| ^
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:97:34
|
-LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
+LL | #[cfg(false)] fn e() { let _ = x.#![attr]foo(); }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: unexpected token: `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:100:34
|
-LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
+LL | #[cfg(false)] fn e() { let _ = x.#[attr]foo(); }
| ^
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
--> $DIR/attr-stmt-expr-attr-bad.rs:100:34
|
-LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
+LL | #[cfg(false)] fn e() { let _ = x.#[attr]foo(); }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: expected statement after outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:105:37
|
-LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
+LL | #[cfg(false)] fn e() { { fn foo() { #[attr]; } } }
| ^^^^^^^
error: expected statement after outer attribute
--> $DIR/attr-stmt-expr-attr-bad.rs:107:37
|
-LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
+LL | #[cfg(false)] fn e() { { fn foo() { #[attr] } } }
| ^^^^^^^
error: aborting due to 53 previous errors
diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
index 33671df..371f19d 100644
--- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
+++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs
@@ -1,7 +1,7 @@
#![feature(stmt_expr_attributes)]
fn foo() -> String {
- #[cfg(FALSE)]
+ #[cfg(false)]
[1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() //~ ERROR expected `;`, found `#`
#[cfg(not(FALSE))]
String::new()
diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
index 6266718..3a97a14 100644
--- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
+++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr
@@ -1,7 +1,7 @@
error: expected `;`, found `#`
--> $DIR/multiple-tail-expr-behind-cfg.rs:5:64
|
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| ------------- only `;` terminated statements or tail expressions are allowed after this attribute
LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>()
| ^ expected `;` here
@@ -18,7 +18,7 @@
| + +
help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)`
|
-LL ~ if cfg!(FALSE) {
+LL ~ if cfg!(false) {
LL ~ [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>()
LL ~ } else if cfg!(not(FALSE)) {
LL ~ String::new()
diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs
index e2a6292..1cd3f13 100644
--- a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs
+++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs
@@ -5,7 +5,7 @@ macro_rules! the_macro {
#[cfg()]
$foo //~ ERROR expected `;`, found `#`
- #[cfg(FALSE)]
+ #[cfg(false)]
$bar
};
}
diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr
index fa4409f..41e7b5a 100644
--- a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr
+++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr
@@ -6,7 +6,7 @@
LL | $foo
| ^ expected `;` here
LL |
-LL | #[cfg(FALSE)]
+LL | #[cfg(false)]
| - unexpected token
...
LL | the_macro!( (); (); );
diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr
index d6b50b0..86ef35b 100644
--- a/tests/ui/parser/bad-lit-suffixes.stderr
+++ b/tests/ui/parser/bad-lit-suffixes.stderr
@@ -51,7 +51,7 @@
|
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
-warning: extern declarations without an explicit ABI are deprecated
+warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/bad-lit-suffixes.rs:3:1
|
LL | extern
@@ -59,7 +59,7 @@
|
= note: `#[warn(missing_abi)]` on by default
-warning: extern declarations without an explicit ABI are deprecated
+warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/bad-lit-suffixes.rs:7:1
|
LL | extern
diff --git a/tests/ui/parser/circular_modules_hello.rs b/tests/ui/parser/circular_modules_hello.rs
index eb0284d..540752e 100644
--- a/tests/ui/parser/circular_modules_hello.rs
+++ b/tests/ui/parser/circular_modules_hello.rs
@@ -1,4 +1,4 @@
-//@ ignore-test: this is an auxiliary file for circular-modules-main.rs
+//@ ignore-auxiliary (used by `./circular-modules-main.rs`)
#[path = "circular_modules_main.rs"]
mod circular_modules_main;
diff --git a/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs
index ed3ffed..acc58a4 100644
--- a/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs
+++ b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs
@@ -1,6 +1,6 @@
//@ check-pass
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
foo::<T = u8, T: Ord, String>();
foo::<T = u8, 'a, T: Ord>();
diff --git a/tests/ui/parser/default-on-wrong-item-kind.rs b/tests/ui/parser/default-on-wrong-item-kind.rs
index 98a95cf..da990a4 100644
--- a/tests/ui/parser/default-on-wrong-item-kind.rs
+++ b/tests/ui/parser/default-on-wrong-item-kind.rs
@@ -4,7 +4,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
mod free_items {
default extern crate foo; //~ ERROR an extern crate cannot be `default`
default use foo; //~ ERROR a `use` import cannot be `default`
@@ -28,7 +28,7 @@ mod free_items {
default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" {
default extern crate foo; //~ ERROR an extern crate cannot be `default`
//~^ ERROR extern crate is not supported in `extern` blocks
@@ -65,7 +65,7 @@ mod free_items {
//~^ ERROR macro definition is not supported in `extern` blocks
}
-#[cfg(FALSE)]
+#[cfg(false)]
impl S {
default extern crate foo; //~ ERROR an extern crate cannot be `default`
//~^ ERROR extern crate is not supported in `trait`s or `impl`s
@@ -102,7 +102,7 @@ impl S {
//~^ ERROR macro definition is not supported in `trait`s or `impl`s
}
-#[cfg(FALSE)]
+#[cfg(false)]
trait T {
default extern crate foo; //~ ERROR an extern crate cannot be `default`
//~^ ERROR extern crate is not supported in `trait`s or `impl`s
diff --git a/tests/ui/parser/extern-abi-syntactic.rs b/tests/ui/parser/extern-abi-syntactic.rs
index d3e2ba0..28565a3 100644
--- a/tests/ui/parser/extern-abi-syntactic.rs
+++ b/tests/ui/parser/extern-abi-syntactic.rs
@@ -5,13 +5,13 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn foo() {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "some_abi_that_we_are_sure_does_not_exist_semantically" {
fn foo();
}
-#[cfg(FALSE)]
+#[cfg(false)]
type T = extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn();
diff --git a/tests/ui/parser/extern-crate-async.rs b/tests/ui/parser/extern-crate-async.rs
index 7c77690..529e0f1 100644
--- a/tests/ui/parser/extern-crate-async.rs
+++ b/tests/ui/parser/extern-crate-async.rs
@@ -5,8 +5,8 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern crate async;
-#[cfg(FALSE)]
+#[cfg(false)]
extern crate async as something_else;
diff --git a/tests/ui/parser/fn-body-optional-syntactic-pass.rs b/tests/ui/parser/fn-body-optional-syntactic-pass.rs
index 140471d..762247e6 100644
--- a/tests/ui/parser/fn-body-optional-syntactic-pass.rs
+++ b/tests/ui/parser/fn-body-optional-syntactic-pass.rs
@@ -4,7 +4,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
fn f();
fn f() {}
diff --git a/tests/ui/parser/fn-header-syntactic-pass.rs b/tests/ui/parser/fn-header-syntactic-pass.rs
index 065ded3..1e15886 100644
--- a/tests/ui/parser/fn-header-syntactic-pass.rs
+++ b/tests/ui/parser/fn-header-syntactic-pass.rs
@@ -5,7 +5,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
async fn f();
unsafe fn f();
diff --git a/tests/ui/parser/foreign-const-syntactic-fail.rs b/tests/ui/parser/foreign-const-syntactic-fail.rs
index a6e77f8..fc3cd0b 100644
--- a/tests/ui/parser/foreign-const-syntactic-fail.rs
+++ b/tests/ui/parser/foreign-const-syntactic-fail.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" {
const A: isize; //~ ERROR extern items cannot be `const`
const B: isize = 42; //~ ERROR extern items cannot be `const`
diff --git a/tests/ui/parser/foreign-static-syntactic-pass.rs b/tests/ui/parser/foreign-static-syntactic-pass.rs
index a76b9ba..d7c21c6 100644
--- a/tests/ui/parser/foreign-static-syntactic-pass.rs
+++ b/tests/ui/parser/foreign-static-syntactic-pass.rs
@@ -4,7 +4,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" {
static X: u8;
static mut Y: u8;
diff --git a/tests/ui/parser/foreign-ty-syntactic-pass.rs b/tests/ui/parser/foreign-ty-syntactic-pass.rs
index 50bb68c..3372768 100644
--- a/tests/ui/parser/foreign-ty-syntactic-pass.rs
+++ b/tests/ui/parser/foreign-ty-syntactic-pass.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" {
type A: Ord;
type A<'a> where 'a: 'static;
diff --git a/tests/ui/parser/impl-item-const-pass.rs b/tests/ui/parser/impl-item-const-pass.rs
index 8ebdf63..6ca4cd9 100644
--- a/tests/ui/parser/impl-item-const-pass.rs
+++ b/tests/ui/parser/impl-item-const-pass.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
impl X {
const Y: u8;
}
diff --git a/tests/ui/parser/impl-item-fn-no-body-pass.rs b/tests/ui/parser/impl-item-fn-no-body-pass.rs
index 5a593fe..b8269fc 100644
--- a/tests/ui/parser/impl-item-fn-no-body-pass.rs
+++ b/tests/ui/parser/impl-item-fn-no-body-pass.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
impl X {
fn f();
}
diff --git a/tests/ui/parser/impl-item-type-no-body-pass.rs b/tests/ui/parser/impl-item-type-no-body-pass.rs
index 039825b..979b5f7 100644
--- a/tests/ui/parser/impl-item-type-no-body-pass.rs
+++ b/tests/ui/parser/impl-item-type-no-body-pass.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
impl X {
type Y;
type Z: Ord;
diff --git a/tests/ui/parser/inverted-parameters.rs b/tests/ui/parser/inverted-parameters.rs
index 5c42725..bc2f53f 100644
--- a/tests/ui/parser/inverted-parameters.rs
+++ b/tests/ui/parser/inverted-parameters.rs
@@ -1,3 +1,5 @@
+//@ dont-require-annotations: SUGGESTION
+
struct S;
impl S {
diff --git a/tests/ui/parser/inverted-parameters.stderr b/tests/ui/parser/inverted-parameters.stderr
index 8662277..7b96903 100644
--- a/tests/ui/parser/inverted-parameters.stderr
+++ b/tests/ui/parser/inverted-parameters.stderr
@@ -1,5 +1,5 @@
error: expected one of `:`, `@`, or `|`, found `bar`
- --> $DIR/inverted-parameters.rs:4:24
+ --> $DIR/inverted-parameters.rs:6:24
|
LL | fn foo(&self, &str bar) {}
| -----^^^
@@ -8,7 +8,7 @@
| help: declare the type after the parameter binding: `<identifier>: <type>`
error: expected one of `:`, `@`, or `|`, found `quux`
- --> $DIR/inverted-parameters.rs:10:10
+ --> $DIR/inverted-parameters.rs:12:10
|
LL | fn baz(S quux, xyzzy: i32) {}
| --^^^^
@@ -17,19 +17,19 @@
| help: declare the type after the parameter binding: `<identifier>: <type>`
error: expected one of `:`, `@`, or `|`, found `a`
- --> $DIR/inverted-parameters.rs:15:12
+ --> $DIR/inverted-parameters.rs:17:12
|
LL | fn one(i32 a b) {}
| ^ expected one of `:`, `@`, or `|`
error: expected one of `:` or `|`, found `(`
- --> $DIR/inverted-parameters.rs:18:23
+ --> $DIR/inverted-parameters.rs:20:23
|
LL | fn pattern((i32, i32) (a, b)) {}
| ^ expected one of `:` or `|`
error: expected one of `:`, `@`, or `|`, found `)`
- --> $DIR/inverted-parameters.rs:21:12
+ --> $DIR/inverted-parameters.rs:23:12
|
LL | fn fizz(i32) {}
| ^ expected one of `:`, `@`, or `|`
@@ -49,7 +49,7 @@
| ++
error: expected one of `:`, `@`, or `|`, found `S`
- --> $DIR/inverted-parameters.rs:27:23
+ --> $DIR/inverted-parameters.rs:29:23
|
LL | fn missing_colon(quux S) {}
| -----^
diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs
index 3d758be..2e9a15e 100644
--- a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs
+++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs
@@ -1,4 +1,4 @@
-//@ ignore-test: this is an auxiliary file for circular-module-with-doc-comment-issue-97589.rs
+//@ ignore-auxiliary (used by `./circular-module-with-doc-comment-issue-97589.rs`)
//! this comment caused the circular dependency checker to break
diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr
index e34371b..64cf8ba 100644
--- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr
+++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr
@@ -49,24 +49,18 @@
|
LL | let _ = 0i32: i32: i32.count_ones();
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: expected one of `!`, `(`, `.`, `::`, `;`, `<`, `?`, or `else`, found `:`
--> $DIR/issue-35813-postfix-after-cast.rs:43:21
|
LL | let _ = 0 as i32: i32.count_ones();
| ^ expected one of 8 possible tokens
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:`
--> $DIR/issue-35813-postfix-after-cast.rs:47:17
|
LL | let _ = 0i32: i32 as i32.count_ones();
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: cast cannot be followed by a method call
--> $DIR/issue-35813-postfix-after-cast.rs:51:13
@@ -84,16 +78,12 @@
|
LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones();
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:`
--> $DIR/issue-35813-postfix-after-cast.rs:60:17
|
LL | let _ = 0i32: i32.count_ones(): u32;
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: cast cannot be followed by a method call
--> $DIR/issue-35813-postfix-after-cast.rs:64:13
@@ -111,16 +101,12 @@
|
LL | let _ = 0 as i32.count_ones(): u32;
| ^ expected one of `.`, `;`, `?`, or `else`
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:`
--> $DIR/issue-35813-postfix-after-cast.rs:69:17
|
LL | let _ = 0i32: i32.count_ones() as u32;
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: cast cannot be followed by a method call
--> $DIR/issue-35813-postfix-after-cast.rs:73:13
@@ -138,8 +124,6 @@
|
LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32;
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: cast cannot be followed by a method call
--> $DIR/issue-35813-postfix-after-cast.rs:82:13
@@ -262,8 +246,6 @@
|
LL | drop_ptr: F();
| ^ expected identifier
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:`
--> $DIR/issue-35813-postfix-after-cast.rs:160:13
diff --git a/tests/ui/parser/issues/issue-48508-aux.rs b/tests/ui/parser/issues/issue-48508-aux.rs
index 0f2b442..0bf6490e 100644
--- a/tests/ui/parser/issues/issue-48508-aux.rs
+++ b/tests/ui/parser/issues/issue-48508-aux.rs
@@ -1,5 +1,4 @@
-//@ run-pass
-//@ ignore-test Not a test. Used by issue-48508.rs
+//@ ignore-auxiliary (used by `./issue-48508.rs`)
pub fn other() -> f64 {
let µ = 1.0;
diff --git a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs
index 4fa803b..13bb935 100644
--- a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs
+++ b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs
@@ -20,7 +20,7 @@ enum Enum {
mac_variant!(MARKER);
// We also accept visibilities on variants syntactically but not semantically.
-#[cfg(FALSE)]
+#[cfg(false)]
enum E {
pub U,
pub(crate) T(u8),
diff --git a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs
index cd474db..55e69cd 100644
--- a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs
+++ b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs
@@ -20,7 +20,7 @@ trait Alpha {
}
// We also accept visibilities on items in traits syntactically but not semantically.
-#[cfg(FALSE)]
+#[cfg(false)]
trait Foo {
pub fn bar();
pub(crate) type baz;
diff --git a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs
index cf754a6..782a46a 100644
--- a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs
+++ b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs
@@ -12,7 +12,7 @@ fn w<$lt>(w: &mut $lt i32) {}
// avoid false positives
fn y<'a>(y: &mut 'a + Send) {
- //~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a`
+ //~^ ERROR expected a path on the left-hand side of `+`
//~| ERROR at least one trait is required for an object type
let z = y as &mut 'a + Send;
//~^ ERROR expected value, found trait `Send`
diff --git a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr
index 6b8f8e4..ae1ed72 100644
--- a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr
+++ b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr
@@ -10,11 +10,11 @@
LL + fn x<'a>(x: &'a mut i32){}
|
-error[E0178]: expected a path on the left-hand side of `+`, not `&mut 'a`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/issue-73568-lifetime-after-mut.rs:14:13
|
LL | fn y<'a>(y: &mut 'a + Send) {
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try adding parentheses
|
diff --git a/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs b/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs
index 4edbee5..0b92298 100644
--- a/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs
+++ b/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs
@@ -4,5 +4,5 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
const X: u8;
diff --git a/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs b/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs
index df51926..8dae433 100644
--- a/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs
+++ b/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs
@@ -4,5 +4,5 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
static X: u8;
diff --git a/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs b/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs
index 80de3cf..8603dc3 100644
--- a/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs
+++ b/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
type A: Ord;
type B: Ord = u8;
diff --git a/tests/ui/parser/keyword-try-as-identifier-edition2018.rs b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs
index 27452f4..795f320 100644
--- a/tests/ui/parser/keyword-try-as-identifier-edition2018.rs
+++ b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
fn main() {
let try = "foo"; //~ error: expected identifier, found reserved keyword `try`
diff --git a/tests/ui/parser/lit-err-in-macro.stderr b/tests/ui/parser/lit-err-in-macro.stderr
index 9422f22..08fe586 100644
--- a/tests/ui/parser/lit-err-in-macro.stderr
+++ b/tests/ui/parser/lit-err-in-macro.stderr
@@ -4,7 +4,7 @@
LL | f!("Foo"__);
| ^^^^^^^ invalid suffix `__`
-warning: extern declarations without an explicit ABI are deprecated
+warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/lit-err-in-macro.rs:3:9
|
LL | extern $abi fn f() {}
diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.e2015.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.e2015.stderr
new file mode 100644
index 0000000..f2db351
--- /dev/null
+++ b/tests/ui/parser/macro/trait-object-macro-matcher.e2015.stderr
@@ -0,0 +1,32 @@
+error: lifetimes must be followed by `+` to form a trait object type
+ --> $DIR/trait-object-macro-matcher.rs:17:8
+ |
+LL | m!('static);
+ | ^^^^^^^
+ |
+help: consider adding a trait bound after the potential lifetime bound
+ |
+LL | m!('static + /* Trait */);
+ | +++++++++++++
+
+error: lifetimes must be followed by `+` to form a trait object type
+ --> $DIR/trait-object-macro-matcher.rs:17:8
+ |
+LL | m!('static);
+ | ^^^^^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider adding a trait bound after the potential lifetime bound
+ |
+LL | m!('static + /* Trait */);
+ | +++++++++++++
+
+error[E0224]: at least one trait is required for an object type
+ --> $DIR/trait-object-macro-matcher.rs:17:8
+ |
+LL | m!('static);
+ | ^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.e2021.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.e2021.stderr
new file mode 100644
index 0000000..7d9e8d7
--- /dev/null
+++ b/tests/ui/parser/macro/trait-object-macro-matcher.e2021.stderr
@@ -0,0 +1,16 @@
+error: expected type, found lifetime
+ --> $DIR/trait-object-macro-matcher.rs:17:8
+ |
+LL | m!('static);
+ | ^^^^^^^ expected type
+
+error: expected type, found lifetime
+ --> $DIR/trait-object-macro-matcher.rs:17:8
+ |
+LL | m!('static);
+ | ^^^^^^^ expected type
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.rs b/tests/ui/parser/macro/trait-object-macro-matcher.rs
index d4ec199..ba61752 100644
--- a/tests/ui/parser/macro/trait-object-macro-matcher.rs
+++ b/tests/ui/parser/macro/trait-object-macro-matcher.rs
@@ -1,6 +1,10 @@
// A single lifetime is not parsed as a type.
// `ty` matcher in particular doesn't accept a single lifetime
+//@ revisions: e2015 e2021
+//@[e2015] edition: 2015
+//@[e2021] edition: 2021
+
macro_rules! m {
($t: ty) => {
let _: $t;
@@ -8,8 +12,10 @@ macro_rules! m {
}
fn main() {
+ //[e2021]~vv ERROR expected type, found lifetime
+ //[e2021]~v ERROR expected type, found lifetime
m!('static);
- //~^ ERROR lifetime in trait object type must be followed by `+`
- //~| ERROR lifetime in trait object type must be followed by `+`
- //~| ERROR at least one trait is required for an object type
+ //[e2015]~^ ERROR lifetimes must be followed by `+` to form a trait object type
+ //[e2015]~| ERROR lifetimes must be followed by `+` to form a trait object type
+ //[e2015]~| ERROR at least one trait is required for an object type
}
diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.stderr
deleted file mode 100644
index 81dca6f..0000000
--- a/tests/ui/parser/macro/trait-object-macro-matcher.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error: lifetime in trait object type must be followed by `+`
- --> $DIR/trait-object-macro-matcher.rs:11:8
- |
-LL | m!('static);
- | ^^^^^^^
-
-error: lifetime in trait object type must be followed by `+`
- --> $DIR/trait-object-macro-matcher.rs:11:8
- |
-LL | m!('static);
- | ^^^^^^^
- |
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0224]: at least one trait is required for an object type
- --> $DIR/trait-object-macro-matcher.rs:11:8
- |
-LL | m!('static);
- | ^^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/parser/recover/raw-no-const-mut.rs b/tests/ui/parser/recover/raw-no-const-mut.rs
new file mode 100644
index 0000000..d0ae69c
--- /dev/null
+++ b/tests/ui/parser/recover/raw-no-const-mut.rs
@@ -0,0 +1,31 @@
+fn a() {
+ let x = &raw 1;
+ //~^ ERROR expected one of
+}
+
+fn b() {
+ [&raw const 1, &raw 2]
+ //~^ ERROR expected one of
+ //~| ERROR cannot find value `raw` in this scope
+ //~| ERROR cannot take address of a temporary
+}
+
+fn c() {
+ if x == &raw z {}
+ //~^ ERROR expected `{`
+}
+
+fn d() {
+ f(&raw 2);
+ //~^ ERROR expected one of
+ //~| ERROR cannot find value `raw` in this scope
+ //~| ERROR cannot find function `f` in this scope
+}
+
+fn e() {
+ let x;
+ x = &raw 1;
+ //~^ ERROR expected one of
+}
+
+fn main() {}
diff --git a/tests/ui/parser/recover/raw-no-const-mut.stderr b/tests/ui/parser/recover/raw-no-const-mut.stderr
new file mode 100644
index 0000000..65032c8
--- /dev/null
+++ b/tests/ui/parser/recover/raw-no-const-mut.stderr
@@ -0,0 +1,109 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `const`, `else`, `mut`, `{`, or an operator, found `1`
+ --> $DIR/raw-no-const-mut.rs:2:18
+ |
+LL | let x = &raw 1;
+ | ^ expected one of 10 possible tokens
+ |
+help: `&raw` must be followed by `const` or `mut` to be a raw reference expression
+ |
+LL | let x = &raw const 1;
+ | +++++
+LL | let x = &raw mut 1;
+ | +++
+
+error: expected one of `!`, `,`, `.`, `::`, `?`, `]`, `const`, `mut`, `{`, or an operator, found `2`
+ --> $DIR/raw-no-const-mut.rs:7:25
+ |
+LL | [&raw const 1, &raw 2]
+ | ^ expected one of 10 possible tokens
+ |
+help: `&raw` must be followed by `const` or `mut` to be a raw reference expression
+ |
+LL | [&raw const 1, &raw const 2]
+ | +++++
+LL | [&raw const 1, &raw mut 2]
+ | +++
+help: missing `,`
+ |
+LL | [&raw const 1, &raw, 2]
+ | +
+
+error: expected `{`, found `z`
+ --> $DIR/raw-no-const-mut.rs:14:18
+ |
+LL | if x == &raw z {}
+ | ^ expected `{`
+ |
+note: the `if` expression is missing a block after this condition
+ --> $DIR/raw-no-const-mut.rs:14:8
+ |
+LL | if x == &raw z {}
+ | ^^^^^^^^^
+help: `&raw` must be followed by `const` or `mut` to be a raw reference expression
+ |
+LL | if x == &raw const z {}
+ | +++++
+LL | if x == &raw mut z {}
+ | +++
+
+error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `const`, `mut`, `{`, or an operator, found `2`
+ --> $DIR/raw-no-const-mut.rs:19:12
+ |
+LL | f(&raw 2);
+ | ^ expected one of 10 possible tokens
+ |
+help: `&raw` must be followed by `const` or `mut` to be a raw reference expression
+ |
+LL | f(&raw const 2);
+ | +++++
+LL | f(&raw mut 2);
+ | +++
+help: missing `,`
+ |
+LL | f(&raw, 2);
+ | +
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `const`, `mut`, `{`, `}`, or an operator, found `1`
+ --> $DIR/raw-no-const-mut.rs:27:14
+ |
+LL | x = &raw 1;
+ | ^ expected one of 10 possible tokens
+ |
+help: `&raw` must be followed by `const` or `mut` to be a raw reference expression
+ |
+LL | x = &raw const 1;
+ | +++++
+LL | x = &raw mut 1;
+ | +++
+
+error[E0425]: cannot find value `raw` in this scope
+ --> $DIR/raw-no-const-mut.rs:7:21
+ |
+LL | [&raw const 1, &raw 2]
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find value `raw` in this scope
+ --> $DIR/raw-no-const-mut.rs:19:8
+ |
+LL | f(&raw 2);
+ | ^^^ not found in this scope
+
+error[E0745]: cannot take address of a temporary
+ --> $DIR/raw-no-const-mut.rs:7:17
+ |
+LL | [&raw const 1, &raw 2]
+ | ^ temporary value
+
+error[E0425]: cannot find function `f` in this scope
+ --> $DIR/raw-no-const-mut.rs:19:5
+ |
+LL | fn a() {
+ | ------ similarly named function `a` defined here
+...
+LL | f(&raw 2);
+ | ^ help: a function with a similar name exists: `a`
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0425, E0745.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/recover/recover-ampersand-less-ref-ty.rs b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.rs
new file mode 100644
index 0000000..8f1a424
--- /dev/null
+++ b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.rs
@@ -0,0 +1,13 @@
+//@ edition: 2021
+
+struct Entity<'a> {
+ name: 'a str, //~ ERROR expected type, found lifetime
+ //~^ HELP you might have meant to write a reference type here
+}
+
+struct Buffer<'buf> {
+ bytes: 'buf mut [u8], //~ ERROR expected type, found lifetime
+ //~^ HELP you might have meant to write a reference type here
+}
+
+fn main() {}
diff --git a/tests/ui/parser/recover/recover-ampersand-less-ref-ty.stderr b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.stderr
new file mode 100644
index 0000000..033348b
--- /dev/null
+++ b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.stderr
@@ -0,0 +1,24 @@
+error: expected type, found lifetime
+ --> $DIR/recover-ampersand-less-ref-ty.rs:4:11
+ |
+LL | name: 'a str,
+ | ^^ expected type
+ |
+help: you might have meant to write a reference type here
+ |
+LL | name: &'a str,
+ | +
+
+error: expected type, found lifetime
+ --> $DIR/recover-ampersand-less-ref-ty.rs:9:12
+ |
+LL | bytes: 'buf mut [u8],
+ | ^^^^ expected type
+ |
+help: you might have meant to write a reference type here
+ |
+LL | bytes: &'buf mut [u8],
+ | +
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/recover/recover-assoc-const-constraint.rs b/tests/ui/parser/recover/recover-assoc-const-constraint.rs
index 1453e6c..d938b4c 100644
--- a/tests/ui/parser/recover/recover-assoc-const-constraint.rs
+++ b/tests/ui/parser/recover/recover-assoc-const-constraint.rs
@@ -1,4 +1,4 @@
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
bar::<Item = 42>();
//~^ ERROR associated const equality is incomplete
diff --git a/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs b/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs
index 4b42c44..73b4e22 100644
--- a/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs
+++ b/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs
@@ -1,4 +1,4 @@
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
bar::<Item = >(); //~ ERROR missing type to the right of `=`
}
diff --git a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs
index cb65f80..30bac49 100644
--- a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs
+++ b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs
@@ -1,4 +1,4 @@
-#[cfg(FALSE)]
+#[cfg(false)]
fn syntax() {
bar::<Item = 'a>(); //~ ERROR lifetimes are not permitted in this context
}
diff --git a/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr
index 583b98c..c0f9db9 100644
--- a/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr
+++ b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr
@@ -4,7 +4,6 @@
LL | let x = Tr<A, A:>;
| ^ expected one of 8 possible tokens
|
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: maybe write a path separator here
|
LL | let x = Tr<A, A::>;
diff --git a/tests/ui/parser/self-param-syntactic-pass.rs b/tests/ui/parser/self-param-syntactic-pass.rs
index c7fdc52..331e652 100644
--- a/tests/ui/parser/self-param-syntactic-pass.rs
+++ b/tests/ui/parser/self-param-syntactic-pass.rs
@@ -5,7 +5,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn free() {
fn f(self) {}
fn f(mut self) {}
@@ -17,7 +17,7 @@ fn f(self: u8) {}
fn f(mut self: u8) {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" {
fn f(self);
fn f(mut self);
@@ -29,7 +29,7 @@ fn f(mut self: u8) {}
fn f(mut self: u8);
}
-#[cfg(FALSE)]
+#[cfg(false)]
trait X {
fn f(self) {}
fn f(mut self) {}
@@ -41,7 +41,7 @@ fn f(self: u8) {}
fn f(mut self: u8) {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
impl X for Y {
fn f(self) {}
fn f(mut self) {}
@@ -53,7 +53,7 @@ fn f(self: u8) {}
fn f(mut self: u8) {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
impl X for Y {
type X = fn(self);
type X = fn(mut self);
diff --git a/tests/ui/parser/stripped-nested-outline-mod-pass.rs b/tests/ui/parser/stripped-nested-outline-mod-pass.rs
index 8909d8a..166a60f 100644
--- a/tests/ui/parser/stripped-nested-outline-mod-pass.rs
+++ b/tests/ui/parser/stripped-nested-outline-mod-pass.rs
@@ -5,7 +5,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
mod foo {
mod bar {
mod baz; // This was an error before.
diff --git a/tests/ui/parser/ternary_operator.stderr b/tests/ui/parser/ternary_operator.stderr
index 6635e16..e12a7ff 100644
--- a/tests/ui/parser/ternary_operator.stderr
+++ b/tests/ui/parser/ternary_operator.stderr
@@ -33,8 +33,6 @@
|
LL | let x = 5 > 2 ? { let x = vec![]: Vec<u16>; x } : { false };
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: Rust has no ternary operator
--> $DIR/ternary_operator.rs:26:19
diff --git a/tests/ui/parser/trait-item-with-defaultness-pass.rs b/tests/ui/parser/trait-item-with-defaultness-pass.rs
index c636342..164d0b1 100644
--- a/tests/ui/parser/trait-item-with-defaultness-pass.rs
+++ b/tests/ui/parser/trait-item-with-defaultness-pass.rs
@@ -2,7 +2,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
trait X {
default const A: u8;
default const B: u8 = 0;
diff --git a/tests/ui/parser/trait-object-bad-parens.rs b/tests/ui/parser/trait-object-bad-parens.rs
index 8e267c7..bb047a4 100644
--- a/tests/ui/parser/trait-object-bad-parens.rs
+++ b/tests/ui/parser/trait-object-bad-parens.rs
@@ -5,12 +5,8 @@
auto trait Auto {}
fn main() {
- let _: Box<((Auto)) + Auto>;
- //~^ ERROR expected a path on the left-hand side of `+`, not `((Auto))`
- let _: Box<(Auto + Auto) + Auto>;
- //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto + Auto)`
- let _: Box<(Auto +) + Auto>;
- //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto)`
- let _: Box<(dyn Auto) + Auto>;
- //~^ ERROR expected a path on the left-hand side of `+`, not `(dyn Auto)`
+ let _: Box<((Auto)) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
+ let _: Box<(Auto + Auto) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
+ let _: Box<(Auto +) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
+ let _: Box<(dyn Auto) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
}
diff --git a/tests/ui/parser/trait-object-bad-parens.stderr b/tests/ui/parser/trait-object-bad-parens.stderr
index 74e484e..7c2559c 100644
--- a/tests/ui/parser/trait-object-bad-parens.stderr
+++ b/tests/ui/parser/trait-object-bad-parens.stderr
@@ -1,26 +1,26 @@
-error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-bad-parens.rs:8:16
|
LL | let _: Box<((Auto)) + Auto>;
- | ^^^^^^^^^^^^^^^ expected a path
+ | ^^^^^^^^ expected a path
-error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)`
- --> $DIR/trait-object-bad-parens.rs:10:16
+error[E0178]: expected a path on the left-hand side of `+`
+ --> $DIR/trait-object-bad-parens.rs:9:16
|
LL | let _: Box<(Auto + Auto) + Auto>;
- | ^^^^^^^^^^^^^^^^^^^^ expected a path
+ | ^^^^^^^^^^^^^ expected a path
-error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)`
- --> $DIR/trait-object-bad-parens.rs:12:16
+error[E0178]: expected a path on the left-hand side of `+`
+ --> $DIR/trait-object-bad-parens.rs:10:16
|
LL | let _: Box<(Auto +) + Auto>;
- | ^^^^^^^^^^^^^^^ expected a path
+ | ^^^^^^^^ expected a path
-error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)`
- --> $DIR/trait-object-bad-parens.rs:14:16
+error[E0178]: expected a path on the left-hand side of `+`
+ --> $DIR/trait-object-bad-parens.rs:11:16
|
LL | let _: Box<(dyn Auto) + Auto>;
- | ^^^^^^^^^^^^^^^^^ expected a path
+ | ^^^^^^^^^^ expected a path
error: aborting due to 4 previous errors
diff --git a/tests/ui/parser/trait-object-lifetime-parens.stderr b/tests/ui/parser/trait-object-lifetime-parens.e2015.stderr
similarity index 60%
rename from tests/ui/parser/trait-object-lifetime-parens.stderr
rename to tests/ui/parser/trait-object-lifetime-parens.e2015.stderr
index 280c0e4..cf0b3d7 100644
--- a/tests/ui/parser/trait-object-lifetime-parens.stderr
+++ b/tests/ui/parser/trait-object-lifetime-parens.e2015.stderr
@@ -1,5 +1,5 @@
error: parenthesized lifetime bounds are not supported
- --> $DIR/trait-object-lifetime-parens.rs:5:21
+ --> $DIR/trait-object-lifetime-parens.rs:9:21
|
LL | fn f<'a, T: Trait + ('a)>() {}
| ^^^^
@@ -11,7 +11,7 @@
|
error: parenthesized lifetime bounds are not supported
- --> $DIR/trait-object-lifetime-parens.rs:8:24
+ --> $DIR/trait-object-lifetime-parens.rs:12:24
|
LL | let _: Box<Trait + ('a)>;
| ^^^^
@@ -22,11 +22,16 @@
LL + let _: Box<Trait + 'a>;
|
-error: lifetime in trait object type must be followed by `+`
- --> $DIR/trait-object-lifetime-parens.rs:10:17
+error: lifetimes must be followed by `+` to form a trait object type
+ --> $DIR/trait-object-lifetime-parens.rs:16:17
|
LL | let _: Box<('a) + Trait>;
| ^^
+ |
+help: consider adding a trait bound after the potential lifetime bound
+ |
+LL | let _: Box<('a + /* Trait */) + Trait>;
+ | +++++++++++++
error: aborting due to 3 previous errors
diff --git a/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr b/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr
new file mode 100644
index 0000000..b65c079
--- /dev/null
+++ b/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr
@@ -0,0 +1,51 @@
+error: parenthesized lifetime bounds are not supported
+ --> $DIR/trait-object-lifetime-parens.rs:9:21
+ |
+LL | fn f<'a, T: Trait + ('a)>() {}
+ | ^^^^
+ |
+help: remove the parentheses
+ |
+LL - fn f<'a, T: Trait + ('a)>() {}
+LL + fn f<'a, T: Trait + 'a>() {}
+ |
+
+error: parenthesized lifetime bounds are not supported
+ --> $DIR/trait-object-lifetime-parens.rs:12:24
+ |
+LL | let _: Box<Trait + ('a)>;
+ | ^^^^
+ |
+help: remove the parentheses
+ |
+LL - let _: Box<Trait + ('a)>;
+LL + let _: Box<Trait + 'a>;
+ |
+
+error: expected type, found lifetime
+ --> $DIR/trait-object-lifetime-parens.rs:16:17
+ |
+LL | let _: Box<('a) + Trait>;
+ | ^^ expected type
+
+error[E0178]: expected a path on the left-hand side of `+`
+ --> $DIR/trait-object-lifetime-parens.rs:16:16
+ |
+LL | let _: Box<('a) + Trait>;
+ | ^^^^ expected a path
+
+error[E0782]: expected a type, found a trait
+ --> $DIR/trait-object-lifetime-parens.rs:12:16
+ |
+LL | let _: Box<Trait + ('a)>;
+ | ^^^^^^^^^^^^
+ |
+help: you can add the `dyn` keyword if you want a trait object
+ |
+LL | let _: Box<dyn Trait + ('a)>;
+ | +++
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0178, E0782.
+For more information about an error, try `rustc --explain E0178`.
diff --git a/tests/ui/parser/trait-object-lifetime-parens.rs b/tests/ui/parser/trait-object-lifetime-parens.rs
index f44ebe5..0ff4660 100644
--- a/tests/ui/parser/trait-object-lifetime-parens.rs
+++ b/tests/ui/parser/trait-object-lifetime-parens.rs
@@ -1,4 +1,8 @@
-#![allow(bare_trait_objects)]
+//@ revisions: e2015 e2021
+//@[e2015] edition: 2015
+//@[e2021] edition: 2021
+
+#![cfg_attr(e2015, allow(bare_trait_objects))]
trait Trait {}
@@ -6,8 +10,12 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s
fn check<'a>() {
let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
- // FIXME: It'd be great if we could add suggestion to the following case.
- let _: Box<('a) + Trait>; //~ ERROR lifetime in trait object type must be followed by `+`
+ //[e2021]~^ ERROR expected a type, found a trait
+ // FIXME: It'd be great if we could suggest removing the parentheses here too.
+ //[e2015]~v ERROR lifetimes must be followed by `+` to form a trait object type
+ let _: Box<('a) + Trait>;
+ //[e2021]~^ ERROR expected type, found lifetime
+ //[e2021]~| ERROR expected a path on the left-hand side of `+`
}
fn main() {}
diff --git a/tests/ui/parser/trait-object-polytrait-priority.rs b/tests/ui/parser/trait-object-polytrait-priority.rs
index e7f0851..85568f0 100644
--- a/tests/ui/parser/trait-object-polytrait-priority.rs
+++ b/tests/ui/parser/trait-object-polytrait-priority.rs
@@ -4,6 +4,6 @@ trait Trait<'a> {}
fn main() {
let _: &for<'a> Trait<'a> + 'static;
- //~^ ERROR expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>`
+ //~^ ERROR expected a path on the left-hand side of `+`
//~| HELP try adding parentheses
}
diff --git a/tests/ui/parser/trait-object-polytrait-priority.stderr b/tests/ui/parser/trait-object-polytrait-priority.stderr
index 8cb564e..a291a8e 100644
--- a/tests/ui/parser/trait-object-polytrait-priority.stderr
+++ b/tests/ui/parser/trait-object-polytrait-priority.stderr
@@ -1,8 +1,8 @@
-error[E0178]: expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>`
+error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-polytrait-priority.rs:6:12
|
LL | let _: &for<'a> Trait<'a> + 'static;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^
|
help: try adding parentheses
|
diff --git a/tests/ui/parser/utf16-be-without-bom.rs b/tests/ui/parser/utf16-be-without-bom.rs
index 5387287..1f2abc1 100644
--- a/tests/ui/parser/utf16-be-without-bom.rs
+++ b/tests/ui/parser/utf16-be-without-bom.rs
Binary files differ
diff --git a/tests/ui/parser/utf16-le-without-bom.rs b/tests/ui/parser/utf16-le-without-bom.rs
index fc41366..bb95f0d 100644
--- a/tests/ui/parser/utf16-le-without-bom.rs
+++ b/tests/ui/parser/utf16-le-without-bom.rs
Binary files differ
diff --git a/tests/ui/parser/variadic-ffi-syntactic-pass.rs b/tests/ui/parser/variadic-ffi-syntactic-pass.rs
index da81f13..ebe0b6c 100644
--- a/tests/ui/parser/variadic-ffi-syntactic-pass.rs
+++ b/tests/ui/parser/variadic-ffi-syntactic-pass.rs
@@ -2,31 +2,31 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn f1_1(x: isize, ...) {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn f1_2(...) {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" fn f2_1(x: isize, ...) {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" fn f2_2(...) {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern "C" fn f2_3(..., x: isize) {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern fn f3_1(x: isize, ...) {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern fn f3_2(...) {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern fn f3_3(..., x: isize) {}
-#[cfg(FALSE)]
+#[cfg(false)]
extern {
fn e_f1(...);
fn e_f2(..., x: isize);
@@ -34,7 +34,7 @@ extern "C" fn f2_3(..., x: isize) {}
struct X;
-#[cfg(FALSE)]
+#[cfg(false)]
impl X {
fn i_f1(x: isize, ...) {}
fn i_f2(...) {}
@@ -42,7 +42,7 @@ fn i_f3(..., x: isize, ...) {}
fn i_f4(..., x: isize, ...) {}
}
-#[cfg(FALSE)]
+#[cfg(false)]
trait T {
fn t_f1(x: isize, ...) {}
fn t_f2(x: isize, ...);
diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs
index 01a978d..9582d27 100644
--- a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs
+++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs
@@ -13,19 +13,19 @@ fn _ok() {
fn _f(_a @ _b: u8) {} // OK.
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn case_1() {
let a: u8 @ b = 0;
//~^ ERROR expected one of `!`
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn case_2() {
let a @ (b: u8);
//~^ ERROR expected one of `)`
}
-#[cfg(FALSE)]
+#[cfg(false)]
fn case_3() {
let a: T1 @ Outer(b: T2);
//~^ ERROR expected one of `!`
diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr
index 6ce8f6d..1847e40 100644
--- a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr
+++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr
@@ -11,8 +11,6 @@
|
LL | let a @ (b: u8);
| ^ expected one of `)`, `,`, `@`, `if`, or `|`
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@`
--> $DIR/nested-type-ascription-syntactically-invalid.rs:30:15
diff --git a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs
index 50ac0ef..c3994d3 100644
--- a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs
+++ b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs
@@ -3,7 +3,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
fn wild_before_at_is_bad_syntax() {
let _ @ a = 0;
//~^ ERROR pattern on wrong side of `@`
diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs
index 5881e41..c14d57f 100644
--- a/tests/ui/pattern/deref-patterns/bindings.rs
+++ b/tests/ui/pattern/deref-patterns/bindings.rs
@@ -1,7 +1,9 @@
+//@ revisions: explicit implicit
//@ run-pass
#![feature(deref_patterns)]
#![allow(incomplete_features)]
+#[cfg(explicit)]
fn simple_vec(vec: Vec<u32>) -> u32 {
match vec {
deref!([]) => 100,
@@ -13,6 +15,19 @@ fn simple_vec(vec: Vec<u32>) -> u32 {
}
}
+#[cfg(implicit)]
+fn simple_vec(vec: Vec<u32>) -> u32 {
+ match vec {
+ [] => 100,
+ [x] if x == 4 => x + 4,
+ [x] => x,
+ [1, x] => x + 200,
+ deref!(ref slice) => slice.iter().sum(),
+ _ => 2000,
+ }
+}
+
+#[cfg(explicit)]
fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
match vecvec {
deref!([]) => 0,
@@ -24,6 +39,19 @@ fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
}
}
+#[cfg(implicit)]
+fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
+ match vecvec {
+ [] => 0,
+ [[x]] => x,
+ [[0, x] | [1, x]] => x,
+ [ref x] => x.iter().sum(),
+ [[], [1, x, y]] => y - x,
+ _ => 2000,
+ }
+}
+
+#[cfg(explicit)]
fn ref_mut(val: u32) -> u32 {
let mut b = Box::new(0u32);
match &mut b {
@@ -37,6 +65,21 @@ fn ref_mut(val: u32) -> u32 {
*x
}
+#[cfg(implicit)]
+fn ref_mut(val: u32) -> u32 {
+ let mut b = Box::new((0u32,));
+ match &mut b {
+ (_x,) if false => unreachable!(),
+ (x,) => {
+ *x = val;
+ }
+ _ => unreachable!(),
+ }
+ let (x,) = &b else { unreachable!() };
+ *x
+}
+
+#[cfg(explicit)]
#[rustfmt::skip]
fn or_and_guard(tuple: (u32, u32)) -> u32 {
let mut sum = 0;
@@ -48,6 +91,18 @@ fn or_and_guard(tuple: (u32, u32)) -> u32 {
sum
}
+#[cfg(implicit)]
+#[rustfmt::skip]
+fn or_and_guard(tuple: (u32, u32)) -> u32 {
+ let mut sum = 0;
+ let b = Box::new(tuple);
+ match b {
+ (x, _) | (_, x) if { sum += x; false } => {},
+ _ => {},
+ }
+ sum
+}
+
fn main() {
assert_eq!(simple_vec(vec![1]), 1);
assert_eq!(simple_vec(vec![1, 2]), 202);
diff --git a/tests/ui/pattern/deref-patterns/branch.rs b/tests/ui/pattern/deref-patterns/branch.rs
index 1bac100..9d72b35 100644
--- a/tests/ui/pattern/deref-patterns/branch.rs
+++ b/tests/ui/pattern/deref-patterns/branch.rs
@@ -1,8 +1,10 @@
+//@ revisions: explicit implicit
//@ run-pass
// Test the execution of deref patterns.
#![feature(deref_patterns)]
#![allow(incomplete_features)]
+#[cfg(explicit)]
fn branch(vec: Vec<u32>) -> u32 {
match vec {
deref!([]) => 0,
@@ -12,6 +14,17 @@ fn branch(vec: Vec<u32>) -> u32 {
}
}
+#[cfg(implicit)]
+fn branch(vec: Vec<u32>) -> u32 {
+ match vec {
+ [] => 0,
+ [1, _, 3] => 1,
+ [2, ..] => 2,
+ _ => 1000,
+ }
+}
+
+#[cfg(explicit)]
fn nested(vec: Vec<Vec<u32>>) -> u32 {
match vec {
deref!([deref!([]), ..]) => 1,
@@ -20,6 +33,15 @@ fn nested(vec: Vec<Vec<u32>>) -> u32 {
}
}
+#[cfg(implicit)]
+fn nested(vec: Vec<Vec<u32>>) -> u32 {
+ match vec {
+ [[], ..] => 1,
+ [[0, ..], [1, ..]] => 2,
+ _ => 1000,
+ }
+}
+
fn main() {
assert!(matches!(Vec::<u32>::new(), deref!([])));
assert!(matches!(vec![1], deref!([1])));
diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
index 84b5ec0..791776b 100644
--- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs
@@ -21,4 +21,22 @@ fn cant_move_out_rc(rc: Rc<Struct>) -> Struct {
}
}
+struct Container(Struct);
+
+fn cant_move_out_box_implicit(b: Box<Container>) -> Struct {
+ match b {
+ //~^ ERROR: cannot move out of a shared reference
+ Container(x) => x,
+ _ => unreachable!(),
+ }
+}
+
+fn cant_move_out_rc_implicit(rc: Rc<Container>) -> Struct {
+ match rc {
+ //~^ ERROR: cannot move out of a shared reference
+ Container(x) => x,
+ _ => unreachable!(),
+ }
+}
+
fn main() {}
diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
index 2cf435b..1887800 100644
--- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
+++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr
@@ -32,6 +32,40 @@
LL | deref!(ref x) => x,
| +++
-error: aborting due to 2 previous errors
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/cant_move_out_of_pattern.rs:27:11
+ |
+LL | match b {
+ | ^
+LL |
+LL | Container(x) => x,
+ | -
+ | |
+ | data moved here
+ | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | Container(ref x) => x,
+ | +++
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/cant_move_out_of_pattern.rs:35:11
+ |
+LL | match rc {
+ | ^^
+LL |
+LL | Container(x) => x,
+ | -
+ | |
+ | data moved here
+ | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | Container(ref x) => x,
+ | +++
+
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/deref-patterns/closure_capture.rs b/tests/ui/pattern/deref-patterns/closure_capture.rs
index fc0dded..08586b6 100644
--- a/tests/ui/pattern/deref-patterns/closure_capture.rs
+++ b/tests/ui/pattern/deref-patterns/closure_capture.rs
@@ -11,6 +11,15 @@ fn main() {
assert_eq!(b.len(), 3);
f();
+ let v = vec![1, 2, 3];
+ let f = || {
+ // this should count as a borrow of `v` as a whole
+ let [.., x] = v else { unreachable!() };
+ assert_eq!(x, 3);
+ };
+ assert_eq!(v, [1, 2, 3]);
+ f();
+
let mut b = Box::new("aaa".to_string());
let mut f = || {
let deref!(ref mut s) = b else { unreachable!() };
@@ -18,4 +27,22 @@ fn main() {
};
f();
assert_eq!(b.len(), 5);
+
+ let mut v = vec![1, 2, 3];
+ let mut f = || {
+ // this should count as a mutable borrow of `v` as a whole
+ let [.., ref mut x] = v else { unreachable!() };
+ *x = 4;
+ };
+ f();
+ assert_eq!(v, [1, 2, 4]);
+
+ let mut v = vec![1, 2, 3];
+ let mut f = || {
+ // here, `[.., x]` is adjusted by both an overloaded deref and a builtin deref
+ let [.., x] = &mut v else { unreachable!() };
+ *x = 4;
+ };
+ f();
+ assert_eq!(v, [1, 2, 4]);
}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.rs b/tests/ui/pattern/deref-patterns/fake_borrows.rs
index 35fa9cb..bf614d7 100644
--- a/tests/ui/pattern/deref-patterns/fake_borrows.rs
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.rs
@@ -11,4 +11,11 @@ fn main() {
deref!(false) => {}
_ => {},
}
+ match b {
+ true => {}
+ _ if { *b = true; false } => {}
+ //~^ ERROR cannot assign `*b` in match guard
+ false => {}
+ _ => {},
+ }
}
diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.stderr b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
index 6a591e6..8c06023 100644
--- a/tests/ui/pattern/deref-patterns/fake_borrows.stderr
+++ b/tests/ui/pattern/deref-patterns/fake_borrows.stderr
@@ -7,6 +7,15 @@
LL | _ if { *b = true; false } => {}
| ^^^^^^^^^ cannot assign
-error: aborting due to 1 previous error
+error[E0510]: cannot assign `*b` in match guard
+ --> $DIR/fake_borrows.rs:16:16
+ |
+LL | match b {
+ | - value is immutable in match guard
+LL | true => {}
+LL | _ if { *b = true; false } => {}
+ | ^^^^^^^^^ cannot assign
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0510`.
diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.rs b/tests/ui/pattern/deref-patterns/implicit-const-deref.rs
new file mode 100644
index 0000000..70f8962
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.rs
@@ -0,0 +1,19 @@
+//! Test that we get an error about structural equality rather than a type error when attempting to
+//! use const patterns of library pointer types. Currently there aren't any smart pointers that can
+//! be used in constant patterns, but we still need to make sure we don't implicitly dereference the
+//! scrutinee and end up with a type error; this would prevent us from reporting that only constants
+//! supporting structural equality can be used as patterns.
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+const EMPTY: Vec<()> = Vec::new();
+
+fn main() {
+ // FIXME(inline_const_pat): if `inline_const_pat` is reinstated, there should be a case here for
+ // inline const block patterns as well; they're checked differently than named constants.
+ match vec![()] {
+ EMPTY => {}
+ //~^ ERROR: constant of non-structural type `Vec<()>` in a pattern
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
new file mode 100644
index 0000000..21d09ec4
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
@@ -0,0 +1,16 @@
+error: constant of non-structural type `Vec<()>` in a pattern
+ --> $DIR/implicit-const-deref.rs:15:9
+ |
+LL | const EMPTY: Vec<()> = Vec::new();
+ | -------------------- constant defined here
+...
+LL | EMPTY => {}
+ | ^^^^^ constant of non-structural type
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ |
+ = note: `Vec<()>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+ |
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs
new file mode 100644
index 0000000..a9b8de8
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs
@@ -0,0 +1,45 @@
+//@ run-pass
+//! Test that implicit deref patterns interact as expected with `Cow` constructor patterns.
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+use std::borrow::Cow;
+
+fn main() {
+ let cow: Cow<'static, [u8]> = Cow::Borrowed(&[1, 2, 3]);
+
+ match cow {
+ [..] => {}
+ _ => unreachable!(),
+ }
+
+ match cow {
+ Cow::Borrowed(_) => {}
+ Cow::Owned(_) => unreachable!(),
+ }
+
+ match Box::new(&cow) {
+ Cow::Borrowed { 0: _ } => {}
+ Cow::Owned { 0: _ } => unreachable!(),
+ _ => unreachable!(),
+ }
+
+ let cow_of_cow: Cow<'_, Cow<'static, [u8]>> = Cow::Owned(cow);
+
+ match cow_of_cow {
+ [..] => {}
+ _ => unreachable!(),
+ }
+
+ // This matches on the outer `Cow` (the owned one).
+ match cow_of_cow {
+ Cow::Borrowed(_) => unreachable!(),
+ Cow::Owned(_) => {}
+ }
+
+ match Box::new(&cow_of_cow) {
+ Cow::Borrowed { 0: _ } => unreachable!(),
+ Cow::Owned { 0: _ } => {}
+ _ => unreachable!(),
+ }
+}
diff --git a/tests/ui/pattern/deref-patterns/needs-gate.rs b/tests/ui/pattern/deref-patterns/needs-gate.rs
new file mode 100644
index 0000000..2d5ec45
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/needs-gate.rs
@@ -0,0 +1,15 @@
+// gate-test-deref_patterns
+
+fn main() {
+ match Box::new(0) {
+ deref!(0) => {}
+ //~^ ERROR: use of unstable library feature `deref_patterns`: placeholder syntax for deref patterns
+ _ => {}
+ }
+
+ match Box::new(0) {
+ 0 => {}
+ //~^ ERROR: mismatched types
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/deref-patterns/needs-gate.stderr b/tests/ui/pattern/deref-patterns/needs-gate.stderr
new file mode 100644
index 0000000..8687b5d
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr
@@ -0,0 +1,29 @@
+error[E0658]: use of unstable library feature `deref_patterns`: placeholder syntax for deref patterns
+ --> $DIR/needs-gate.rs:5:9
+ |
+LL | deref!(0) => {}
+ | ^^^^^
+ |
+ = note: see issue #87121 <https://github.com/rust-lang/rust/issues/87121> for more information
+ = help: add `#![feature(deref_patterns)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0308]: mismatched types
+ --> $DIR/needs-gate.rs:11:9
+ |
+LL | match Box::new(0) {
+ | ----------- this expression has type `Box<{integer}>`
+LL | 0 => {}
+ | ^ expected `Box<{integer}>`, found integer
+ |
+ = note: expected struct `Box<{integer}>`
+ found type `{integer}`
+help: consider dereferencing to access the inner value using the Deref trait
+ |
+LL | match *Box::new(0) {
+ | +
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/recursion-limit.rs b/tests/ui/pattern/deref-patterns/recursion-limit.rs
new file mode 100644
index 0000000..c5fe520
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/recursion-limit.rs
@@ -0,0 +1,23 @@
+//! Test that implicit deref patterns respect the recursion limit
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+#![recursion_limit = "8"]
+
+use std::ops::Deref;
+
+struct Cyclic;
+impl Deref for Cyclic {
+ type Target = Cyclic;
+ fn deref(&self) -> &Cyclic {
+ &Cyclic
+ }
+}
+
+fn main() {
+ match &Box::new(Cyclic) {
+ () => {}
+ //~^ ERROR: reached the recursion limit while auto-dereferencing `Cyclic`
+ //~| ERROR: the trait bound `Cyclic: DerefPure` is not satisfied
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/deref-patterns/recursion-limit.stderr b/tests/ui/pattern/deref-patterns/recursion-limit.stderr
new file mode 100644
index 0000000..9a83d1e
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/recursion-limit.stderr
@@ -0,0 +1,18 @@
+error[E0055]: reached the recursion limit while auto-dereferencing `Cyclic`
+ --> $DIR/recursion-limit.rs:18:9
+ |
+LL | () => {}
+ | ^^ deref recursion limit reached
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "16"]` attribute to your crate (`recursion_limit`)
+
+error[E0277]: the trait bound `Cyclic: DerefPure` is not satisfied
+ --> $DIR/recursion-limit.rs:18:9
+ |
+LL | () => {}
+ | ^^ the trait `DerefPure` is not implemented for `Cyclic`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0055, E0277.
+For more information about an error, try `rustc --explain E0055`.
diff --git a/tests/ui/pattern/deref-patterns/ref-mut.rs b/tests/ui/pattern/deref-patterns/ref-mut.rs
index 1918008..4373867 100644
--- a/tests/ui/pattern/deref-patterns/ref-mut.rs
+++ b/tests/ui/pattern/deref-patterns/ref-mut.rs
@@ -8,10 +8,19 @@ fn main() {
deref!(x) => {}
_ => {}
}
+ match &mut vec![1] {
+ [x] => {}
+ _ => {}
+ }
match &mut Rc::new(1) {
deref!(x) => {}
//~^ ERROR the trait bound `Rc<{integer}>: DerefMut` is not satisfied
_ => {}
}
+ match &mut Rc::new((1,)) {
+ (x,) => {}
+ //~^ ERROR the trait bound `Rc<({integer},)>: DerefMut` is not satisfied
+ _ => {}
+ }
}
diff --git a/tests/ui/pattern/deref-patterns/ref-mut.stderr b/tests/ui/pattern/deref-patterns/ref-mut.stderr
index 41f1c30..24a35b4 100644
--- a/tests/ui/pattern/deref-patterns/ref-mut.stderr
+++ b/tests/ui/pattern/deref-patterns/ref-mut.stderr
@@ -8,13 +8,19 @@
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `Rc<{integer}>: DerefMut` is not satisfied
- --> $DIR/ref-mut.rs:13:9
+ --> $DIR/ref-mut.rs:17:9
|
LL | deref!(x) => {}
| ^^^^^^^^^ the trait `DerefMut` is not implemented for `Rc<{integer}>`
|
= note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 1 previous error; 1 warning emitted
+error[E0277]: the trait bound `Rc<({integer},)>: DerefMut` is not satisfied
+ --> $DIR/ref-mut.rs:22:9
+ |
+LL | (x,) => {}
+ | ^^^^ the trait `DerefMut` is not implemented for `Rc<({integer},)>`
+
+error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/pattern/deref-patterns/typeck.rs b/tests/ui/pattern/deref-patterns/typeck.rs
index f23f704..3a7ce9d 100644
--- a/tests/ui/pattern/deref-patterns/typeck.rs
+++ b/tests/ui/pattern/deref-patterns/typeck.rs
@@ -10,26 +10,32 @@ fn main() {
let vec: Vec<u32> = Vec::new();
match vec {
deref!([..]) => {}
+ [..] => {}
_ => {}
}
match Box::new(true) {
deref!(true) => {}
+ true => {}
_ => {}
}
match &Box::new(true) {
deref!(true) => {}
+ true => {}
_ => {}
}
match &Rc::new(0) {
deref!(1..) => {}
+ 1.. => {}
_ => {}
}
let _: &Struct = match &Rc::new(Struct) {
deref!(x) => x,
+ Struct => &Struct,
_ => unreachable!(),
};
let _: &[Struct] = match &Rc::new(vec![Struct]) {
deref!(deref!(x)) => x,
+ [Struct] => &[Struct],
_ => unreachable!(),
};
}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs
index 0401184..4b9ad7d 100644
--- a/tests/ui/pattern/deref-patterns/typeck_fail.rs
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs
@@ -7,11 +7,22 @@ fn main() {
match "foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
+ "foo" => {}
+ //~^ ERROR: mismatched types
_ => {}
}
match &"foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
+ "foo" => {}
+ //~^ ERROR: mismatched types
+ _ => {}
+ }
+
+ // Make sure we don't try implicitly dereferncing any ADT.
+ match Some(0) {
+ Ok(0) => {}
+ //~^ ERROR: mismatched types
_ => {}
}
}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
index 1c14802..3e2f356 100644
--- a/tests/ui/pattern/deref-patterns/typeck_fail.stderr
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
@@ -7,13 +7,45 @@
| ^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
- --> $DIR/typeck_fail.rs:13:16
+ --> $DIR/typeck_fail.rs:10:9
+ |
+LL | match "foo".to_string() {
+ | ----------------- this expression has type `String`
+...
+LL | "foo" => {}
+ | ^^^^^ expected `String`, found `&str`
+
+error[E0308]: mismatched types
+ --> $DIR/typeck_fail.rs:15:16
|
LL | match &"foo".to_string() {
| ------------------ this expression has type `&String`
LL | deref!("foo") => {}
| ^^^^^ expected `str`, found `&str`
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+ --> $DIR/typeck_fail.rs:17:9
+ |
+LL | match &"foo".to_string() {
+ | ------------------ this expression has type `&String`
+...
+LL | "foo" => {}
+ | ^^^^^ expected `&String`, found `&str`
+ |
+ = note: expected reference `&String`
+ found reference `&'static str`
+
+error[E0308]: mismatched types
+ --> $DIR/typeck_fail.rs:24:9
+ |
+LL | match Some(0) {
+ | ------- this expression has type `Option<{integer}>`
+LL | Ok(0) => {}
+ | ^^^^^ expected `Option<{integer}>`, found `Result<_, _>`
+ |
+ = note: expected enum `Option<{integer}>`
+ found enum `Result<_, _>`
+
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs
new file mode 100644
index 0000000..00064b2
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs
@@ -0,0 +1,21 @@
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+struct MyPointer;
+
+impl std::ops::Deref for MyPointer {
+ type Target = ();
+ fn deref(&self) -> &() {
+ &()
+ }
+}
+
+fn main() {
+ // Test that we get a trait error if a user attempts implicit deref pats on their own impls.
+ // FIXME(deref_patterns): there should be a special diagnostic for missing `DerefPure`.
+ match MyPointer {
+ () => {}
+ //~^ the trait bound `MyPointer: DerefPure` is not satisfied
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr
new file mode 100644
index 0000000..983ce27
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `MyPointer: DerefPure` is not satisfied
+ --> $DIR/unsatisfied-bounds.rs:17:9
+ |
+LL | () => {}
+ | ^^ the trait `DerefPure` is not implemented for `MyPointer`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/pattern/rest-pat-syntactic.rs b/tests/ui/pattern/rest-pat-syntactic.rs
index 1de29e6..59c687b 100644
--- a/tests/ui/pattern/rest-pat-syntactic.rs
+++ b/tests/ui/pattern/rest-pat-syntactic.rs
@@ -11,7 +11,7 @@ macro_rules! accept_pat {
accept_pat!(..);
-#[cfg(FALSE)]
+#[cfg(false)]
fn rest_patterns() {
// Top level:
fn foo(..: u8) {}
diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs
deleted file mode 100644
index 36a47d0..0000000
--- a/tests/ui/pin-macro/cant_access_internals.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ edition:2018
-
-use core::{
- marker::PhantomPinned,
- mem,
- pin::{pin, Pin},
-};
-
-fn main() {
- let mut phantom_pinned = pin!(PhantomPinned);
- mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature `unsafe_pin_internals`
-}
diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr
deleted file mode 100644
index 8ad897b..0000000
--- a/tests/ui/pin-macro/cant_access_internals.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: use of unstable library feature `unsafe_pin_internals`
- --> $DIR/cant_access_internals.rs:11:15
- |
-LL | mem::take(phantom_pinned.__pointer);
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add `#![feature(unsafe_pin_internals)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs
index 8a0244e..e505fe4 100644
--- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs
+++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs
@@ -9,14 +9,14 @@
fn function_call_stops_borrow_extension() {
let phantom_pinned = identity(pin!(PhantomPinned));
- //~^ ERROR temporary value dropped while borrowed
+ //~^ ERROR does not live long enough
stuff(phantom_pinned)
}
fn promotion_only_works_for_the_innermost_block() {
let phantom_pinned = {
let phantom_pinned = pin!(PhantomPinned);
- //~^ ERROR temporary value dropped while borrowed
+ //~^ ERROR does not live long enough
phantom_pinned
};
stuff(phantom_pinned)
diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
index 9df7f0f..43fb82b 100644
--- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
+++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr
@@ -1,35 +1,29 @@
-error[E0716]: temporary value dropped while borrowed
+error[E0597]: value does not live long enough
--> $DIR/lifetime_errors_on_promotion_misusage.rs:11:35
|
LL | let phantom_pinned = identity(pin!(PhantomPinned));
- | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+ | ^^^^^^^^^^^^^^^^^^^ - value dropped here while still borrowed
| |
- | creates a temporary value which is freed while still in use
+ | borrowed value does not live long enough
LL |
LL | stuff(phantom_pinned)
| -------------- borrow later used here
|
= note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider using a `let` binding to create a longer lived value
- |
-LL ~ let binding = pin!(PhantomPinned);
-LL ~ let phantom_pinned = identity(binding);
- |
-error[E0716]: temporary value dropped while borrowed
+error[E0597]: value does not live long enough
--> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30
|
LL | let phantom_pinned = {
| -------------- borrow later stored here
LL | let phantom_pinned = pin!(PhantomPinned);
- | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+ | ^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
LL | };
- | - temporary value is freed at the end of this statement
+ | - value dropped here while still borrowed
|
- = note: consider using a `let` binding to create a longer lived value
= note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0716`.
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr
index c9b8ad9..3f46602 100644
--- a/tests/ui/pin-macro/pin_move.stderr
+++ b/tests/ui/pin-macro/pin_move.stderr
@@ -31,6 +31,11 @@
LL | let mut pointee = NotCopy(PhantomPinned);
LL | pin!(*&mut pointee);
| ------------- you could clone this value
+help: consider removing the dereference here
+ |
+LL - pin!(*&mut pointee);
+LL + pin!(&mut pointee);
+ |
error: aborting due to 2 previous errors
diff --git a/tests/ui/precondition-checks/read.rs b/tests/ui/precondition-checks/read.rs
index ab9921a..d5ab777 100644
--- a/tests/ui/precondition-checks/read.rs
+++ b/tests/ui/precondition-checks/read.rs
@@ -2,7 +2,7 @@
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::read requires
//@ revisions: null misaligned
-//@ ignore-test
+//@ ignore-test (unimplemented)
use std::ptr;
diff --git a/tests/ui/precondition-checks/write.rs b/tests/ui/precondition-checks/write.rs
index f76e776..5d6b958 100644
--- a/tests/ui/precondition-checks/write.rs
+++ b/tests/ui/precondition-checks/write.rs
@@ -2,7 +2,7 @@
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::write requires
//@ revisions: null misaligned
-//@ ignore-test
+//@ ignore-test (unimplemented)
use std::ptr;
diff --git a/tests/ui/precondition-checks/write_bytes.rs b/tests/ui/precondition-checks/write_bytes.rs
index 3f64be9..be4f5a0 100644
--- a/tests/ui/precondition-checks/write_bytes.rs
+++ b/tests/ui/precondition-checks/write_bytes.rs
@@ -2,7 +2,7 @@
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::write requires
//@ revisions: null misaligned
-//@ ignore-test
+//@ ignore-test (unimplemented)
use std::ptr;
diff --git a/tests/ui/print-request/print-lints-help.rs b/tests/ui/print-request/print-lints-help.rs
index 6dd88a7..9a706a2 100644
--- a/tests/ui/print-request/print-lints-help.rs
+++ b/tests/ui/print-request/print-lints-help.rs
@@ -2,7 +2,8 @@
//! `--print=lints` (which is not a valid print request).
//@ compile-flags: --print lints
-//@ error-pattern: help: use `-Whelp` to print a list of lints
-//@ error-pattern: help: for more information, see the rustc book
//~? ERROR unknown print request: `lints`
+//~? HELP use `-Whelp` to print a list of lints
+//~? HELP for more information, see the rustc book
+//~? HELP valid print requests are
diff --git a/tests/ui/proc-macro/attribute-after-derive.rs b/tests/ui/proc-macro/attribute-after-derive.rs
index f2e2eb1..382ef1f 100644
--- a/tests/ui/proc-macro/attribute-after-derive.rs
+++ b/tests/ui/proc-macro/attribute-after-derive.rs
@@ -14,14 +14,14 @@
#[print_attr]
#[derive(Print)]
struct AttributeDerive {
- #[cfg(FALSE)]
+ #[cfg(false)]
field: u8,
}
#[derive(Print)]
#[print_attr]
struct DeriveAttribute {
- #[cfg(FALSE)]
+ #[cfg(false)]
field: u8,
}
diff --git a/tests/ui/proc-macro/attribute-after-derive.stdout b/tests/ui/proc-macro/attribute-after-derive.stdout
index 6d9531d..bc0fc6d 100644
--- a/tests/ui/proc-macro/attribute-after-derive.stdout
+++ b/tests/ui/proc-macro/attribute-after-derive.stdout
@@ -1,5 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field: u8, }
-PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, }
+PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(false)] field: u8, }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(false)] field : u8, }
PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: '#',
@@ -53,7 +53,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0),
},
],
@@ -131,8 +131,8 @@
span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0),
},
]
-PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field: u8, }
-PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, }
+PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(false)] field: u8, }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): struct DeriveAttribute { #[cfg(false)] field : u8, }
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
@@ -161,7 +161,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/attribute-after-derive.rs:24:11: 24:16 (#0),
},
],
diff --git a/tests/ui/proc-macro/auxiliary/expand-expr.rs b/tests/ui/proc-macro/auxiliary/expand-expr.rs
index 78c9fa7..14efc3c 100644
--- a/tests/ui/proc-macro/auxiliary/expand-expr.rs
+++ b/tests/ui/proc-macro/auxiliary/expand-expr.rs
@@ -3,9 +3,10 @@
extern crate proc_macro;
-use proc_macro::*;
use std::str::FromStr;
+use proc_macro::*;
+
// Flatten the TokenStream, removing any toplevel `Delimiter::None`s for
// comparison.
fn flatten(ts: TokenStream) -> Vec<TokenTree> {
@@ -136,9 +137,8 @@ pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream {
.to_string();
assert_eq!(input_t, parse_t);
- // Check that the literal matches `Span::call_site().source_file().path()`
- let expect_t =
- Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string();
+ // Check that the literal matches `Span::call_site().file()`
+ let expect_t = Literal::string(&Span::call_site().file()).to_string();
assert_eq!(input_t, expect_t);
TokenStream::new()
diff --git a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs
index 4971de2..11e1910 100644
--- a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs
+++ b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs
@@ -79,7 +79,7 @@ fn check_useful_span(token: TokenTree, expected_filename: &str) {
let span = token.span();
assert!(span.column() < span.end().column());
- let source_path = span.source_file().path();
+ let source_path = span.local_file().unwrap();
let filename = source_path.components().last().unwrap();
assert_eq!(filename, Component::Normal(expected_filename.as_ref()));
}
diff --git a/tests/ui/proc-macro/auxiliary/span-api-tests.rs b/tests/ui/proc-macro/auxiliary/span-api-tests.rs
index 99db66e..036f2e3 100644
--- a/tests/ui/proc-macro/auxiliary/span-api-tests.rs
+++ b/tests/ui/proc-macro/auxiliary/span-api-tests.rs
@@ -11,20 +11,9 @@ pub fn reemit(input: TokenStream) -> TokenStream {
}
#[proc_macro]
-pub fn assert_fake_source_file(input: TokenStream) -> TokenStream {
+pub fn assert_local_file(input: TokenStream) -> TokenStream {
for tk in input {
- let source_file = tk.span().source_file();
- assert!(!source_file.is_real(), "Source file is real: {:?}", source_file);
- }
-
- "".parse().unwrap()
-}
-
-#[proc_macro]
-pub fn assert_source_file(input: TokenStream) -> TokenStream {
- for tk in input {
- let source_file = tk.span().source_file();
- assert!(source_file.is_real(), "Source file is not real: {:?}", source_file);
+ assert!(tk.span().local_file().is_some(), "No local file for span: {:?}", tk.span());
}
"".parse().unwrap()
diff --git a/tests/ui/proc-macro/cfg-attr-trace.rs b/tests/ui/proc-macro/cfg-attr-trace.rs
index 140dd10..412c65b 100644
--- a/tests/ui/proc-macro/cfg-attr-trace.rs
+++ b/tests/ui/proc-macro/cfg-attr-trace.rs
@@ -3,7 +3,6 @@
//@ check-pass
//@ proc-macro: test-macros.rs
-#![feature(cfg_boolean_literals)]
#![feature(cfg_eval)]
#[macro_use]
diff --git a/tests/ui/proc-macro/cfg-attr-trace.stdout b/tests/ui/proc-macro/cfg-attr-trace.stdout
index 52f9ff4..33bcfe5 100644
--- a/tests/ui/proc-macro/cfg-attr-trace.stdout
+++ b/tests/ui/proc-macro/cfg-attr-trace.stdout
@@ -4,75 +4,75 @@
Punct {
ch: '#',
spacing: Alone,
- span: #0 bytes(305..306),
+ span: #0 bytes(271..272),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "test_macros",
- span: #0 bytes(322..333),
+ span: #0 bytes(288..299),
},
Punct {
ch: ':',
spacing: Joint,
- span: #0 bytes(333..334),
+ span: #0 bytes(299..300),
},
Punct {
ch: ':',
spacing: Alone,
- span: #0 bytes(334..335),
+ span: #0 bytes(300..301),
},
Ident {
ident: "print_attr",
- span: #0 bytes(335..345),
+ span: #0 bytes(301..311),
},
],
- span: #0 bytes(306..347),
+ span: #0 bytes(272..313),
},
Ident {
ident: "struct",
- span: #0 bytes(348..354),
+ span: #0 bytes(314..320),
},
Ident {
ident: "S",
- span: #0 bytes(355..356),
+ span: #0 bytes(321..322),
},
Punct {
ch: ';',
spacing: Alone,
- span: #0 bytes(356..357),
+ span: #0 bytes(322..323),
},
]
PRINT-ATTR INPUT (DISPLAY): struct S;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
- span: #0 bytes(348..354),
+ span: #0 bytes(314..320),
},
Ident {
ident: "S",
- span: #0 bytes(355..356),
+ span: #0 bytes(321..322),
},
Punct {
ch: ';',
spacing: Alone,
- span: #0 bytes(356..357),
+ span: #0 bytes(322..323),
},
]
PRINT-ATTR INPUT (DISPLAY): struct Z;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
- span: #0 bytes(411..417),
+ span: #0 bytes(377..383),
},
Ident {
ident: "Z",
- span: #0 bytes(418..419),
+ span: #0 bytes(384..385),
},
Punct {
ch: ';',
spacing: Alone,
- span: #0 bytes(419..420),
+ span: #0 bytes(385..386),
},
]
diff --git a/tests/ui/proc-macro/cfg-eval-fail.rs b/tests/ui/proc-macro/cfg-eval-fail.rs
index a259aa2..a94dcd2 100644
--- a/tests/ui/proc-macro/cfg-eval-fail.rs
+++ b/tests/ui/proc-macro/cfg-eval-fail.rs
@@ -2,6 +2,6 @@
#![feature(stmt_expr_attributes)]
fn main() {
- let _ = #[cfg_eval] #[cfg(FALSE)] 0;
+ let _ = #[cfg_eval] #[cfg(false)] 0;
//~^ ERROR removing an expression is not supported in this position
}
diff --git a/tests/ui/proc-macro/cfg-eval-fail.stderr b/tests/ui/proc-macro/cfg-eval-fail.stderr
index 945ad46..7f21e46 100644
--- a/tests/ui/proc-macro/cfg-eval-fail.stderr
+++ b/tests/ui/proc-macro/cfg-eval-fail.stderr
@@ -1,7 +1,7 @@
error: removing an expression is not supported in this position
--> $DIR/cfg-eval-fail.rs:5:25
|
-LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
+LL | let _ = #[cfg_eval] #[cfg(false)] 0;
| ^^^^^^^^^^^^^
error: aborting due to 1 previous error
diff --git a/tests/ui/proc-macro/cfg-eval-inner.rs b/tests/ui/proc-macro/cfg-eval-inner.rs
index 7493f3e..dc4efd6 100644
--- a/tests/ui/proc-macro/cfg-eval-inner.rs
+++ b/tests/ui/proc-macro/cfg-eval-inner.rs
@@ -32,7 +32,7 @@ struct Inner {
#![cfg_attr(not(FALSE), rustc_dummy(evaluated_attr))]
fn bar() {
- #[cfg(FALSE)] let a = 1;
+ #[cfg(false)] let a = 1;
}
}
diff --git a/tests/ui/proc-macro/cfg-eval.rs b/tests/ui/proc-macro/cfg-eval.rs
index 1d9b4f2..ddf3708 100644
--- a/tests/ui/proc-macro/cfg-eval.rs
+++ b/tests/ui/proc-macro/cfg-eval.rs
@@ -15,7 +15,7 @@
#[cfg_eval]
#[print_attr]
struct S1 {
- #[cfg(FALSE)]
+ #[cfg(false)]
field_false: u8,
#[cfg(all(/*true*/))]
#[cfg_attr(FALSE, unknown_attr)]
@@ -24,7 +24,7 @@ struct S1 {
}
#[cfg_eval]
-#[cfg(FALSE)]
+#[cfg(false)]
struct S2 {}
fn main() {
@@ -33,5 +33,5 @@ fn main() {
// expression. `#[cfg]` is not supported inside parenthesized expressions, so this will
// produce an error when attribute collection runs.
let _ = #[cfg_eval] #[print_attr] #[cfg_attr(not(FALSE), rustc_dummy)]
- (#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1,);
+ (#[cfg(false)] 0, #[cfg(all(/*true*/))] 1,);
}
diff --git a/tests/ui/proc-macro/derive-cfg-nested-tokens.rs b/tests/ui/proc-macro/derive-cfg-nested-tokens.rs
index 7d4e8d8..ec6aba0 100644
--- a/tests/ui/proc-macro/derive-cfg-nested-tokens.rs
+++ b/tests/ui/proc-macro/derive-cfg-nested-tokens.rs
@@ -15,7 +15,7 @@ struct S {
// - on eagerly configured `S` (from `impl Copy`), only 11 should be printed
// - on non-configured `S` (from `struct S`), both 10 and 11 should be printed
field: [u8; #[print_attr] {
- #[cfg(FALSE)] { 10 }
+ #[cfg(false)] { 10 }
#[cfg(not(FALSE))] { 11 }
}],
}
diff --git a/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout b/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout
index 05bf21e..9dbddc9 100644
--- a/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout
+++ b/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout
@@ -54,7 +54,7 @@
span: #0 bytes(452..523),
},
]
-PRINT-ATTR INPUT (DISPLAY): { #[cfg(FALSE)] { 10 } #[cfg(not(FALSE))] { 11 } }
+PRINT-ATTR INPUT (DISPLAY): { #[cfg(false)] { 10 } #[cfg(not(FALSE))] { 11 } }
PRINT-ATTR INPUT (DEBUG): TokenStream [
Group {
delimiter: Brace,
@@ -75,7 +75,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: #0 bytes(468..473),
},
],
diff --git a/tests/ui/proc-macro/expand-to-derive.rs b/tests/ui/proc-macro/expand-to-derive.rs
index 0e38e47..05c8e32 100644
--- a/tests/ui/proc-macro/expand-to-derive.rs
+++ b/tests/ui/proc-macro/expand-to-derive.rs
@@ -14,7 +14,7 @@ macro_rules! expand_to_derive {
($item:item) => {
#[derive(Print)]
struct Foo {
- #[cfg(FALSE)] removed: bool,
+ #[cfg(false)] removed: bool,
field: [bool; {
$item
0
@@ -26,7 +26,7 @@ struct Foo {
expand_to_derive! {
#[cfg_attr(not(FALSE), rustc_dummy)]
struct Inner {
- #[cfg(FALSE)] removed_inner_field: bool,
+ #[cfg(false)] removed_inner_field: bool,
other_inner_field: u8,
}
}
diff --git a/tests/ui/proc-macro/inner-attrs.rs b/tests/ui/proc-macro/inner-attrs.rs
index 34c37dd..ca4b202 100644
--- a/tests/ui/proc-macro/inner-attrs.rs
+++ b/tests/ui/proc-macro/inner-attrs.rs
@@ -1,6 +1,5 @@
// gate-test-custom_inner_attributes
-//@ compile-flags: -Z span-debug --error-format human
-//@ error-pattern:expected non-macro inner attribute
+//@ compile-flags: -Z span-debug
//@ proc-macro: test-macros.rs
//@ edition:2018
@@ -63,23 +62,27 @@ fn bar() {
for _ in &[true] {
#![print_attr]
+ //~^ ERROR expected non-macro inner attribute, found attribute macro `print_attr`
}
let _ = {
#![print_attr]
+ //~^ ERROR expected non-macro inner attribute, found attribute macro `print_attr`
};
let _ = async {
#![print_attr]
+ //~^ ERROR expected non-macro inner attribute, found attribute macro `print_attr`
};
{
#![print_attr]
+ //~^ ERROR expected non-macro inner attribute, found attribute macro `print_attr`
};
}
-extern {
+extern { //~ WARN `extern` declarations without an explicit ABI are deprecated
fn weird_extern() {
#![print_target_and_args_consume(tenth)]
}
diff --git a/tests/ui/proc-macro/inner-attrs.stderr b/tests/ui/proc-macro/inner-attrs.stderr
index 8b5fec1..54cccae 100644
--- a/tests/ui/proc-macro/inner-attrs.stderr
+++ b/tests/ui/proc-macro/inner-attrs.stderr
@@ -1,5 +1,5 @@
error: expected non-macro inner attribute, found attribute macro `print_attr`
- --> $DIR/inner-attrs.rs:65:12
+ --> $DIR/inner-attrs.rs:64:12
|
LL | #![print_attr]
| ^^^^^^^^^^ not a non-macro inner attribute
@@ -11,19 +11,19 @@
| ^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_attr`
- --> $DIR/inner-attrs.rs:73:12
+ --> $DIR/inner-attrs.rs:74:12
|
LL | #![print_attr]
| ^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_attr`
- --> $DIR/inner-attrs.rs:77:12
+ --> $DIR/inner-attrs.rs:79:12
|
LL | #![print_attr]
| ^^^^^^^^^^ not a non-macro inner attribute
-warning: extern declarations without an explicit ABI are deprecated
- --> $DIR/inner-attrs.rs:82:1
+warning: `extern` declarations without an explicit ABI are deprecated
+ --> $DIR/inner-attrs.rs:85:1
|
LL | extern {
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
diff --git a/tests/ui/proc-macro/inner-attrs.stdout b/tests/ui/proc-macro/inner-attrs.stdout
index ed47ee2..4496f7b 100644
--- a/tests/ui/proc-macro/inner-attrs.stdout
+++ b/tests/ui/proc-macro/inner-attrs.stdout
@@ -2,7 +2,7 @@
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "first",
- span: $DIR/inner-attrs.rs:18:25: 18:30 (#0),
+ span: $DIR/inner-attrs.rs:17:25: 17:30 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second)] fn foo()
@@ -13,40 +13,40 @@
Punct {
ch: '#',
spacing: Alone,
- span: $DIR/inner-attrs.rs:19:1: 19:2 (#0),
+ span: $DIR/inner-attrs.rs:18:1: 18:2 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:19:3: 19:24 (#0),
+ span: $DIR/inner-attrs.rs:18:3: 18:24 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "second",
- span: $DIR/inner-attrs.rs:19:25: 19:31 (#0),
+ span: $DIR/inner-attrs.rs:18:25: 18:31 (#0),
},
],
- span: $DIR/inner-attrs.rs:19:24: 19:32 (#0),
+ span: $DIR/inner-attrs.rs:18:24: 18:32 (#0),
},
],
- span: $DIR/inner-attrs.rs:19:2: 19:33 (#0),
+ span: $DIR/inner-attrs.rs:18:2: 18:33 (#0),
},
Ident {
ident: "fn",
- span: $DIR/inner-attrs.rs:20:1: 20:3 (#0),
+ span: $DIR/inner-attrs.rs:19:1: 19:3 (#0),
},
Ident {
ident: "foo",
- span: $DIR/inner-attrs.rs:20:4: 20:7 (#0),
+ span: $DIR/inner-attrs.rs:19:4: 19:7 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
- span: $DIR/inner-attrs.rs:20:7: 20:9 (#0),
+ span: $DIR/inner-attrs.rs:19:7: 19:9 (#0),
},
Group {
delimiter: Brace,
@@ -54,6 +54,36 @@
Punct {
ch: '#',
spacing: Joint,
+ span: $DIR/inner-attrs.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "third",
+ span: $DIR/inner-attrs.rs:20:30: 20:35 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:29: 20:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:7: 20:37 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
span: $DIR/inner-attrs.rs:21:5: 21:6 (#0),
},
Punct {
@@ -72,54 +102,24 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "third",
- span: $DIR/inner-attrs.rs:21:30: 21:35 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:21:29: 21:36 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:21:7: 21:37 (#0),
- },
- Punct {
- ch: '#',
- spacing: Joint,
- span: $DIR/inner-attrs.rs:22:5: 22:6 (#0),
- },
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:22:6: 22:7 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:22:8: 22:29 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
ident: "fourth",
- span: $DIR/inner-attrs.rs:22:30: 22:36 (#0),
+ span: $DIR/inner-attrs.rs:21:30: 21:36 (#0),
},
],
- span: $DIR/inner-attrs.rs:22:29: 22:37 (#0),
+ span: $DIR/inner-attrs.rs:21:29: 21:37 (#0),
},
],
- span: $DIR/inner-attrs.rs:22:7: 22:38 (#0),
+ span: $DIR/inner-attrs.rs:21:7: 21:38 (#0),
},
],
- span: $DIR/inner-attrs.rs:20:10: 23:2 (#0),
+ span: $DIR/inner-attrs.rs:19:10: 22:2 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): second
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "second",
- span: $DIR/inner-attrs.rs:19:25: 19:31 (#0),
+ span: $DIR/inner-attrs.rs:18:25: 18:31 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): fn foo()
@@ -129,16 +129,106 @@
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "fn",
- span: $DIR/inner-attrs.rs:20:1: 20:3 (#0),
+ span: $DIR/inner-attrs.rs:19:1: 19:3 (#0),
},
Ident {
ident: "foo",
- span: $DIR/inner-attrs.rs:20:4: 20:7 (#0),
+ span: $DIR/inner-attrs.rs:19:4: 19:7 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
- span: $DIR/inner-attrs.rs:20:7: 20:9 (#0),
+ span: $DIR/inner-attrs.rs:19:7: 19:9 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "third",
+ span: $DIR/inner-attrs.rs:20:30: 20:35 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:29: 20:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:7: 20:37 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:21:5: 21:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:21:6: 21:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:21:8: 21:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "fourth",
+ span: $DIR/inner-attrs.rs:21:30: 21:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:21:29: 21:37 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:21:7: 21:38 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:19:10: 22:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): third
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "third",
+ span: $DIR/inner-attrs.rs:20:30: 20:35 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): fn foo() { #![print_target_and_args(fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/inner-attrs.rs:19:1: 19:3 (#0),
+ },
+ Ident {
+ ident: "foo",
+ span: $DIR/inner-attrs.rs:19:4: 19:7 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:19:7: 19:9 (#0),
},
Group {
delimiter: Brace,
@@ -164,142 +254,52 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "third",
- span: $DIR/inner-attrs.rs:21:30: 21:35 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:21:29: 21:36 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:21:7: 21:37 (#0),
- },
- Punct {
- ch: '#',
- spacing: Joint,
- span: $DIR/inner-attrs.rs:22:5: 22:6 (#0),
- },
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:22:6: 22:7 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:22:8: 22:29 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
ident: "fourth",
- span: $DIR/inner-attrs.rs:22:30: 22:36 (#0),
+ span: $DIR/inner-attrs.rs:21:30: 21:36 (#0),
},
],
- span: $DIR/inner-attrs.rs:22:29: 22:37 (#0),
+ span: $DIR/inner-attrs.rs:21:29: 21:37 (#0),
},
],
- span: $DIR/inner-attrs.rs:22:7: 22:38 (#0),
+ span: $DIR/inner-attrs.rs:21:7: 21:38 (#0),
},
],
- span: $DIR/inner-attrs.rs:20:10: 23:2 (#0),
- },
-]
-PRINT-ATTR_ARGS INPUT (DISPLAY): third
-PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
- Ident {
- ident: "third",
- span: $DIR/inner-attrs.rs:21:30: 21:35 (#0),
- },
-]
-PRINT-ATTR INPUT (DISPLAY): fn foo() { #![print_target_and_args(fourth)] }
-PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] }
-PRINT-ATTR INPUT (DEBUG): TokenStream [
- Ident {
- ident: "fn",
- span: $DIR/inner-attrs.rs:20:1: 20:3 (#0),
- },
- Ident {
- ident: "foo",
- span: $DIR/inner-attrs.rs:20:4: 20:7 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [],
- span: $DIR/inner-attrs.rs:20:7: 20:9 (#0),
- },
- Group {
- delimiter: Brace,
- stream: TokenStream [
- Punct {
- ch: '#',
- spacing: Joint,
- span: $DIR/inner-attrs.rs:22:5: 22:6 (#0),
- },
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:22:6: 22:7 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:22:8: 22:29 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
- ident: "fourth",
- span: $DIR/inner-attrs.rs:22:30: 22:36 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:22:29: 22:37 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:22:7: 22:38 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:20:10: 23:2 (#0),
+ span: $DIR/inner-attrs.rs:19:10: 22:2 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): fourth
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "fourth",
- span: $DIR/inner-attrs.rs:22:30: 22:36 (#0),
+ span: $DIR/inner-attrs.rs:21:30: 21:36 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): fn foo() {}
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "fn",
- span: $DIR/inner-attrs.rs:20:1: 20:3 (#0),
+ span: $DIR/inner-attrs.rs:19:1: 19:3 (#0),
},
Ident {
ident: "foo",
- span: $DIR/inner-attrs.rs:20:4: 20:7 (#0),
+ span: $DIR/inner-attrs.rs:19:4: 19:7 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
- span: $DIR/inner-attrs.rs:20:7: 20:9 (#0),
+ span: $DIR/inner-attrs.rs:19:7: 19:9 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [],
- span: $DIR/inner-attrs.rs:20:10: 23:2 (#0),
+ span: $DIR/inner-attrs.rs:19:10: 22:2 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): mod_first
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "mod_first",
- span: $DIR/inner-attrs.rs:25:25: 25:34 (#0),
+ span: $DIR/inner-attrs.rs:24:25: 24:34 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod
@@ -313,35 +313,35 @@
Punct {
ch: '#',
spacing: Alone,
- span: $DIR/inner-attrs.rs:26:1: 26:2 (#0),
+ span: $DIR/inner-attrs.rs:25:1: 25:2 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:26:3: 26:24 (#0),
+ span: $DIR/inner-attrs.rs:25:3: 25:24 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "mod_second",
- span: $DIR/inner-attrs.rs:26:25: 26:35 (#0),
+ span: $DIR/inner-attrs.rs:25:25: 25:35 (#0),
},
],
- span: $DIR/inner-attrs.rs:26:24: 26:36 (#0),
+ span: $DIR/inner-attrs.rs:25:24: 25:36 (#0),
},
],
- span: $DIR/inner-attrs.rs:26:2: 26:37 (#0),
+ span: $DIR/inner-attrs.rs:25:2: 25:37 (#0),
},
Ident {
ident: "mod",
- span: $DIR/inner-attrs.rs:27:1: 27:4 (#0),
+ span: $DIR/inner-attrs.rs:26:1: 26:4 (#0),
},
Ident {
ident: "inline_mod",
- span: $DIR/inner-attrs.rs:27:5: 27:15 (#0),
+ span: $DIR/inner-attrs.rs:26:5: 26:15 (#0),
},
Group {
delimiter: Brace,
@@ -349,6 +349,36 @@
Punct {
ch: '#',
spacing: Joint,
+ span: $DIR/inner-attrs.rs:27:5: 27:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:27:6: 27:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:27:8: 27:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_third",
+ span: $DIR/inner-attrs.rs:27:30: 27:39 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:29: 27:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:7: 27:41 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
span: $DIR/inner-attrs.rs:28:5: 28:6 (#0),
},
Punct {
@@ -367,54 +397,24 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "mod_third",
- span: $DIR/inner-attrs.rs:28:30: 28:39 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:28:29: 28:40 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:28:7: 28:41 (#0),
- },
- Punct {
- ch: '#',
- spacing: Joint,
- span: $DIR/inner-attrs.rs:29:5: 29:6 (#0),
- },
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:29:6: 29:7 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:29:8: 29:29 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
ident: "mod_fourth",
- span: $DIR/inner-attrs.rs:29:30: 29:40 (#0),
+ span: $DIR/inner-attrs.rs:28:30: 28:40 (#0),
},
],
- span: $DIR/inner-attrs.rs:29:29: 29:41 (#0),
+ span: $DIR/inner-attrs.rs:28:29: 28:41 (#0),
},
],
- span: $DIR/inner-attrs.rs:29:7: 29:42 (#0),
+ span: $DIR/inner-attrs.rs:28:7: 28:42 (#0),
},
],
- span: $DIR/inner-attrs.rs:27:16: 30:2 (#0),
+ span: $DIR/inner-attrs.rs:26:16: 29:2 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): mod_second
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "mod_second",
- span: $DIR/inner-attrs.rs:26:25: 26:35 (#0),
+ span: $DIR/inner-attrs.rs:25:25: 25:35 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): mod inline_mod
@@ -427,11 +427,96 @@
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "mod",
- span: $DIR/inner-attrs.rs:27:1: 27:4 (#0),
+ span: $DIR/inner-attrs.rs:26:1: 26:4 (#0),
},
Ident {
ident: "inline_mod",
- span: $DIR/inner-attrs.rs:27:5: 27:15 (#0),
+ span: $DIR/inner-attrs.rs:26:5: 26:15 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:27:5: 27:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:27:6: 27:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:27:8: 27:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_third",
+ span: $DIR/inner-attrs.rs:27:30: 27:39 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:29: 27:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:7: 27:41 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:28:5: 28:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:28:6: 28:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:28:8: 28:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_fourth",
+ span: $DIR/inner-attrs.rs:28:30: 28:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:28:29: 28:41 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:28:7: 28:42 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:26:16: 29:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod_third",
+ span: $DIR/inner-attrs.rs:27:30: 27:39 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #![print_target_and_args(mod_fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod",
+ span: $DIR/inner-attrs.rs:26:1: 26:4 (#0),
+ },
+ Ident {
+ ident: "inline_mod",
+ span: $DIR/inner-attrs.rs:26:5: 26:15 (#0),
},
Group {
delimiter: Brace,
@@ -457,125 +542,40 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "mod_third",
- span: $DIR/inner-attrs.rs:28:30: 28:39 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:28:29: 28:40 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:28:7: 28:41 (#0),
- },
- Punct {
- ch: '#',
- spacing: Joint,
- span: $DIR/inner-attrs.rs:29:5: 29:6 (#0),
- },
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:29:6: 29:7 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:29:8: 29:29 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
ident: "mod_fourth",
- span: $DIR/inner-attrs.rs:29:30: 29:40 (#0),
+ span: $DIR/inner-attrs.rs:28:30: 28:40 (#0),
},
],
- span: $DIR/inner-attrs.rs:29:29: 29:41 (#0),
+ span: $DIR/inner-attrs.rs:28:29: 28:41 (#0),
},
],
- span: $DIR/inner-attrs.rs:29:7: 29:42 (#0),
+ span: $DIR/inner-attrs.rs:28:7: 28:42 (#0),
},
],
- span: $DIR/inner-attrs.rs:27:16: 30:2 (#0),
- },
-]
-PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third
-PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
- Ident {
- ident: "mod_third",
- span: $DIR/inner-attrs.rs:28:30: 28:39 (#0),
- },
-]
-PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #![print_target_and_args(mod_fourth)] }
-PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] }
-PRINT-ATTR INPUT (DEBUG): TokenStream [
- Ident {
- ident: "mod",
- span: $DIR/inner-attrs.rs:27:1: 27:4 (#0),
- },
- Ident {
- ident: "inline_mod",
- span: $DIR/inner-attrs.rs:27:5: 27:15 (#0),
- },
- Group {
- delimiter: Brace,
- stream: TokenStream [
- Punct {
- ch: '#',
- spacing: Joint,
- span: $DIR/inner-attrs.rs:29:5: 29:6 (#0),
- },
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:29:6: 29:7 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "print_target_and_args",
- span: $DIR/inner-attrs.rs:29:8: 29:29 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
- ident: "mod_fourth",
- span: $DIR/inner-attrs.rs:29:30: 29:40 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:29:29: 29:41 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:29:7: 29:42 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:27:16: 30:2 (#0),
+ span: $DIR/inner-attrs.rs:26:16: 29:2 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): mod_fourth
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "mod_fourth",
- span: $DIR/inner-attrs.rs:29:30: 29:40 (#0),
+ span: $DIR/inner-attrs.rs:28:30: 28:40 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): mod inline_mod {}
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "mod",
- span: $DIR/inner-attrs.rs:27:1: 27:4 (#0),
+ span: $DIR/inner-attrs.rs:26:1: 26:4 (#0),
},
Ident {
ident: "inline_mod",
- span: $DIR/inner-attrs.rs:27:5: 27:15 (#0),
+ span: $DIR/inner-attrs.rs:26:5: 26:15 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [],
- span: $DIR/inner-attrs.rs:27:16: 30:2 (#0),
+ span: $DIR/inner-attrs.rs:26:16: 29:2 (#0),
},
]
PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint
@@ -585,63 +585,63 @@
PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
- span: $DIR/inner-attrs.rs:37:1: 37:7 (#0),
+ span: $DIR/inner-attrs.rs:36:1: 36:7 (#0),
},
Ident {
ident: "MyDerivePrint",
- span: $DIR/inner-attrs.rs:37:8: 37:21 (#0),
+ span: $DIR/inner-attrs.rs:36:8: 36:21 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [
Ident {
ident: "field",
- span: $DIR/inner-attrs.rs:38:5: 38:10 (#0),
+ span: $DIR/inner-attrs.rs:37:5: 37:10 (#0),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/inner-attrs.rs:38:10: 38:11 (#0),
+ span: $DIR/inner-attrs.rs:37:10: 37:11 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "u8",
- span: $DIR/inner-attrs.rs:38:13: 38:15 (#0),
+ span: $DIR/inner-attrs.rs:37:13: 37:15 (#0),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/inner-attrs.rs:38:15: 38:16 (#0),
+ span: $DIR/inner-attrs.rs:37:15: 37:16 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [
Ident {
ident: "match",
- span: $DIR/inner-attrs.rs:39:9: 39:14 (#0),
+ span: $DIR/inner-attrs.rs:38:9: 38:14 (#0),
},
Ident {
ident: "true",
- span: $DIR/inner-attrs.rs:39:15: 39:19 (#0),
+ span: $DIR/inner-attrs.rs:38:15: 38:19 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [
Ident {
ident: "_",
- span: $DIR/inner-attrs.rs:40:13: 40:14 (#0),
+ span: $DIR/inner-attrs.rs:39:13: 39:14 (#0),
},
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/inner-attrs.rs:40:15: 40:16 (#0),
+ span: $DIR/inner-attrs.rs:39:15: 39:16 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/inner-attrs.rs:40:16: 40:17 (#0),
+ span: $DIR/inner-attrs.rs:39:16: 39:17 (#0),
},
Group {
delimiter: Brace,
@@ -649,69 +649,69 @@
Punct {
ch: '#',
spacing: Joint,
- span: $DIR/inner-attrs.rs:41:17: 41:18 (#0),
+ span: $DIR/inner-attrs.rs:40:17: 40:18 (#0),
},
Punct {
ch: '!',
spacing: Alone,
- span: $DIR/inner-attrs.rs:41:18: 41:19 (#0),
+ span: $DIR/inner-attrs.rs:40:18: 40:19 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "rustc_dummy",
- span: $DIR/inner-attrs.rs:41:41: 41:52 (#0),
+ span: $DIR/inner-attrs.rs:40:41: 40:52 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "third",
- span: $DIR/inner-attrs.rs:41:53: 41:58 (#0),
+ span: $DIR/inner-attrs.rs:40:53: 40:58 (#0),
},
],
- span: $DIR/inner-attrs.rs:41:52: 41:59 (#0),
+ span: $DIR/inner-attrs.rs:40:52: 40:59 (#0),
},
],
- span: $DIR/inner-attrs.rs:41:19: 41:61 (#0),
+ span: $DIR/inner-attrs.rs:40:19: 40:61 (#0),
},
Ident {
ident: "true",
- span: $DIR/inner-attrs.rs:42:17: 42:21 (#0),
+ span: $DIR/inner-attrs.rs:41:17: 41:21 (#0),
},
],
- span: $DIR/inner-attrs.rs:40:18: 43:14 (#0),
+ span: $DIR/inner-attrs.rs:39:18: 42:14 (#0),
},
],
- span: $DIR/inner-attrs.rs:39:20: 44:10 (#0),
+ span: $DIR/inner-attrs.rs:38:20: 43:10 (#0),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/inner-attrs.rs:44:10: 44:11 (#0),
+ span: $DIR/inner-attrs.rs:43:10: 43:11 (#0),
},
Literal {
kind: Integer,
symbol: "0",
suffix: None,
- span: $DIR/inner-attrs.rs:45:9: 45:10 (#0),
+ span: $DIR/inner-attrs.rs:44:9: 44:10 (#0),
},
],
- span: $DIR/inner-attrs.rs:38:17: 46:6 (#0),
+ span: $DIR/inner-attrs.rs:37:17: 45:6 (#0),
},
],
- span: $DIR/inner-attrs.rs:38:12: 46:7 (#0),
+ span: $DIR/inner-attrs.rs:37:12: 45:7 (#0),
},
],
- span: $DIR/inner-attrs.rs:37:22: 47:2 (#0),
+ span: $DIR/inner-attrs.rs:36:22: 46:2 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "tuple_attrs",
- span: $DIR/inner-attrs.rs:50:29: 50:40 (#0),
+ span: $DIR/inner-attrs.rs:49:29: 49:40 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 });
@@ -724,23 +724,23 @@
kind: Integer,
symbol: "3",
suffix: None,
- span: $DIR/inner-attrs.rs:51:9: 51:10 (#0),
+ span: $DIR/inner-attrs.rs:50:9: 50:10 (#0),
},
Punct {
ch: ',',
spacing: Alone,
- span: $DIR/inner-attrs.rs:51:10: 51:11 (#0),
+ span: $DIR/inner-attrs.rs:50:10: 50:11 (#0),
},
Literal {
kind: Integer,
symbol: "4",
suffix: None,
- span: $DIR/inner-attrs.rs:51:12: 51:13 (#0),
+ span: $DIR/inner-attrs.rs:50:12: 50:13 (#0),
},
Punct {
ch: ',',
spacing: Alone,
- span: $DIR/inner-attrs.rs:51:13: 51:14 (#0),
+ span: $DIR/inner-attrs.rs:50:13: 50:14 (#0),
},
Group {
delimiter: Brace,
@@ -748,85 +748,85 @@
Punct {
ch: '#',
spacing: Joint,
+ span: $DIR/inner-attrs.rs:51:13: 51:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:51:14: 51:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg_attr",
+ span: $DIR/inner-attrs.rs:51:16: 51:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/inner-attrs.rs:51:25: 51:28 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/inner-attrs.rs:51:29: 51:34 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:51:28: 51:35 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:51:35: 51:36 (#0),
+ },
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/inner-attrs.rs:51:37: 51:48 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "innermost",
+ span: $DIR/inner-attrs.rs:51:49: 51:58 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:51:48: 51:59 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:51:24: 51:60 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:51:15: 51:61 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "5",
+ suffix: None,
span: $DIR/inner-attrs.rs:52:13: 52:14 (#0),
},
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:52:14: 52:15 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "cfg_attr",
- span: $DIR/inner-attrs.rs:52:16: 52:24 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
- ident: "not",
- span: $DIR/inner-attrs.rs:52:25: 52:28 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
- ident: "FALSE",
- span: $DIR/inner-attrs.rs:52:29: 52:34 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:52:28: 52:35 (#0),
- },
- Punct {
- ch: ',',
- spacing: Alone,
- span: $DIR/inner-attrs.rs:52:35: 52:36 (#0),
- },
- Ident {
- ident: "rustc_dummy",
- span: $DIR/inner-attrs.rs:52:37: 52:48 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
- ident: "innermost",
- span: $DIR/inner-attrs.rs:52:49: 52:58 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:52:48: 52:59 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:52:24: 52:60 (#0),
- },
- ],
- span: $DIR/inner-attrs.rs:52:15: 52:61 (#0),
- },
- Literal {
- kind: Integer,
- symbol: "5",
- suffix: None,
- span: $DIR/inner-attrs.rs:53:13: 53:14 (#0),
- },
],
- span: $DIR/inner-attrs.rs:51:15: 54:10 (#0),
+ span: $DIR/inner-attrs.rs:50:15: 53:10 (#0),
},
],
- span: $DIR/inner-attrs.rs:50:43: 55:6 (#0),
+ span: $DIR/inner-attrs.rs:49:43: 54:6 (#0),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/inner-attrs.rs:55:6: 55:7 (#0),
+ span: $DIR/inner-attrs.rs:54:6: 54:7 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "tuple_attrs",
- span: $DIR/inner-attrs.rs:57:29: 57:40 (#0),
+ span: $DIR/inner-attrs.rs:56:29: 56:40 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 });
@@ -839,23 +839,23 @@
kind: Integer,
symbol: "3",
suffix: None,
- span: $DIR/inner-attrs.rs:58:9: 58:10 (#0),
+ span: $DIR/inner-attrs.rs:57:9: 57:10 (#0),
},
Punct {
ch: ',',
spacing: Alone,
- span: $DIR/inner-attrs.rs:58:10: 58:11 (#0),
+ span: $DIR/inner-attrs.rs:57:10: 57:11 (#0),
},
Literal {
kind: Integer,
symbol: "4",
suffix: None,
- span: $DIR/inner-attrs.rs:58:12: 58:13 (#0),
+ span: $DIR/inner-attrs.rs:57:12: 57:13 (#0),
},
Punct {
ch: ',',
spacing: Alone,
- span: $DIR/inner-attrs.rs:58:13: 58:14 (#0),
+ span: $DIR/inner-attrs.rs:57:13: 57:14 (#0),
},
Group {
delimiter: Brace,
@@ -863,105 +863,105 @@
Punct {
ch: '#',
spacing: Joint,
- span: $DIR/inner-attrs.rs:59:13: 59:14 (#0),
+ span: $DIR/inner-attrs.rs:58:13: 58:14 (#0),
},
Punct {
ch: '!',
spacing: Alone,
- span: $DIR/inner-attrs.rs:59:14: 59:15 (#0),
+ span: $DIR/inner-attrs.rs:58:14: 58:15 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "cfg_attr",
- span: $DIR/inner-attrs.rs:59:16: 59:24 (#0),
+ span: $DIR/inner-attrs.rs:58:16: 58:24 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "not",
- span: $DIR/inner-attrs.rs:59:25: 59:28 (#0),
+ span: $DIR/inner-attrs.rs:58:25: 58:28 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "FALSE",
- span: $DIR/inner-attrs.rs:59:29: 59:34 (#0),
+ span: $DIR/inner-attrs.rs:58:29: 58:34 (#0),
},
],
- span: $DIR/inner-attrs.rs:59:28: 59:35 (#0),
+ span: $DIR/inner-attrs.rs:58:28: 58:35 (#0),
},
Punct {
ch: ',',
spacing: Alone,
- span: $DIR/inner-attrs.rs:59:35: 59:36 (#0),
+ span: $DIR/inner-attrs.rs:58:35: 58:36 (#0),
},
Ident {
ident: "rustc_dummy",
- span: $DIR/inner-attrs.rs:59:37: 59:48 (#0),
+ span: $DIR/inner-attrs.rs:58:37: 58:48 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "innermost",
- span: $DIR/inner-attrs.rs:59:49: 59:58 (#0),
+ span: $DIR/inner-attrs.rs:58:49: 58:58 (#0),
},
],
- span: $DIR/inner-attrs.rs:59:48: 59:59 (#0),
+ span: $DIR/inner-attrs.rs:58:48: 58:59 (#0),
},
],
- span: $DIR/inner-attrs.rs:59:24: 59:60 (#0),
+ span: $DIR/inner-attrs.rs:58:24: 58:60 (#0),
},
],
- span: $DIR/inner-attrs.rs:59:15: 59:61 (#0),
+ span: $DIR/inner-attrs.rs:58:15: 58:61 (#0),
},
Literal {
kind: Integer,
symbol: "5",
suffix: None,
- span: $DIR/inner-attrs.rs:60:13: 60:14 (#0),
+ span: $DIR/inner-attrs.rs:59:13: 59:14 (#0),
},
],
- span: $DIR/inner-attrs.rs:58:15: 61:10 (#0),
+ span: $DIR/inner-attrs.rs:57:15: 60:10 (#0),
},
],
- span: $DIR/inner-attrs.rs:57:43: 62:6 (#0),
+ span: $DIR/inner-attrs.rs:56:43: 61:6 (#0),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/inner-attrs.rs:62:6: 62:7 (#0),
+ span: $DIR/inner-attrs.rs:61:6: 61:7 (#0),
},
]
PRINT-ATTR_ARGS INPUT (DISPLAY): tenth
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "tenth",
- span: $DIR/inner-attrs.rs:84:42: 84:47 (#0),
+ span: $DIR/inner-attrs.rs:87:42: 87:47 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): fn weird_extern() {}
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "fn",
- span: $DIR/inner-attrs.rs:83:5: 83:7 (#0),
+ span: $DIR/inner-attrs.rs:86:5: 86:7 (#0),
},
Ident {
ident: "weird_extern",
- span: $DIR/inner-attrs.rs:83:8: 83:20 (#0),
+ span: $DIR/inner-attrs.rs:86:8: 86:20 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
- span: $DIR/inner-attrs.rs:83:20: 83:22 (#0),
+ span: $DIR/inner-attrs.rs:86:20: 86:22 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [],
- span: $DIR/inner-attrs.rs:83:23: 85:6 (#0),
+ span: $DIR/inner-attrs.rs:86:23: 88:6 (#0),
},
]
diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.rs b/tests/ui/proc-macro/issue-75930-derive-cfg.rs
index 376a8ea..f0851b3 100644
--- a/tests/ui/proc-macro/issue-75930-derive-cfg.rs
+++ b/tests/ui/proc-macro/issue-75930-derive-cfg.rs
@@ -31,7 +31,7 @@
//
// It is because of this code from below:
// ```
-// struct Foo<#[cfg(FALSE)] A, B>
+// struct Foo<#[cfg(false)] A, B>
// ```
// When the token stream is formed during parsing, `<` is followed immediately
// by `#`, which is punctuation, so it is marked `Joint`. But before being
@@ -51,22 +51,22 @@
#[print_attr]
#[derive(Print)]
#[print_helper(b)]
-struct Foo<#[cfg(FALSE)] A, B> {
- #[cfg(FALSE)] first: String,
+struct Foo<#[cfg(false)] A, B> {
+ #[cfg(false)] first: String,
#[cfg_attr(FALSE, deny(warnings))] second: bool,
third: [u8; {
- #[cfg(FALSE)] struct Bar;
+ #[cfg(false)] struct Bar;
#[cfg(not(FALSE))] struct Inner;
- #[cfg(FALSE)] let a = 25;
+ #[cfg(false)] let a = 25;
match true {
- #[cfg(FALSE)] true => {},
+ #[cfg(false)] true => {},
#[cfg_attr(not(FALSE), allow(warnings))] false => {},
_ => {}
};
#[print_helper(should_be_removed)]
fn removed_fn() {
- #![cfg(FALSE)]
+ #![cfg(false)]
}
#[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() {
@@ -76,22 +76,22 @@ fn removed_fn() {
enum TupleEnum {
Foo(
- #[cfg(FALSE)] u8,
- #[cfg(FALSE)] bool,
+ #[cfg(false)] u8,
+ #[cfg(false)] bool,
#[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] String, u8
+ #[cfg(false)] String, u8
)
}
struct TupleStruct(
- #[cfg(FALSE)] String,
+ #[cfg(false)] String,
#[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] bool,
+ #[cfg(false)] bool,
u8
);
fn plain_removed_fn() {
- #![cfg_attr(not(FALSE), cfg(FALSE))]
+ #![cfg_attr(not(FALSE), cfg(false))]
}
0
diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout
index 4dcf2b7..549621f 100644
--- a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout
+++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout
@@ -1,73 +1,73 @@
PRINT-ATTR INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
-struct Foo<#[cfg(FALSE)] A, B>
+struct Foo<#[cfg(false)] A, B>
{
- #[cfg(FALSE)] first: String, #[cfg_attr(FALSE, deny(warnings))] second:
+ #[cfg(false)] first: String, #[cfg_attr(FALSE, deny(warnings))] second:
bool, third:
[u8;
{
- #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner;
- #[cfg(FALSE)] let a = 25; match true
+ #[cfg(false)] struct Bar; #[cfg(not(FALSE))] struct Inner;
+ #[cfg(false)] let a = 25; match true
{
- #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
+ #[cfg(false)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
false => {}, _ => {}
}; #[print_helper(should_be_removed)] fn removed_fn()
- { #![cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
+ { #![cfg(false)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
{ #![cfg(not(FALSE))] let my_val = true; } enum TupleEnum
{
- Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] String, u8)
+ Foo(#[cfg(false)] u8, #[cfg(false)] bool, #[cfg(not(FALSE))] i32,
+ #[cfg(false)] String, u8)
} struct
- TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] bool, u8); fn plain_removed_fn()
- { #![cfg_attr(not(FALSE), cfg(FALSE))] } 0
+ TupleStruct(#[cfg(false)] String, #[cfg(not(FALSE))] i32,
+ #[cfg(false)] bool, u8); fn plain_removed_fn()
+ { #![cfg_attr(not(FALSE), cfg(false))] } 0
}], #[print_helper(d)] fourth: B
}
PRINT-ATTR RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
-struct Foo <#[cfg(FALSE)] A, B >
+struct Foo <#[cfg(false)] A, B >
{
- #[cfg(FALSE)] first: String, #[cfg_attr(FALSE, deny(warnings))] second:
+ #[cfg(false)] first: String, #[cfg_attr(FALSE, deny(warnings))] second:
bool, third:
[u8;
{
- #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner;
- #[cfg(FALSE)] let a = 25; match true
+ #[cfg(false)] struct Bar; #[cfg(not(FALSE))] struct Inner;
+ #[cfg(false)] let a = 25; match true
{
- #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
+ #[cfg(false)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
false => {}, _ => {}
}; #[print_helper(should_be_removed)] fn removed_fn()
- { #![cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
+ { #![cfg(false)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
{ #![cfg(not(FALSE))] let my_val = true; } enum TupleEnum
{
- Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] String, u8)
+ Foo(#[cfg(false)] u8, #[cfg(false)] bool, #[cfg(not(FALSE))] i32,
+ #[cfg(false)] String, u8)
} struct
- TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] bool, u8); fn plain_removed_fn()
- { #![cfg_attr(not(FALSE), cfg(FALSE))] } 0
+ TupleStruct(#[cfg(false)] String, #[cfg(not(FALSE))] i32,
+ #[cfg(false)] bool, u8); fn plain_removed_fn()
+ { #![cfg_attr(not(FALSE), cfg(false))] } 0
}], #[print_helper(d)] fourth: B
}
PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
-struct Foo <#[cfg(FALSE)] A, B >
+struct Foo <#[cfg(false)] A, B >
{
- #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second :
+ #[cfg(false)] first : String, #[cfg_attr(FALSE, deny(warnings))] second :
bool, third :
[u8;
{
- #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner;
- #[cfg(FALSE)] let a = 25; match true
+ #[cfg(false)] struct Bar; #[cfg(not(FALSE))] struct Inner;
+ #[cfg(false)] let a = 25; match true
{
- #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
+ #[cfg(false)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
false => {}, _ => {}
}; #[print_helper(should_be_removed)] fn removed_fn()
- { #! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
+ { #! [cfg(false)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
{ #! [cfg(not(FALSE))] let my_val = true; } enum TupleEnum
{
- Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] String, u8)
+ Foo(#[cfg(false)] u8, #[cfg(false)] bool, #[cfg(not(FALSE))] i32,
+ #[cfg(false)] String, u8)
} struct
- TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32,
- #[cfg(FALSE)] bool, u8); fn plain_removed_fn()
- { #! [cfg_attr(not(FALSE), cfg(FALSE))] } 0
+ TupleStruct(#[cfg(false)] String, #[cfg(not(FALSE))] i32,
+ #[cfg(false)] bool, u8); fn plain_removed_fn()
+ { #! [cfg_attr(not(FALSE), cfg(false))] } 0
}], #[print_helper(d)] fourth : B
}
PRINT-ATTR INPUT (DEBUG): TokenStream [
@@ -200,7 +200,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:54:18: 54:23 (#0),
},
],
@@ -246,7 +246,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:55:11: 55:16 (#0),
},
],
@@ -375,7 +375,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:58:15: 58:20 (#0),
},
],
@@ -461,7 +461,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:60:15: 60:20 (#0),
},
],
@@ -521,7 +521,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:62:19: 62:24 (#0),
},
],
@@ -721,7 +721,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:69:20: 69:25 (#0),
},
],
@@ -908,7 +908,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:79:23: 79:28 (#0),
},
],
@@ -942,7 +942,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:80:23: 80:28 (#0),
},
],
@@ -1020,7 +1020,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:82:23: 82:28 (#0),
},
],
@@ -1075,7 +1075,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:87:19: 87:24 (#0),
},
],
@@ -1153,7 +1153,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:89:19: 89:24 (#0),
},
],
@@ -1246,7 +1246,7 @@
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "FALSE",
+ ident: "false",
span: $DIR/issue-75930-derive-cfg.rs:94:41: 94:46 (#0),
},
],
diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout
index 1ee7179..1734b9a 100644
--- a/tests/ui/proc-macro/meta-macro-hygiene.stdout
+++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout
@@ -60,11 +60,11 @@
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
-#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
+#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiOpaque)
#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
#5: parent: #3, outer_mark: (crate0::{{expn3}}, Transparent)
-#6: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent)
+#6: parent: #0, outer_mark: (crate0::{{expn3}}, SemiOpaque)
#7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
#8: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent)
-#9: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent)
+#9: parent: #4, outer_mark: (crate0::{{expn4}}, SemiOpaque)
*/
diff --git a/tests/ui/proc-macro/module.rs b/tests/ui/proc-macro/module.rs
index 210c059..5878f1b 100644
--- a/tests/ui/proc-macro/module.rs
+++ b/tests/ui/proc-macro/module.rs
@@ -1 +1 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `./attributes-on-modules-fail.rs`)
diff --git a/tests/ui/proc-macro/module_with_attrs.rs b/tests/ui/proc-macro/module_with_attrs.rs
index 8a4ca92..7e4ec97 100644
--- a/tests/ui/proc-macro/module_with_attrs.rs
+++ b/tests/ui/proc-macro/module_with_attrs.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `../inner-attr-non-inline-mod.rs`)
#![rustfmt::skip]
#![print_attr]
diff --git a/tests/ui/proc-macro/nested-derive-cfg.rs b/tests/ui/proc-macro/nested-derive-cfg.rs
index bd8f231..b3dcfb7 100644
--- a/tests/ui/proc-macro/nested-derive-cfg.rs
+++ b/tests/ui/proc-macro/nested-derive-cfg.rs
@@ -10,10 +10,10 @@
#[derive(Print)]
struct Foo {
- #[cfg(FALSE)] removed: bool,
+ #[cfg(false)] removed: bool,
my_array: [bool; {
struct Inner {
- #[cfg(FALSE)] removed_inner_field: u8,
+ #[cfg(false)] removed_inner_field: u8,
non_removed_inner_field: usize
}
0
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.rs b/tests/ui/proc-macro/nonterminal-token-hygiene.rs
index e2aedb2..b7b0d1e 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.rs
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.rs
@@ -8,6 +8,7 @@
//@ normalize-stdout: "expn\d{3,}" -> "expnNNN"
//@ normalize-stdout: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */"
//@ proc-macro: test-macros.rs
+//@ edition: 2015
#![feature(decl_macro)]
#![no_std] // Don't load unnecessary hygiene information from std
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
index 6fd6cb4..4225731 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -5,19 +5,19 @@
stream: TokenStream [
Ident {
ident: "struct",
- span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5),
+ span: $DIR/nonterminal-token-hygiene.rs:33:5: 33:11 (#5),
},
Ident {
ident: "S",
- span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5),
+ span: $DIR/nonterminal-token-hygiene.rs:33:12: 33:13 (#5),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5),
+ span: $DIR/nonterminal-token-hygiene.rs:33:13: 33:14 (#5),
},
],
- span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4),
+ span: $DIR/nonterminal-token-hygiene.rs:23:27: 23:32 (#4),
},
]
#![feature /* 0#0 */(prelude_import)]
@@ -32,6 +32,7 @@
//@ normalize-stdout: "expn\d{3,}" -> "expnNNN"
//@ normalize-stdout: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */"
//@ proc-macro: test-macros.rs
+//@ edition: 2015
#![feature /* 0#0 */(decl_macro)]
#![no_std /* 0#0 */]
@@ -82,10 +83,10 @@
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
-#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
+#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiOpaque)
#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque)
#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
#6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent)
-#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
+#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiOpaque)
*/
diff --git a/tests/ui/proc-macro/outer/inner.rs b/tests/ui/proc-macro/outer/inner.rs
index 210c059..d0f2087 100644
--- a/tests/ui/proc-macro/outer/inner.rs
+++ b/tests/ui/proc-macro/outer/inner.rs
@@ -1 +1 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `../attributes-on-modules-fail.rs`)
diff --git a/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs
index f89098f..a27176a 100644
--- a/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs
+++ b/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `../../../pretty-print-hack-show.rs`)
#[derive(Print)]
enum ProceduralMasqueradeDummyType {
diff --git a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs
index f89098f..a27176a 100644
--- a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs
+++ b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `../../../pretty-print-hack-show.rs`)
#[derive(Print)]
enum ProceduralMasqueradeDummyType {
diff --git a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs
index f89098f..765ee4b 100644
--- a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs
+++ b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs
@@ -1,4 +1,4 @@
-//@ ignore-test (auxiliary, used by other tests)
+//@ ignore-auxiliary (used by `../../../pretty-print-hack/hide.rs`)
#[derive(Print)]
enum ProceduralMasqueradeDummyType {
diff --git a/tests/ui/proc-macro/quote/debug.rs b/tests/ui/proc-macro/quote/debug.rs
index ce11307..ce1ef81 100644
--- a/tests/ui/proc-macro/quote/debug.rs
+++ b/tests/ui/proc-macro/quote/debug.rs
@@ -3,6 +3,7 @@
//@ no-prefer-dynamic
//@ compile-flags: -Z unpretty=expanded
//@ needs-unwind compiling proc macros with panic=abort causes a warning
+//@ edition: 2015
//
// This file is not actually used as a proc-macro - instead,
// it's just used to show the output of the `quote!` macro
diff --git a/tests/ui/proc-macro/quote/debug.stdout b/tests/ui/proc-macro/quote/debug.stdout
index 3eaad9e..6ebb3a3 100644
--- a/tests/ui/proc-macro/quote/debug.stdout
+++ b/tests/ui/proc-macro/quote/debug.stdout
@@ -5,6 +5,7 @@
//@ no-prefer-dynamic
//@ compile-flags: -Z unpretty=expanded
//@ needs-unwind compiling proc macros with panic=abort causes a warning
+//@ edition: 2015
//
// This file is not actually used as a proc-macro - instead,
// it's just used to show the output of the `quote!` macro
diff --git a/tests/ui/proc-macro/span-api-tests.rs b/tests/ui/proc-macro/span-api-tests.rs
index ac42a7e..792859e 100644
--- a/tests/ui/proc-macro/span-api-tests.rs
+++ b/tests/ui/proc-macro/span-api-tests.rs
@@ -8,26 +8,24 @@
extern crate span_api_tests;
-// FIXME(69775): Investigate `assert_fake_source_file`.
-
-use span_api_tests::{reemit, assert_source_file, macro_stringify};
+use span_api_tests::{reemit, assert_local_file, macro_stringify};
macro_rules! say_hello {
($macname:ident) => ( $macname! { "Hello, world!" })
}
-assert_source_file! { "Hello, world!" }
+assert_local_file! { "Hello, world!" }
-say_hello! { assert_source_file }
+say_hello! { assert_local_file }
reemit_legacy! {
- assert_source_file! { "Hello, world!" }
+ assert_local_file! { "Hello, world!" }
}
-say_hello_extern! { assert_source_file }
+say_hello_extern! { assert_local_file }
reemit! {
- assert_source_file! { "Hello, world!" }
+ assert_local_file! { "Hello, world!" }
}
fn main() {
diff --git a/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs
new file mode 100644
index 0000000..b3310ac
--- /dev/null
+++ b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+#![deny(unreachable_code)]
+#![deny(unused)]
+
+pub enum Void {}
+
+pub struct S<T>(T);
+
+pub fn foo(void: Void, void1: Void) {
+ let s = S(void);
+ drop(s);
+ let s1 = S { 0: void1 };
+ drop(s1);
+}
+
+fn main() {}
diff --git a/tests/ui/regions/region-invariant-static-error-reporting.rs b/tests/ui/regions/region-invariant-static-error-reporting.rs
index e58eea3..9792c10 100644
--- a/tests/ui/regions/region-invariant-static-error-reporting.rs
+++ b/tests/ui/regions/region-invariant-static-error-reporting.rs
@@ -3,7 +3,7 @@
// over time, but this test used to exhibit some pretty bogus messages
// that were not remotely helpful.
-//@ error-pattern:requires that `'a` must outlive `'static`
+//@ dont-require-annotations: NOTE
struct Invariant<'a>(Option<&'a mut &'a mut ()>);
@@ -14,6 +14,7 @@ fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
x.unwrap()
} else {
mk_static() //~ ERROR lifetime may not live long enough
+ //~| NOTE assignment requires that `'a` must outlive `'static`
};
f(bad);
}
diff --git a/tests/ui/resolve/auxiliary/empty.rs b/tests/ui/resolve/auxiliary/empty.rs
new file mode 100644
index 0000000..bd9ec07
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/empty.rs
@@ -0,0 +1 @@
+// Intentionally empty.
diff --git a/tests/ui/resolve/prim-crate-partial-res.rs b/tests/ui/resolve/prim-crate-partial-res.rs
new file mode 100644
index 0000000..955f4fa
--- /dev/null
+++ b/tests/ui/resolve/prim-crate-partial-res.rs
@@ -0,0 +1,8 @@
+//@ aux-build: empty.rs
+
+extern crate empty as usize;
+
+fn foo() -> usize<()> { 0 }
+//~^ ERROR type arguments are not allowed on builtin type `usize`
+
+fn main() {}
diff --git a/tests/ui/resolve/prim-crate-partial-res.stderr b/tests/ui/resolve/prim-crate-partial-res.stderr
new file mode 100644
index 0000000..d10d37c
--- /dev/null
+++ b/tests/ui/resolve/prim-crate-partial-res.stderr
@@ -0,0 +1,17 @@
+error[E0109]: type arguments are not allowed on builtin type `usize`
+ --> $DIR/prim-crate-partial-res.rs:5:19
+ |
+LL | fn foo() -> usize<()> { 0 }
+ | ----- ^^ type argument not allowed
+ | |
+ | not allowed on builtin type `usize`
+ |
+help: primitive type `usize` doesn't have generic parameters
+ |
+LL - fn foo() -> usize<()> { 0 }
+LL + fn foo() -> usize { 0 }
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
index f1f53e3..400969c 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
@@ -4,11 +4,11 @@
LL | fn main() -> Something {
| ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
|
-note: required by a bound in `Main::{synthetic#0}`
+note: required by a bound in `Main::{anon_assoc#0}`
--> $DIR/issue-103052-2.rs:3:27
|
LL | fn main() -> impl std::process::Termination;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{synthetic#0}`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{anon_assoc#0}`
error: aborting due to 1 previous error
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
index 110c03d..983fe87 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
@@ -64,7 +64,7 @@ macro_rules! use_expr {
//~^ ERROR expected expression, found `let` statement
//~| ERROR expected expression, found `let` statement
match () {
- #[cfg(FALSE)]
+ #[cfg(false)]
() if let 0 = 1 => {}
//~^ ERROR `if let` guards are experimental
_ => {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs
index f12824d..0e71a9d 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs
@@ -3,7 +3,7 @@
#![feature(if_let_guard)]
#![feature(let_chains)]
-#[cfg(FALSE)]
+#[cfg(false)]
fn un_cfged() {
match () {
() if let 0 = 1 => {}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs
index 8d78264..16165c4 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs
@@ -1,5 +1,6 @@
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
fn main() {
if let 0 = 1 {}
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout
index 1c103f0..e2e45ae 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout
@@ -6,5 +6,6 @@
extern crate std;
//@ check-pass
//@ compile-flags: -Z unpretty=expanded
+//@ edition: 2015
fn main() { if let 0 = 1 {} }
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
index 99f99c2..0b0abe6 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -340,12 +340,12 @@ fn _check_try_binds_tighter() -> Result<(), ()> {
//~| ERROR expected expression, found `let` statement
{
- #[cfg(FALSE)]
+ #[cfg(false)]
let x = true && let y = 1;
//~^ ERROR expected expression, found `let` statement
}
- #[cfg(FALSE)]
+ #[cfg(false)]
{
[1, 2, 3][let _ = ()]
//~^ ERROR expected expression, found `let` statement
@@ -436,11 +436,11 @@ fn with_parenthesis() {
//[no_feature]~^ ERROR `let` expressions in this position are unstable
}
- #[cfg(FALSE)]
+ #[cfg(false)]
let x = (true && let y = 1);
//~^ ERROR expected expression, found `let` statement
- #[cfg(FALSE)]
+ #[cfg(false)]
{
([1, 2, 3][let _ = ()])
//~^ ERROR expected expression, found `let` statement
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
index 2087fc4..dad02b7 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs
@@ -51,7 +51,7 @@ macro_rules! use_expr {
while $e {}
}
}
- #[cfg(FALSE)] (let 0 = 1);
+ #[cfg(false)] (let 0 = 1);
//~^ ERROR expected expression, found `let` statement
use_expr!(let 0 = 1);
//~^ ERROR no rules expected keyword `let`
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
index 7c874ae..b9dac47 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr
@@ -1,7 +1,7 @@
error: expected expression, found `let` statement
--> $DIR/feature-gate.rs:54:20
|
-LL | #[cfg(FALSE)] (let 0 = 1);
+LL | #[cfg(false)] (let 0 = 1);
| ^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
index dce1c19..ae525ae 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
@@ -3,12 +3,12 @@
fn main() {
let _opt = Some(1i32);
- #[cfg(FALSE)]
+ #[cfg(false)]
{
let _ = &&let Some(x) = Some(42);
//~^ ERROR expected expression, found `let` statement
}
- #[cfg(FALSE)]
+ #[cfg(false)]
{
if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
//~^ ERROR expected expression, found `let` statement
@@ -18,7 +18,7 @@ fn main() {
}
}
- #[cfg(FALSE)]
+ #[cfg(false)]
{
if let Some(elem) = _opt && {
[1, 2, 3][let _ = ()];
@@ -28,7 +28,7 @@ fn main() {
}
}
- #[cfg(FALSE)]
+ #[cfg(false)]
{
if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
//~^ ERROR expected expression, found `let` statement
@@ -36,7 +36,7 @@ fn main() {
true
}
}
- #[cfg(FALSE)]
+ #[cfg(false)]
{
if let a = 1 && {
let x = let y = 1;
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs
index eeb2191..c0f1757 100644
--- a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs
@@ -1,14 +1,14 @@
-#[cfg(FALSE)]
+#[cfg(false)]
impl S {
fn f(#[attr]) {} //~ ERROR expected parameter name, found `)`
}
-#[cfg(FALSE)]
+#[cfg(false)]
impl T for S {
fn f(#[attr]) {} //~ ERROR expected parameter name, found `)`
}
-#[cfg(FALSE)]
+#[cfg(false)]
trait T {
fn f(#[attr]); //~ ERROR expected argument name, found `)`
}
diff --git a/tests/ui/rfcs/rfc-3467-unsafe-pinned/unsafe-pinned-hides-niche.rs b/tests/ui/rfcs/rfc-3467-unsafe-pinned/unsafe-pinned-hides-niche.rs
new file mode 100644
index 0000000..a1ff9a1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-3467-unsafe-pinned/unsafe-pinned-hides-niche.rs
@@ -0,0 +1,29 @@
+//@ check-pass
+// this test ensures that UnsafePinned hides the niche of its inner type, just like UnsafeCell does
+
+#![crate_type = "lib"]
+#![feature(unsafe_pinned)]
+
+use std::num::NonZero;
+use std::pin::UnsafePinned;
+
+macro_rules! assert_size_is {
+ ($ty:ty = $size:expr) => {
+ const _: () = assert!(size_of::<$ty>() == $size);
+ };
+}
+
+assert_size_is!(UnsafePinned<()> = 0);
+assert_size_is!(UnsafePinned<u8> = 1);
+
+assert_size_is!( UnsafePinned< u32> = 4);
+assert_size_is!( UnsafePinned< NonZero<u32>> = 4);
+assert_size_is!( UnsafePinned<Option<NonZero<u32>>> = 4);
+assert_size_is!(Option<UnsafePinned< u32>> = 8);
+assert_size_is!(Option<UnsafePinned< NonZero<u32>>> = 8);
+assert_size_is!(Option<UnsafePinned<Option<NonZero<u32>>>> = 8);
+
+assert_size_is!( UnsafePinned< &()> = size_of::<usize>());
+assert_size_is!( UnsafePinned<Option<&()>> = size_of::<usize>());
+assert_size_is!(Option<UnsafePinned< &()>> = size_of::<usize>() * 2);
+assert_size_is!(Option<UnsafePinned<Option<&()>>> = size_of::<usize>() * 2);
diff --git a/tests/ui/runtime/backtrace-debuginfo-aux.rs b/tests/ui/runtime/backtrace-debuginfo-aux.rs
index 24180ed..4493fa5 100644
--- a/tests/ui/runtime/backtrace-debuginfo-aux.rs
+++ b/tests/ui/runtime/backtrace-debuginfo-aux.rs
@@ -1,5 +1,4 @@
-//@ run-pass
-//@ ignore-test: not a test, used by backtrace-debuginfo.rs to test file!()
+//@ ignore-auxiliary (used by `./backtrace-debuginfo.rs` to test `file!()`)
#[inline(never)]
pub fn callback<F>(f: F) where F: FnOnce((&'static str, u32)) {
diff --git a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs
index dd604b6..f4f383e 100644
--- a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs
+++ b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs
@@ -2,7 +2,8 @@
// trait object type to fail, causing an ICE.
//
//@ needs-sanitizer-cfi
-//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021
+//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi
+//@ edition: 2021
//@ no-prefer-dynamic
//@ only-x86_64-unknown-linux-gnu
//@ build-pass
diff --git a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs
index e5b1e03..7d0c73c 100644
--- a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs
+++ b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs
@@ -2,7 +2,8 @@
// encode_ty and caused the compiler to ICE.
//
//@ needs-sanitizer-cfi
-//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021
+//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi
+//@ edition: 2021
//@ no-prefer-dynamic
//@ only-x86_64-unknown-linux-gnu
//@ build-pass
diff --git a/tests/ui/specialization/issue-63716-parse-async.rs b/tests/ui/specialization/issue-63716-parse-async.rs
index 3314b4e..00c0b29 100644
--- a/tests/ui/specialization/issue-63716-parse-async.rs
+++ b/tests/ui/specialization/issue-63716-parse-async.rs
@@ -8,7 +8,7 @@
fn main() {}
-#[cfg(FALSE)]
+#[cfg(false)]
impl Foo for Bar {
default async fn baz() {}
}
diff --git a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr b/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr
index 92947e3..713b071 100644
--- a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr
+++ b/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr
@@ -4,7 +4,6 @@
LL | fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result {
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/tests/ui/suggestions/const-no-type.rs b/tests/ui/suggestions/const-no-type.rs
index c6fdcda..b72ace9 100644
--- a/tests/ui/suggestions/const-no-type.rs
+++ b/tests/ui/suggestions/const-no-type.rs
@@ -10,19 +10,19 @@ fn main() {}
// These will not reach typeck:
-#[cfg(FALSE)]
+#[cfg(false)]
const C2 = 42;
//~^ ERROR missing type for `const` item
//~| HELP provide a type for the item
//~| SUGGESTION : <type>
-#[cfg(FALSE)]
+#[cfg(false)]
static S2 = "abc";
//~^ ERROR missing type for `static` item
//~| HELP provide a type for the item
//~| SUGGESTION : <type>
-#[cfg(FALSE)]
+#[cfg(false)]
static mut SM2 = "abc";
//~^ ERROR missing type for `static mut` item
//~| HELP provide a type for the item
diff --git a/tests/ui/suggestions/enum-method-probe.fixed b/tests/ui/suggestions/enum-method-probe.fixed
index 611be99..e097fa8 100644
--- a/tests/ui/suggestions/enum-method-probe.fixed
+++ b/tests/ui/suggestions/enum-method-probe.fixed
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2021
+//@ edition: 2021
//@ run-rustfix
#![allow(unused)]
diff --git a/tests/ui/suggestions/enum-method-probe.rs b/tests/ui/suggestions/enum-method-probe.rs
index e183ebd..665ee7d 100644
--- a/tests/ui/suggestions/enum-method-probe.rs
+++ b/tests/ui/suggestions/enum-method-probe.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2021
+//@ edition: 2021
//@ run-rustfix
#![allow(unused)]
diff --git a/tests/ui/suggestions/inner_type.fixed b/tests/ui/suggestions/inner_type.fixed
index cfea66b..3dc939d 100644
--- a/tests/ui/suggestions/inner_type.fixed
+++ b/tests/ui/suggestions/inner_type.fixed
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2021
+//@ edition: 2021
//@ run-rustfix
pub struct Struct<T> {
diff --git a/tests/ui/suggestions/inner_type.rs b/tests/ui/suggestions/inner_type.rs
index 5fedf3f..81a05c2 100644
--- a/tests/ui/suggestions/inner_type.rs
+++ b/tests/ui/suggestions/inner_type.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2021
+//@ edition: 2021
//@ run-rustfix
pub struct Struct<T> {
diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs
index 1f37e9a..cc5b878 100644
--- a/tests/ui/suggestions/issue-86667.rs
+++ b/tests/ui/suggestions/issue-86667.rs
@@ -1,7 +1,7 @@
// Regression test for #86667, where a garbled suggestion was issued for
// a missing named lifetime parameter.
-//@ compile-flags: --edition 2018
+//@ edition: 2018
async fn a(s1: &str, s2: &str) -> &str {
//~^ ERROR: missing lifetime specifier [E0106]
diff --git a/tests/ui/suggestions/many-type-ascription.stderr b/tests/ui/suggestions/many-type-ascription.stderr
index feddc7d..47e19c5 100644
--- a/tests/ui/suggestions/many-type-ascription.stderr
+++ b/tests/ui/suggestions/many-type-ascription.stderr
@@ -3,8 +3,6 @@
|
LL | let _ = 0: i32;
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: aborting due to 1 previous error
diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
index ce16aca..b9302b0 100644
--- a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
+++ b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
@@ -4,7 +4,6 @@
LL | a: foo:A,
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | a: foo::A,
@@ -16,7 +15,6 @@
LL | b: foo::bar:B,
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | b: foo::bar::B,
diff --git a/tests/ui/suggestions/suggest-ref-mut.rs b/tests/ui/suggestions/suggest-ref-mut.rs
index 9f5df93..2a933f6 100644
--- a/tests/ui/suggestions/suggest-ref-mut.rs
+++ b/tests/ui/suggestions/suggest-ref-mut.rs
@@ -1,3 +1,5 @@
+//@ dont-require-annotations: SUGGESTION
+
struct X(usize);
impl X {
diff --git a/tests/ui/suggestions/suggest-ref-mut.stderr b/tests/ui/suggestions/suggest-ref-mut.stderr
index 935a04c..7c0899f 100644
--- a/tests/ui/suggestions/suggest-ref-mut.stderr
+++ b/tests/ui/suggestions/suggest-ref-mut.stderr
@@ -1,5 +1,5 @@
error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
- --> $DIR/suggest-ref-mut.rs:7:9
+ --> $DIR/suggest-ref-mut.rs:9:9
|
LL | self.0 = 32;
| ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
@@ -10,7 +10,7 @@
| +++
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
- --> $DIR/suggest-ref-mut.rs:15:5
+ --> $DIR/suggest-ref-mut.rs:17:5
|
LL | *foo = 32;
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
@@ -21,7 +21,7 @@
| +++
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
- --> $DIR/suggest-ref-mut.rs:19:9
+ --> $DIR/suggest-ref-mut.rs:21:9
|
LL | *bar = 32;
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
@@ -32,7 +32,7 @@
| +++
error[E0594]: cannot assign to `*quo`, which is behind a `&` reference
- --> $DIR/suggest-ref-mut.rs:23:22
+ --> $DIR/suggest-ref-mut.rs:25:22
|
LL | ref quo => { *quo = 32; },
| ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written
diff --git a/tests/ui/suggestions/type-ascription-and-other-error.rs b/tests/ui/suggestions/type-ascription-and-other-error.rs
index 99ab2f3..da985b5 100644
--- a/tests/ui/suggestions/type-ascription-and-other-error.rs
+++ b/tests/ui/suggestions/type-ascription-and-other-error.rs
@@ -1,6 +1,6 @@
fn main() {
not rust; //~ ERROR
let _ = 0: i32; // (error hidden by existing error)
- #[cfg(FALSE)]
+ #[cfg(false)]
let _ = 0: i32; // (warning hidden by existing error)
}
diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.stderr b/tests/ui/suggestions/type-ascription-instead-of-method.stderr
index 0bef1c1..6dc7b5e 100644
--- a/tests/ui/suggestions/type-ascription-instead-of-method.stderr
+++ b/tests/ui/suggestions/type-ascription-instead-of-method.stderr
@@ -4,7 +4,6 @@
LL | let _ = Box:new("foo".to_string());
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | let _ = Box::new("foo".to_string());
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr
index 0b37bf9..79dffc0 100644
--- a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr
+++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr
@@ -4,7 +4,6 @@
LL | let _ = vec![Ok(2)].into_iter().collect:<Result<Vec<_>,_>>()?;
| ^ expected one of 7 possible tokens
|
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: maybe write a path separator here
|
LL | let _ = vec![Ok(2)].into_iter().collect::<Result<Vec<_>,_>>()?;
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path.stderr b/tests/ui/suggestions/type-ascription-instead-of-path.stderr
index 8c16acf..a836461 100644
--- a/tests/ui/suggestions/type-ascription-instead-of-path.stderr
+++ b/tests/ui/suggestions/type-ascription-instead-of-path.stderr
@@ -4,7 +4,6 @@
LL | std:io::stdin();
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | std::io::stdin();
diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr
index f0b3172..e836b37 100644
--- a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr
+++ b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr
@@ -4,7 +4,6 @@
LL | let _ = Option:Some("");
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | let _ = Option::Some("");
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
index fda0b1c..d394dbe 100644
--- a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
+++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
@@ -4,7 +4,7 @@
//@ compile-flags: -Ctarget-feature=-forced-atomics
// For now this is just a warning.
//@ build-pass
-//@error-pattern: unsound because it changes the ABI
+
#![feature(no_core, lang_items)]
#![no_core]
diff --git a/tests/ui/target-feature/tied-features-no-implication-1.rs b/tests/ui/target-feature/tied-features-no-implication-1.rs
index 0a98a7e..63a1d77 100644
--- a/tests/ui/target-feature/tied-features-no-implication-1.rs
+++ b/tests/ui/target-feature/tied-features-no-implication-1.rs
@@ -2,9 +2,7 @@
//@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu
//@ needs-llvm-components: aarch64
//@[paca] compile-flags: -Ctarget-feature=+paca
-//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together
//@[pacg] compile-flags: -Ctarget-feature=+pacg
-//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together
#![feature(no_core, lang_items)]
#![no_core]
diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.rs b/tests/ui/test-attrs/test-should-panic-failed-show-span.rs
new file mode 100644
index 0000000..f400f61
--- /dev/null
+++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.rs
@@ -0,0 +1,46 @@
+//@ compile-flags: --test
+//@ run-flags: --test-threads=1 --nocapture
+//@ run-fail
+//@ check-run-results
+//@ exec-env:RUST_BACKTRACE=0
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ normalize-stdout: "TypeId\(0x[0-9a-f]+\)" -> "TypeId($$HEX)"
+//@ needs-threads
+//@ needs-unwind (panic)
+
+#[test]
+#[should_panic]
+fn should_panic_with_any_message() {
+ panic!("Panic!");
+}
+
+#[test]
+#[should_panic = "message"]
+fn should_panic_with_message() {
+ panic!("message");
+}
+
+#[test]
+#[should_panic]
+fn should_panic_with_any_message_does_not_panic() {
+ // DON'T PANIC
+}
+
+#[test]
+#[should_panic = "message"]
+fn should_panic_with_message_does_not_panic() {
+ // DON'T PANIC
+}
+
+#[test]
+#[should_panic = "message"]
+fn should_panic_with_substring_panics_with_incorrect_string() {
+ panic!("ZOMGWTFBBQ");
+}
+
+#[test]
+#[should_panic = "message"]
+#[expect(non_fmt_panics)]
+fn should_panic_with_substring_panics_with_non_string_value() {
+ panic!(123);
+}
diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stderr b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stderr
new file mode 100644
index 0000000..db379a1
--- /dev/null
+++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stderr
@@ -0,0 +1,13 @@
+
+thread 'should_panic_with_any_message' panicked at $DIR/test-should-panic-failed-show-span.rs:14:5:
+Panic!
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+thread 'should_panic_with_message' panicked at $DIR/test-should-panic-failed-show-span.rs:20:5:
+message
+
+thread 'should_panic_with_substring_panics_with_incorrect_string' panicked at $DIR/test-should-panic-failed-show-span.rs:38:5:
+ZOMGWTFBBQ
+
+thread 'should_panic_with_substring_panics_with_non_string_value' panicked at $DIR/test-should-panic-failed-show-span.rs:45:5:
+Box<dyn Any>
diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout
new file mode 100644
index 0000000..75600b4
--- /dev/null
+++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout
@@ -0,0 +1,32 @@
+
+running 6 tests
+test should_panic_with_any_message - should panic ... ok
+test should_panic_with_any_message_does_not_panic - should panic ... FAILED
+test should_panic_with_message - should panic ... ok
+test should_panic_with_message_does_not_panic - should panic ... FAILED
+test should_panic_with_substring_panics_with_incorrect_string - should panic ... FAILED
+test should_panic_with_substring_panics_with_non_string_value - should panic ... FAILED
+
+failures:
+
+---- should_panic_with_any_message_does_not_panic stdout ----
+note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:25:4
+---- should_panic_with_message_does_not_panic stdout ----
+note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:31:4
+---- should_panic_with_substring_panics_with_incorrect_string stdout ----
+note: panic did not contain expected string
+ panic message: `"ZOMGWTFBBQ"`,
+ expected substring: `"message"`
+---- should_panic_with_substring_panics_with_non_string_value stdout ----
+note: expected panic with string value,
+ found non-string value: `TypeId($HEX)`
+ expected substring: `"message"`
+
+failures:
+ should_panic_with_any_message_does_not_panic
+ should_panic_with_message_does_not_panic
+ should_panic_with_substring_panics_with_incorrect_string
+ should_panic_with_substring_panics_with_non_string_value
+
+test result: FAILED. 2 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/ui/traits/associated_type_bound/hrtb-associated.rs b/tests/ui/traits/associated_type_bound/hrtb-associated.rs
new file mode 100644
index 0000000..59e5a09
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/hrtb-associated.rs
@@ -0,0 +1,30 @@
+//@ check-pass
+//! This test ensures that HRTB (higher-ranked trait bounds) on associated types
+//! compile correctly. This was previously rejected by the compiler.
+//! Related issue: <https://github.com/rust-lang/rust/issues/34834>
+
+pub trait Provides<'a> {
+ type Item;
+}
+
+pub trait Selector: for<'a> Provides<'a> {
+ type Namespace: PartialEq + for<'a> PartialEq<<Self as Provides<'a>>::Item>;
+
+ fn get_namespace(&self) -> <Self as Provides>::Item;
+}
+
+pub struct MySelector;
+
+impl<'a> Provides<'a> for MySelector {
+ type Item = &'a str;
+}
+
+impl Selector for MySelector {
+ type Namespace = String;
+
+ fn get_namespace(&self) -> &str {
+ unimplemented!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs
index 931879a..f7c4904 100644
--- a/tests/ui/traits/issue-85360-eval-obligation-ice.rs
+++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2021
+//@ edition: 2021
#![feature(rustc_attrs)]
diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs
index b0c778e..754fc87 100644
--- a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs
+++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs
@@ -34,9 +34,17 @@ impl Trait for MultipleCandidates
MultipleNested: Trait,
{}
+// We ignore the trivially true global where-bounds when checking that this
+// impl is well-formed, meaning that we depend on `MultipleNested: Trait` when
+// recursively proving `MultipleCandidates: Trait`.
+//
+// These overflow errors will disappear once we treat these cycles as either
+// productive or an error.
impl Trait for MultipleNested
+//~^ ERROR overflow evaluating the requirement `MultipleNested: Trait`
where
MultipleCandidates: Trait,
+ //~^ ERROR overflow evaluating the requirement `MultipleCandidates: Trait`
DoesNotImpl: Trait,
{}
diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr
index acacaf6..7895a26 100644
--- a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr
+++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr
@@ -1,16 +1,29 @@
+error[E0275]: overflow evaluating the requirement `MultipleNested: Trait`
+ --> $DIR/inductive-cycle-but-err.rs:43:16
+ |
+LL | impl Trait for MultipleNested
+ | ^^^^^^^^^^^^^^
+
+error[E0275]: overflow evaluating the requirement `MultipleCandidates: Trait`
+ --> $DIR/inductive-cycle-but-err.rs:46:25
+ |
+LL | MultipleCandidates: Trait,
+ | ^^^^^
+
error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied
- --> $DIR/inductive-cycle-but-err.rs:46:19
+ --> $DIR/inductive-cycle-but-err.rs:54:19
|
LL | impls_trait::<MultipleCandidates>();
| ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates`
|
= help: the trait `Trait` is implemented for `MultipleCandidates`
note: required by a bound in `impls_trait`
- --> $DIR/inductive-cycle-but-err.rs:43:19
+ --> $DIR/inductive-cycle-but-err.rs:51:19
|
LL | fn impls_trait<T: Trait>() {}
| ^^^^^ required by this bound in `impls_trait`
-error: aborting due to 1 previous error
+error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0275, E0277.
+For more information about an error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs
new file mode 100644
index 0000000..bb3540f
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs
@@ -0,0 +1,24 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#176.
+//
+// Normalizing `<Vec<T> as IntoIterator>::IntoIter` has two candidates
+// inside of the function:
+// - `impl<T> IntoIterator for Vec<T>` which trivially applies
+// - `impl<I: Iterator> IntoIterator for I`
+// - requires `Vec<T>: Iterator`
+// - where-clause requires `<Vec<T> as IntoIterator>::IntoIter eq Vec<T>`
+// - normalize `<Vec<T> as IntoIterator>::IntoIter` again, cycle
+//
+// We need to treat this cycle as an error to be able to use the actual impl.
+
+fn test<T>()
+where
+ <Vec<T> as IntoIterator>::IntoIter: Iterator,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.current.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.current.stderr
new file mode 100644
index 0000000..0a5b90f
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.current.stderr
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `Foo: Bound` is not satisfied
+ --> $DIR/normalizes-to-is-not-productive.rs:41:1
+ |
+LL | / fn generic<T>()
+LL | | where
+LL | | <Foo as Trait<T>>::Assoc: Bound,
+ | |____________________________________^ the trait `Bound` is not implemented for `Foo`
+ |
+ = help: the trait `Bound` is implemented for `u32`
+note: required for `Foo` to implement `Trait<T>`
+ --> $DIR/normalizes-to-is-not-productive.rs:24:19
+ |
+LL | impl<T: Bound, U> Trait<U> for T {
+ | ----- ^^^^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+
+error[E0277]: the trait bound `Foo: Bound` is not satisfied
+ --> $DIR/normalizes-to-is-not-productive.rs:41:4
+ |
+LL | fn generic<T>()
+ | ^^^^^^^ the trait `Bound` is not implemented for `Foo`
+ |
+ = help: the trait `Bound` is implemented for `u32`
+note: required for `Foo` to implement `Trait<T>`
+ --> $DIR/normalizes-to-is-not-productive.rs:24:19
+ |
+LL | impl<T: Bound, U> Trait<U> for T {
+ | ----- ^^^^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+
+error[E0277]: the trait bound `Foo: Bound` is not satisfied
+ --> $DIR/normalizes-to-is-not-productive.rs:48:19
+ |
+LL | impls_bound::<Foo>();
+ | ^^^ the trait `Bound` is not implemented for `Foo`
+ |
+ = help: the trait `Bound` is implemented for `u32`
+note: required by a bound in `impls_bound`
+ --> $DIR/normalizes-to-is-not-productive.rs:28:19
+ |
+LL | fn impls_bound<T: Bound>() {
+ | ^^^^^ required by this bound in `impls_bound`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.next.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.next.stderr
new file mode 100644
index 0000000..d888fbf
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.next.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the trait bound `Foo: Bound` is not satisfied
+ --> $DIR/normalizes-to-is-not-productive.rs:43:31
+ |
+LL | <Foo as Trait<T>>::Assoc: Bound,
+ | ^^^^^ the trait `Bound` is not implemented for `Foo`
+ |
+ = help: the trait `Bound` is implemented for `u32`
+note: required for `Foo` to implement `Trait<T>`
+ --> $DIR/normalizes-to-is-not-productive.rs:24:19
+ |
+LL | impl<T: Bound, U> Trait<U> for T {
+ | ----- ^^^^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+
+error[E0277]: the trait bound `Foo: Bound` is not satisfied
+ --> $DIR/normalizes-to-is-not-productive.rs:48:19
+ |
+LL | impls_bound::<Foo>();
+ | ^^^ the trait `Bound` is not implemented for `Foo`
+ |
+ = help: the trait `Bound` is implemented for `u32`
+note: required by a bound in `impls_bound`
+ --> $DIR/normalizes-to-is-not-productive.rs:28:19
+ |
+LL | fn impls_bound<T: Bound>() {
+ | ^^^^^ required by this bound in `impls_bound`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs
new file mode 100644
index 0000000..ffbbeca
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs
@@ -0,0 +1,54 @@
+//@ ignore-compare-mode-next-solver (explicit)
+//@ compile-flags: -Znext-solver
+
+// Make sure that stepping into impl where-clauses of `NormalizesTo`
+// goals is unproductive. This must not compile, see the inline
+// comments.
+
+trait Bound {
+ fn method();
+}
+impl Bound for u32 {
+ fn method() {}
+}
+trait Trait<T> {
+ type Assoc: Bound;
+}
+
+struct Foo;
+
+impl Trait<u32> for Foo {
+ type Assoc = u32;
+}
+impl<T: Bound, U> Trait<U> for T {
+ type Assoc = T;
+}
+
+fn impls_bound<T: Bound>() {
+ T::method();
+}
+
+// The where-clause requires `Foo: Trait<T>` to hold to be wf.
+// If stepping into where-clauses during normalization is considered
+// to be productive, this would be the case:
+//
+// - `Foo: Trait<T>`
+// - via blanket impls, requires `Foo: Bound`
+// - via where-bound, requires `Foo eq <Foo as Trait<T>>::Assoc`
+// - normalize `<Foo as Trait<T>>::Assoc`
+// - via blanket impl, requires where-clause `Foo: Bound` -> cycle
+fn generic<T>()
+where
+ <Foo as Trait<T>>::Assoc: Bound,
+ //~^ ERROR the trait bound `Foo: Bound` is not satisfied
+{
+ // Requires proving `Foo: Bound` by normalizing
+ // `<Foo as Trait<T>>::Assoc` to `Foo`.
+ impls_bound::<Foo>();
+ //~^ ERROR the trait bound `Foo: Bound` is not satisfied
+}
+fn main() {
+ // Requires proving `<Foo as Trait<u32>>::Assoc: Bound`.
+ // This is trivially true.
+ generic::<u32>();
+}
diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr
new file mode 100644
index 0000000..8901805
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the trait bound `Foo: Bound` is not satisfied
+ --> $DIR/normalizes-to-is-not-productive.rs:42:31
+ |
+LL | <Foo as Trait<T>>::Assoc: Bound,
+ | ^^^^^ the trait `Bound` is not implemented for `Foo`
+ |
+ = help: the trait `Bound` is implemented for `u32`
+note: required for `Foo` to implement `Trait<T>`
+ --> $DIR/normalizes-to-is-not-productive.rs:23:19
+ |
+LL | impl<T: Bound, U> Trait<U> for T {
+ | ----- ^^^^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+
+error[E0277]: the trait bound `Foo: Bound` is not satisfied
+ --> $DIR/normalizes-to-is-not-productive.rs:47:19
+ |
+LL | impls_bound::<Foo>();
+ | ^^^ the trait `Bound` is not implemented for `Foo`
+ |
+ = help: the trait `Bound` is implemented for `u32`
+note: required by a bound in `impls_bound`
+ --> $DIR/normalizes-to-is-not-productive.rs:27:19
+ |
+LL | fn impls_bound<T: Bound>() {
+ | ^^^^^ required by this bound in `impls_bound`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr
index 74a0a90..d179c80 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr
+++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr
@@ -4,14 +4,14 @@
LL | Self::Assoc: A<T>,
| ^^^^
|
-note: the requirement `<() as A<T>>::Assoc: A<T>` appears on the `impl`'s method `f` but not on the corresponding trait's method
+note: the requirement `<() as A<T>>::Assoc: A<T>` appears on the `impl`'s associated function `f` but not on the corresponding trait's associated function
--> $DIR/normalize-param-env-2.rs:12:8
|
LL | trait A<T> {
| - in this trait
...
LL | fn f()
- | ^ this trait's method doesn't have the requirement `<() as A<T>>::Assoc: A<T>`
+ | ^ this trait's associated function doesn't have the requirement `<() as A<T>>::Assoc: A<T>`
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
--> $DIR/normalize-param-env-2.rs:24:22
diff --git a/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs
index 11a2617..3ef6bea 100644
--- a/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs
+++ b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs
@@ -1,5 +1,5 @@
//@ compile-flags: -Znext-solver
-//@ ignore-test
+//@ ignore-test (see #114196)
trait Trait {
type Gat<'lt>;
diff --git a/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs
index e5208e3..198e619 100644
--- a/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs
+++ b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs
@@ -1,7 +1,8 @@
// Regression test for #132335. This previously ICE'd due to ambiguity
// in MIR typeck.
-//@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018
+//@ compile-flags: -Znext-solver=globally --crate-type lib
+//@ edition: 2018
//@ check-pass
use core::future::Future;
use core::pin::Pin;
diff --git a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs
index 8388751..b79926e 100644
--- a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs
+++ b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs
@@ -3,7 +3,7 @@
// of the async block. This caused borrowck of the recursive
// call to ICE.
-//@ compile-flags: --edition=2021
+//@ edition: 2021
//@ check-pass
async fn test() {
Box::pin(test()).await;
diff --git a/tests/ui/traits/next-solver/supertrait-alias-1.rs b/tests/ui/traits/next-solver/supertrait-alias-1.rs
new file mode 100644
index 0000000..579a446
--- /dev/null
+++ b/tests/ui/traits/next-solver/supertrait-alias-1.rs
@@ -0,0 +1,22 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/171>.
+// Tests that we don't try to replace `<V as Super>::Output` when replacing projections in the
+// required bounds for `dyn Trait`, b/c `V` is not relevant to the dyn type, which we were
+// previously encountering b/c we were walking into the existential projection bounds of the dyn
+// type itself.
+
+pub trait Trait: Super {}
+
+pub trait Super {
+ type Output;
+}
+
+fn bound<T: Trait + ?Sized>() {}
+
+fn visit_simd_operator<V: Super + ?Sized>() {
+ bound::<dyn Trait<Output = <V as Super>::Output>>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/supertrait-alias-2.rs b/tests/ui/traits/next-solver/supertrait-alias-2.rs
new file mode 100644
index 0000000..a0f3e03
--- /dev/null
+++ b/tests/ui/traits/next-solver/supertrait-alias-2.rs
@@ -0,0 +1,25 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/171>.
+// Tests that we don't try to replace `<T as Other>::Assoc` when replacing projections in the
+// required bounds for `dyn Foo`, b/c `T` is not relevant to the dyn type, which we were
+// encountering when walking through the elaborated supertraits of `dyn Foo`.
+
+trait Other<X> {}
+
+trait Foo<T: Foo<T>>: Other<<T as Foo<T>>::Assoc> {
+ type Assoc;
+}
+
+impl<T> Foo<T> for T {
+ type Assoc = ();
+}
+
+impl<T: ?Sized> Other<()> for T {}
+
+fn is_foo<T: Foo<()> + ?Sized>() {}
+
+fn main() {
+ is_foo::<dyn Foo<(), Assoc = ()>>();
+}
diff --git a/tests/ui/traits/next-solver/supertrait-alias-3.rs b/tests/ui/traits/next-solver/supertrait-alias-3.rs
new file mode 100644
index 0000000..78182bb
--- /dev/null
+++ b/tests/ui/traits/next-solver/supertrait-alias-3.rs
@@ -0,0 +1,32 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/171>.
+// Exercises a case where structural equality is insufficient when replacing projections in a dyn's
+// bounds. In this case, the bound will contain `<Self as Super<<i32 as Mirror>:Assoc>::Assoc`, but
+// the existential projections from the dyn will have `<Self as Super<i32>>::Assoc` because as an
+// optimization we eagerly normalize aliases in goals.
+
+trait Other<T> {}
+impl<T> Other<T> for T {}
+
+trait Super<T> {
+ type Assoc;
+}
+
+trait Mirror {
+ type Assoc;
+}
+impl<T> Mirror for T {
+ type Assoc = T;
+}
+
+trait Foo<A, B>: Super<<A as Mirror>::Assoc, Assoc = A> {
+ type FooAssoc: Other<<Self as Super<<A as Mirror>::Assoc>>::Assoc>;
+}
+
+fn is_foo<F: Foo<T, U> + ?Sized, T, U>() {}
+
+fn main() {
+ is_foo::<dyn Foo<i32, u32, FooAssoc = i32>, _, _>();
+}
diff --git a/tests/ui/traits/next-solver/supertrait-alias-4.rs b/tests/ui/traits/next-solver/supertrait-alias-4.rs
new file mode 100644
index 0000000..919a768
--- /dev/null
+++ b/tests/ui/traits/next-solver/supertrait-alias-4.rs
@@ -0,0 +1,24 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Exercises the ambiguity that comes from replacing the associated types within the bounds
+// that are required for a `impl Trait for dyn Trait` built-in object impl to hold.
+
+trait Sup<T> {
+ type Assoc;
+}
+
+trait Foo<A, B>: Sup<A, Assoc = A> + Sup<B, Assoc = B> {
+ type Other: Bar<<Self as Sup<A>>::Assoc>;
+}
+
+trait Bar<T> {}
+impl Bar<i32> for () {}
+
+fn foo<A, B>(x: &(impl Foo<A, B> + ?Sized)) {}
+
+fn main() {
+ let x: &dyn Foo<_, _, Other = ()> = todo!();
+ foo(x);
+ let y: &dyn Foo<i32, u32, Other = ()> = x;
+}
diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs
index f8fa410..50851a5 100644
--- a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs
+++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs
@@ -1,4 +1,4 @@
-//@compile-flags: --edition 2021
+//@ edition: 2021
fn f<'a>(x: Box<dyn Fn() -> Option<usize + 'a>>) -> usize {
//~^ ERROR expected trait, found builtin type `usize`
diff --git a/tests/ui/traits/winnowing/global-where-bound-region-constraints-2.rs b/tests/ui/traits/winnowing/global-where-bound-region-constraints-2.rs
new file mode 100644
index 0000000..d422605
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-where-bound-region-constraints-2.rs
@@ -0,0 +1,33 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#172.
+//
+// In this test the global where-bound simply constrains the
+// object lifetime bound to 'static while the builtin impl
+// ends up also emitting a `dyn Any: 'static` type outlives
+// constraint. This previously resulted in ambiguity. We now
+// always prefer the impl.
+
+pub trait Any: 'static {}
+
+pub trait Downcast<T>: Any
+where
+ T: Any,
+{
+}
+
+// elided object lifetime: `dyn Any + 'static`
+impl dyn Any {
+ pub fn is<T>(&self)
+ where
+ T: Any,
+ // elaboration adds global where-clause `dyn Any + 'static: Any`
+ Self: Downcast<T>,
+ {
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/winnowing/global-where-bound-region-constraints.rs b/tests/ui/traits/winnowing/global-where-bound-region-constraints.rs
new file mode 100644
index 0000000..3bc8b04
--- /dev/null
+++ b/tests/ui/traits/winnowing/global-where-bound-region-constraints.rs
@@ -0,0 +1,29 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#172.
+//
+// The next-generation trait solver previously simply tried
+// to merge the global where-bounds with the impl candidates.
+// This caused ambiguity in case the where-bound had stricter
+// region requirements than the impl.
+
+trait Trait {}
+struct Foo<'a, 'b>(&'a (), &'b ());
+impl<'a> Trait for Foo<'a, 'static> {}
+
+fn impls_trait<T: Trait>() {}
+fn foo()
+where
+ Foo<'static, 'static>: Trait,
+{
+ // impl requires `'1 to be 'static
+ // global where-bound requires both '0 and '1 to be 'static
+ //
+ // we always prefer the impl here.
+ impls_trait::<Foo<'_, '_>>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs b/tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs
new file mode 100644
index 0000000..cdfb0ee
--- /dev/null
+++ b/tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs
@@ -0,0 +1,29 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Make sure we prefer the `I::IntoIterator: Iterator<Item = ()>`
+// where-bound over the `I::Intoiterator: Iterator<Item = I::Item>`
+// alias-bound.
+
+trait Iterator {
+ type Item;
+}
+
+trait IntoIterator {
+ type Item;
+ type IntoIter: Iterator<Item = Self::Item>;
+}
+
+fn normalize<I: Iterator<Item = ()>>() {}
+
+fn foo<I>()
+where
+ I: IntoIterator,
+ I::IntoIter: Iterator<Item = ()>,
+{
+ normalize::<I::IntoIter>();
+}
+
+fn main() {}
diff --git a/tests/ui/try-block/issue-45124.rs b/tests/ui/try-block/issue-45124.rs
index e9e0e76..26e1736 100644
--- a/tests/ui/try-block/issue-45124.rs
+++ b/tests/ui/try-block/issue-45124.rs
@@ -1,6 +1,6 @@
//@ run-pass
#![allow(unreachable_code)]
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-bad-lifetime.rs b/tests/ui/try-block/try-block-bad-lifetime.rs
index bfff757..9b45b0d 100644
--- a/tests/ui/try-block/try-block-bad-lifetime.rs
+++ b/tests/ui/try-block/try-block-bad-lifetime.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-bad-type.rs b/tests/ui/try-block/try-block-bad-type.rs
index 71eb832..00cd0af 100644
--- a/tests/ui/try-block/try-block-bad-type.rs
+++ b/tests/ui/try-block/try-block-bad-type.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-catch.rs b/tests/ui/try-block/try-block-catch.rs
index c3aa442..170d5ba 100644
--- a/tests/ui/try-block/try-block-catch.rs
+++ b/tests/ui/try-block/try-block-catch.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-in-edition2015.rs b/tests/ui/try-block/try-block-in-edition2015.rs
index 423269d..4ebe2d3 100644
--- a/tests/ui/try-block/try-block-in-edition2015.rs
+++ b/tests/ui/try-block/try-block-in-edition2015.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2015
+//@ edition: 2015
pub fn main() {
let try_result: Option<_> = try {
diff --git a/tests/ui/try-block/try-block-in-match-arm.rs b/tests/ui/try-block/try-block-in-match-arm.rs
index cecbf72..703b1c5 100644
--- a/tests/ui/try-block/try-block-in-match-arm.rs
+++ b/tests/ui/try-block/try-block-in-match-arm.rs
@@ -1,5 +1,5 @@
//@ check-pass
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-in-match.rs b/tests/ui/try-block/try-block-in-match.rs
index 5c62f41..63a3200 100644
--- a/tests/ui/try-block/try-block-in-match.rs
+++ b/tests/ui/try-block/try-block-in-match.rs
@@ -1,5 +1,5 @@
//@ run-pass
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-in-return.rs b/tests/ui/try-block/try-block-in-return.rs
index ee5ca69..7dc023b 100644
--- a/tests/ui/try-block/try-block-in-return.rs
+++ b/tests/ui/try-block/try-block-in-return.rs
@@ -1,5 +1,5 @@
//@ run-pass
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-in-while.rs b/tests/ui/try-block/try-block-in-while.rs
index 88a9713..d623254 100644
--- a/tests/ui/try-block/try-block-in-while.rs
+++ b/tests/ui/try-block/try-block-in-while.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs
index 52ec0c4..14adee8 100644
--- a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs
+++ b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-opt-init.rs b/tests/ui/try-block/try-block-opt-init.rs
index fbe7f90..55ac5b4 100644
--- a/tests/ui/try-block/try-block-opt-init.rs
+++ b/tests/ui/try-block/try-block-opt-init.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-type-error.rs b/tests/ui/try-block/try-block-type-error.rs
index 79cdb7a..4e482b4 100644
--- a/tests/ui/try-block/try-block-type-error.rs
+++ b/tests/ui/try-block/try-block-type-error.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-unreachable-code-lint.rs b/tests/ui/try-block/try-block-unreachable-code-lint.rs
index 62c74b7..9135882 100644
--- a/tests/ui/try-block/try-block-unreachable-code-lint.rs
+++ b/tests/ui/try-block/try-block-unreachable-code-lint.rs
@@ -1,6 +1,6 @@
// Test unreachable_code lint for `try {}` block ok-wrapping. See issues #54165, #63324.
-//@ compile-flags: --edition 2018
+//@ edition: 2018
//@ check-pass
#![feature(try_blocks)]
#![warn(unreachable_code)]
diff --git a/tests/ui/try-block/try-block-unused-delims.fixed b/tests/ui/try-block/try-block-unused-delims.fixed
index 348eb8f..4769c45 100644
--- a/tests/ui/try-block/try-block-unused-delims.fixed
+++ b/tests/ui/try-block/try-block-unused-delims.fixed
@@ -1,5 +1,5 @@
//@ check-pass
-//@ compile-flags: --edition 2018
+//@ edition: 2018
//@ run-rustfix
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block-unused-delims.rs b/tests/ui/try-block/try-block-unused-delims.rs
index f119e10..0520d1d 100644
--- a/tests/ui/try-block/try-block-unused-delims.rs
+++ b/tests/ui/try-block/try-block-unused-delims.rs
@@ -1,5 +1,5 @@
//@ check-pass
-//@ compile-flags: --edition 2018
+//@ edition: 2018
//@ run-rustfix
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-block.rs b/tests/ui/try-block/try-block.rs
index 7520cba..3fa0d2b 100644
--- a/tests/ui/try-block/try-block.rs
+++ b/tests/ui/try-block/try-block.rs
@@ -2,7 +2,7 @@
#![allow(non_camel_case_types)]
#![allow(dead_code)]
-//@ compile-flags: --edition 2018
+//@ edition: 2018
#![feature(try_blocks)]
diff --git a/tests/ui/try-block/try-is-identifier-edition2015.rs b/tests/ui/try-block/try-is-identifier-edition2015.rs
index 54bd049..99f4d20 100644
--- a/tests/ui/try-block/try-is-identifier-edition2015.rs
+++ b/tests/ui/try-block/try-is-identifier-edition2015.rs
@@ -1,7 +1,7 @@
//@ run-pass
#![allow(non_camel_case_types)]
-//@ compile-flags: --edition 2015
+//@ edition: 2015
fn main() {
let try = 2;
diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
index 4f3f6d3..f69fd57 100644
--- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
+++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: --edition=2021
+//@ edition: 2021
//@ build-pass
#![feature(type_alias_impl_trait)]
diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
index cad1cbf..be8b7fa 100644
--- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
+++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
@@ -1,5 +1,5 @@
-//@ compile-flags: --edition=2021 --crate-type=lib
-//@ rustc-env:RUST_BACKTRACE=0
+//@ compile-flags: --crate-type=lib
+//@ edition: 2021
//@ check-pass
// tracked in https://github.com/rust-lang/rust/issues/96572
diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs
index a3b1aba..a42ea08 100644
--- a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs
+++ b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs
@@ -1,3 +1,5 @@
+//@ revisions: current next
+//@ [next] compile-flags: -Znext-solver
//@ build-pass
//@ edition: 2021
diff --git a/tests/ui/type-alias-impl-trait/issue-60662.rs b/tests/ui/type-alias-impl-trait/issue-60662.rs
index 35d96e5..7ecdd26 100644
--- a/tests/ui/type-alias-impl-trait/issue-60662.rs
+++ b/tests/ui/type-alias-impl-trait/issue-60662.rs
@@ -1,5 +1,6 @@
//@ check-pass
//@ compile-flags: -Z unpretty=hir
+//@ edition: 2015
#![feature(type_alias_impl_trait)]
diff --git a/tests/ui/type-alias-impl-trait/issue-60662.stdout b/tests/ui/type-alias-impl-trait/issue-60662.stdout
index b541cbe..56fef85 100644
--- a/tests/ui/type-alias-impl-trait/issue-60662.stdout
+++ b/tests/ui/type-alias-impl-trait/issue-60662.stdout
@@ -1,5 +1,6 @@
//@ check-pass
//@ compile-flags: -Z unpretty=hir
+//@ edition: 2015
#![feature(type_alias_impl_trait)]
#[prelude_import]
diff --git a/tests/ui/type-alias-impl-trait/issue-93411.rs b/tests/ui/type-alias-impl-trait/issue-93411.rs
index 11cbb87..614d2d0 100644
--- a/tests/ui/type-alias-impl-trait/issue-93411.rs
+++ b/tests/ui/type-alias-impl-trait/issue-93411.rs
@@ -2,7 +2,7 @@
// this test used to stack overflow due to infinite recursion.
//@ check-pass
-//@ compile-flags: --edition=2018
+//@ edition: 2018
use std::future::Future;
diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
index 08f3c40..7f0f6a2 100644
--- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
+++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
@@ -1,7 +1,7 @@
#![feature(type_alias_impl_trait)]
//@ check-pass
//@ revisions: default edition2021
-//@[edition2021] compile-flags: --edition 2021
+//@[edition2021]edition: 2021
fn main() {
type T = impl Copy;
diff --git a/tests/ui/type-alias-impl-trait/tait-normalize.rs b/tests/ui/type-alias-impl-trait/tait-normalize.rs
index 38e09b6..a34d167 100644
--- a/tests/ui/type-alias-impl-trait/tait-normalize.rs
+++ b/tests/ui/type-alias-impl-trait/tait-normalize.rs
@@ -1,3 +1,5 @@
+//@ revisions: current next
+//@ [next] compile-flags: -Znext-solver
//@ check-pass
#![feature(type_alias_impl_trait)]
diff --git a/tests/ui/type/ascription/issue-47666.stderr b/tests/ui/type/ascription/issue-47666.stderr
index fd825e8..6568845 100644
--- a/tests/ui/type/ascription/issue-47666.stderr
+++ b/tests/ui/type/ascription/issue-47666.stderr
@@ -4,7 +4,6 @@
LL | let _ = Option:Some(vec![0, 1]);
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | let _ = Option::Some(vec![0, 1]);
diff --git a/tests/ui/type/ascription/issue-54516.stderr b/tests/ui/type/ascription/issue-54516.stderr
index 64fdc1f..925080e 100644
--- a/tests/ui/type/ascription/issue-54516.stderr
+++ b/tests/ui/type/ascription/issue-54516.stderr
@@ -4,7 +4,6 @@
LL | println!("{}", std::mem:size_of::<BTreeMap<u32, u32>>());
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | println!("{}", std::mem::size_of::<BTreeMap<u32, u32>>());
diff --git a/tests/ui/type/ascription/issue-60933.stderr b/tests/ui/type/ascription/issue-60933.stderr
index c68394d..7b55935 100644
--- a/tests/ui/type/ascription/issue-60933.stderr
+++ b/tests/ui/type/ascription/issue-60933.stderr
@@ -4,7 +4,6 @@
LL | let _: usize = std::mem:size_of::<u32>();
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a double colon instead
|
LL | let _: usize = std::mem::size_of::<u32>();
diff --git a/tests/ui/type/missing-let-in-binding.stderr b/tests/ui/type/missing-let-in-binding.stderr
index a9d766e..dee3d56 100644
--- a/tests/ui/type/missing-let-in-binding.stderr
+++ b/tests/ui/type/missing-let-in-binding.stderr
@@ -4,7 +4,6 @@
LL | _foo: i32 = 4;
| ^ expected identifier
|
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: you might have meant to introduce a new binding
|
LL | let _foo: i32 = 4;
diff --git a/tests/ui/type/pattern_types/derives.rs b/tests/ui/type/pattern_types/derives.rs
index 3878c47..a3959b3 100644
--- a/tests/ui/type/pattern_types/derives.rs
+++ b/tests/ui/type/pattern_types/derives.rs
@@ -1,4 +1,5 @@
-//! Check that pattern types don't implement traits of their base automatically
+//! Check that pattern types don't implement traits of their base automatically.
+//! Exceptions are `Clone` and `Copy`, which have builtin impls for pattern types.
#![feature(pattern_types)]
#![feature(pattern_type_macro)]
diff --git a/tests/ui/type/pattern_types/derives.stderr b/tests/ui/type/pattern_types/derives.stderr
index f59617e..2d83684 100644
--- a/tests/ui/type/pattern_types/derives.stderr
+++ b/tests/ui/type/pattern_types/derives.stderr
@@ -1,5 +1,5 @@
error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999`
- --> $DIR/derives.rs:10:20
+ --> $DIR/derives.rs:11:20
|
LL | #[derive(Clone, Copy, PartialEq)]
| --------- in this derive macro expansion
diff --git a/tests/ui/type/pattern_types/derives_fail.rs b/tests/ui/type/pattern_types/derives_fail.rs
new file mode 100644
index 0000000..a3fbad6
--- /dev/null
+++ b/tests/ui/type/pattern_types/derives_fail.rs
@@ -0,0 +1,26 @@
+//! Check that pattern types don't implement traits of their base automatically.
+//! Exceptions are `Clone` and `Copy`, which have bultin impls for pattern types.
+
+#![feature(pattern_types)]
+#![feature(pattern_type_macro)]
+
+use std::pat::pattern_type;
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+#[repr(transparent)]
+struct Nanoseconds(NanoI32);
+//~^ ERROR: the trait bound `(i32) is 0..=999999999: Eq` is not satisfied
+//~| ERROR: `(i32) is 0..=999999999` doesn't implement `Debug`
+//~| ERROR: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied
+//~| ERROR: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied
+//~| ERROR: the trait bound `(i32) is 0..=999999999: Default` is not satisfied
+//~| ERROR: can't compare `(i32) is 0..=999999999` with `_`
+//~| ERROR: `==` cannot be applied
+
+type NanoI32 = crate::pattern_type!(i32 is 0..=999_999_999);
+
+fn main() {
+ let x = Nanoseconds(unsafe { std::mem::transmute(42) });
+ let y = x.clone();
+ if y == x {}
+}
diff --git a/tests/ui/type/pattern_types/derives_fail.stderr b/tests/ui/type/pattern_types/derives_fail.stderr
new file mode 100644
index 0000000..78bef72
--- /dev/null
+++ b/tests/ui/type/pattern_types/derives_fail.stderr
@@ -0,0 +1,74 @@
+error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999`
+ --> $DIR/derives_fail.rs:11:20
+ |
+LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+ | --------- in this derive macro expansion
+LL | #[repr(transparent)]
+LL | struct Nanoseconds(NanoI32);
+ | ^^^^^^^
+
+error[E0277]: the trait bound `(i32) is 0..=999999999: Eq` is not satisfied
+ --> $DIR/derives_fail.rs:11:20
+ |
+LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+ | -- in this derive macro expansion
+LL | #[repr(transparent)]
+LL | struct Nanoseconds(NanoI32);
+ | ^^^^^^^ the trait `Eq` is not implemented for `(i32) is 0..=999999999`
+ |
+note: required by a bound in `AssertParamIsEq`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+
+error[E0277]: `(i32) is 0..=999999999` doesn't implement `Debug`
+ --> $DIR/derives_fail.rs:11:20
+ |
+LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+ | ----- in this derive macro expansion
+LL | #[repr(transparent)]
+LL | struct Nanoseconds(NanoI32);
+ | ^^^^^^^ `(i32) is 0..=999999999` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = help: the trait `Debug` is not implemented for `(i32) is 0..=999999999`
+
+error[E0277]: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied
+ --> $DIR/derives_fail.rs:11:20
+ |
+LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+ | --- in this derive macro expansion
+LL | #[repr(transparent)]
+LL | struct Nanoseconds(NanoI32);
+ | ^^^^^^^ the trait `Ord` is not implemented for `(i32) is 0..=999999999`
+
+error[E0277]: can't compare `(i32) is 0..=999999999` with `_`
+ --> $DIR/derives_fail.rs:11:20
+ |
+LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+ | ---------- in this derive macro expansion
+LL | #[repr(transparent)]
+LL | struct Nanoseconds(NanoI32);
+ | ^^^^^^^ no implementation for `(i32) is 0..=999999999 < _` and `(i32) is 0..=999999999 > _`
+ |
+ = help: the trait `PartialOrd<_>` is not implemented for `(i32) is 0..=999999999`
+
+error[E0277]: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied
+ --> $DIR/derives_fail.rs:11:20
+ |
+LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+ | ---- in this derive macro expansion
+LL | #[repr(transparent)]
+LL | struct Nanoseconds(NanoI32);
+ | ^^^^^^^ the trait `Hash` is not implemented for `(i32) is 0..=999999999`
+
+error[E0277]: the trait bound `(i32) is 0..=999999999: Default` is not satisfied
+ --> $DIR/derives_fail.rs:11:20
+ |
+LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
+ | ------- in this derive macro expansion
+LL | #[repr(transparent)]
+LL | struct Nanoseconds(NanoI32);
+ | ^^^^^^^ the trait `Default` is not implemented for `(i32) is 0..=999999999`
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0277, E0369.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/type/pattern_types/matching.rs b/tests/ui/type/pattern_types/matching.rs
new file mode 100644
index 0000000..b8463a8
--- /dev/null
+++ b/tests/ui/type/pattern_types/matching.rs
@@ -0,0 +1,26 @@
+#![feature(pattern_types, pattern_type_macro, structural_match)]
+
+//@ check-pass
+
+use std::marker::StructuralPartialEq;
+use std::pat::pattern_type;
+
+struct Thing(pattern_type!(u32 is 1..));
+
+impl StructuralPartialEq for Thing {}
+impl PartialEq for Thing {
+ fn eq(&self, other: &Thing) -> bool {
+ unsafe { std::mem::transmute::<_, u32>(self.0) == std::mem::transmute::<_, u32>(other.0) }
+ }
+}
+
+impl Eq for Thing {}
+
+const TWO: Thing = Thing(2);
+
+const _: () = match TWO {
+ TWO => {}
+ _ => unreachable!(),
+};
+
+fn main() {}
diff --git a/tests/ui/type/pattern_types/matching_fail.rs b/tests/ui/type/pattern_types/matching_fail.rs
new file mode 100644
index 0000000..8e2c741
--- /dev/null
+++ b/tests/ui/type/pattern_types/matching_fail.rs
@@ -0,0 +1,25 @@
+#![feature(pattern_types, pattern_type_macro, structural_match)]
+
+use std::pat::pattern_type;
+
+const THREE: pattern_type!(u32 is 1..) = 3;
+
+const _: () = match THREE {
+ THREE => {}
+ //~^ ERROR non-structural type
+ _ => unreachable!(),
+};
+
+const _: () = match THREE {
+ 3 => {}
+ //~^ ERROR mismatched types
+ _ => unreachable!(),
+};
+
+const _: () = match 3 {
+ THREE => {}
+ //~^ ERROR mismatched types
+ _ => unreachable!(),
+};
+
+fn main() {}
diff --git a/tests/ui/type/pattern_types/matching_fail.stderr b/tests/ui/type/pattern_types/matching_fail.stderr
new file mode 100644
index 0000000..446180d
--- /dev/null
+++ b/tests/ui/type/pattern_types/matching_fail.stderr
@@ -0,0 +1,43 @@
+error: constant of non-structural type `(u32) is 1..` in a pattern
+ --> $DIR/matching_fail.rs:8:5
+ |
+LL | const THREE: pattern_type!(u32 is 1..) = 3;
+ | -------------------------------------- constant defined here
+...
+LL | THREE => {}
+ | ^^^^^ constant of non-structural type
+ |
+ = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+
+error[E0308]: mismatched types
+ --> $DIR/matching_fail.rs:14:5
+ |
+LL | const _: () = match THREE {
+ | ----- this expression has type `(u32) is 1..`
+LL | 3 => {}
+ | ^ expected `(u32) is 1..`, found integer
+ |
+ = note: expected pattern type `(u32) is 1..`
+ found type `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/matching_fail.rs:20:5
+ |
+LL | const THREE: pattern_type!(u32 is 1..) = 3;
+ | -------------------------------------- constant defined here
+...
+LL | const _: () = match 3 {
+ | - this expression has type `{integer}`
+LL | THREE => {}
+ | ^^^^^
+ | |
+ | expected integer, found `(u32) is 1..`
+ | `THREE` is interpreted as a constant, not a new binding
+ | help: introduce a new binding instead: `other_three`
+ |
+ = note: expected type `{integer}`
+ found pattern type `(u32) is 1..`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type/type-ascription-instead-of-statement-end.stderr b/tests/ui/type/type-ascription-instead-of-statement-end.stderr
index 34759b4..82b7fd2 100644
--- a/tests/ui/type/type-ascription-instead-of-statement-end.stderr
+++ b/tests/ui/type/type-ascription-instead-of-statement-end.stderr
@@ -4,7 +4,6 @@
LL | println!("test"):
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a semicolon instead
|
LL - println!("test"):
diff --git a/tests/ui/type/type-ascription-precedence.stderr b/tests/ui/type/type-ascription-precedence.stderr
index 09cdc37..f7ae612 100644
--- a/tests/ui/type/type-ascription-precedence.stderr
+++ b/tests/ui/type/type-ascription-precedence.stderr
@@ -33,8 +33,6 @@
|
LL | S .. S: S;
| ^ expected identifier
- |
- = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:`
--> $DIR/type-ascription-precedence.rs:53:13
diff --git a/tests/ui/type/type-ascription-with-fn-call.stderr b/tests/ui/type/type-ascription-with-fn-call.stderr
index 4222762..803c9f1 100644
--- a/tests/ui/type/type-ascription-with-fn-call.stderr
+++ b/tests/ui/type/type-ascription-with-fn-call.stderr
@@ -4,7 +4,6 @@
LL | f() :
| ^
|
- = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>
help: use a semicolon instead
|
LL - f() :
diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs
index 0be1237..dd83395 100644
--- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs
+++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs
@@ -1,4 +1,5 @@
//@ edition:2018
+//@ dont-require-annotations: SUGGESTION
async fn hello() { //~ HELP try adding a return type
0
diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
index c46f4ec..3680df2 100644
--- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
+++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:5:5
|
LL | async fn hello() {
| - help: try adding a return type: `-> i32`
@@ -7,7 +7,7 @@
| ^ expected `()`, found integer
error[E0308]: mismatched types
- --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:10:5
|
LL | async fn world() -> () {
| -- expected `()` because of return type
@@ -15,13 +15,13 @@
| ^ expected `()`, found integer
error[E0308]: mismatched types
- --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:15:5
|
LL | hello()
| ^^^^^^^ expected `()`, found future
|
note: calling an async function returns a future
- --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:15:5
|
LL | hello()
| ^^^^^^^
diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs
index 9304e20..6005bc9 100644
--- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs
+++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs
@@ -1,6 +1,7 @@
//~ ERROR unknown lint: `test_unstable_lint`
+//~^ NOTE the `test_unstable_lint` lint is unstable
//@ check-fail
//@ compile-flags: -Dunknown_lints -Atest_unstable_lint
-//@ error-pattern: the `test_unstable_lint` lint is unstable
+//@ dont-require-annotations: NOTE
fn main() {}
diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs
index 7698341..c32a21a 100644
--- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs
+++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs
@@ -1,6 +1,7 @@
//~ WARN unknown lint: `test_unstable_lint`
+//~^ NOTE the `test_unstable_lint` lint is unstable
//@ check-pass
//@ compile-flags: -Wunknown_lints -Atest_unstable_lint
-//@ error-pattern: the `test_unstable_lint` lint is unstable
+//@ dont-require-annotations: NOTE
fn main() {}
diff --git a/tests/ui/unpretty/bad-literal.rs b/tests/ui/unpretty/bad-literal.rs
index 3737789..0ec1d7b 100644
--- a/tests/ui/unpretty/bad-literal.rs
+++ b/tests/ui/unpretty/bad-literal.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=hir
//@ check-fail
+//@ edition: 2015
// In #100948 this caused an ICE with -Zunpretty=hir.
fn main() {
diff --git a/tests/ui/unpretty/bad-literal.stderr b/tests/ui/unpretty/bad-literal.stderr
index b625948..fd1801a 100644
--- a/tests/ui/unpretty/bad-literal.stderr
+++ b/tests/ui/unpretty/bad-literal.stderr
@@ -1,5 +1,5 @@
error: invalid suffix `u` for number literal
- --> $DIR/bad-literal.rs:6:5
+ --> $DIR/bad-literal.rs:7:5
|
LL | 1u;
| ^^ invalid suffix `u`
diff --git a/tests/ui/unpretty/bad-literal.stdout b/tests/ui/unpretty/bad-literal.stdout
index c527271..06116a4 100644
--- a/tests/ui/unpretty/bad-literal.stdout
+++ b/tests/ui/unpretty/bad-literal.stdout
@@ -4,6 +4,7 @@
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-fail
+//@ edition: 2015
// In #100948 this caused an ICE with -Zunpretty=hir.
fn main() {
diff --git a/tests/ui/unpretty/debug-fmt-hir.rs b/tests/ui/unpretty/debug-fmt-hir.rs
index c19f3c4..c79349d 100644
--- a/tests/ui/unpretty/debug-fmt-hir.rs
+++ b/tests/ui/unpretty/debug-fmt-hir.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
use std::fmt;
diff --git a/tests/ui/unpretty/debug-fmt-hir.stdout b/tests/ui/unpretty/debug-fmt-hir.stdout
index 2c9c96d..dc18675 100644
--- a/tests/ui/unpretty/debug-fmt-hir.stdout
+++ b/tests/ui/unpretty/debug-fmt-hir.stdout
@@ -4,6 +4,7 @@
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
use std::fmt;
diff --git a/tests/ui/unpretty/deprecated-attr.rs b/tests/ui/unpretty/deprecated-attr.rs
index dda362a..0c80203 100644
--- a/tests/ui/unpretty/deprecated-attr.rs
+++ b/tests/ui/unpretty/deprecated-attr.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
#[deprecated]
pub struct PlainDeprecated;
diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout
index 42de7b4..97d863b 100644
--- a/tests/ui/unpretty/deprecated-attr.stdout
+++ b/tests/ui/unpretty/deprecated-attr.stdout
@@ -4,6 +4,7 @@
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
struct PlainDeprecated;
diff --git a/tests/ui/unpretty/diagnostic-attr.rs b/tests/ui/unpretty/diagnostic-attr.rs
index 27f5b69..4ef85c7 100644
--- a/tests/ui/unpretty/diagnostic-attr.rs
+++ b/tests/ui/unpretty/diagnostic-attr.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
#[diagnostic::on_unimplemented(
message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`",
diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout
index e8696d0..81d71b9 100644
--- a/tests/ui/unpretty/diagnostic-attr.stdout
+++ b/tests/ui/unpretty/diagnostic-attr.stdout
@@ -4,6 +4,7 @@
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
#[diagnostic::on_unimplemented(message =
"My Message for `ImportantTrait<{A}>` implemented for `{Self}`", label =
diff --git a/tests/ui/unpretty/expanded-interpolation.rs b/tests/ui/unpretty/expanded-interpolation.rs
index 1dc72c6..0c447ae 100644
--- a/tests/ui/unpretty/expanded-interpolation.rs
+++ b/tests/ui/unpretty/expanded-interpolation.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=expanded
//@ check-pass
+//@ edition: 2015
// This test covers the AST pretty-printer's insertion of parentheses in some
// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in
diff --git a/tests/ui/unpretty/expanded-interpolation.stdout b/tests/ui/unpretty/expanded-interpolation.stdout
index 556e57d..10729a9 100644
--- a/tests/ui/unpretty/expanded-interpolation.stdout
+++ b/tests/ui/unpretty/expanded-interpolation.stdout
@@ -2,6 +2,7 @@
#![no_std]
//@ compile-flags: -Zunpretty=expanded
//@ check-pass
+//@ edition: 2015
// This test covers the AST pretty-printer's insertion of parentheses in some
// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in
diff --git a/tests/ui/unpretty/flattened-format-args.rs b/tests/ui/unpretty/flattened-format-args.rs
index 772f44c..ab065f4 100644
--- a/tests/ui/unpretty/flattened-format-args.rs
+++ b/tests/ui/unpretty/flattened-format-args.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=hir -Zflatten-format-args=yes
//@ check-pass
+//@ edition: 2015
fn main() {
let x = 1;
diff --git a/tests/ui/unpretty/flattened-format-args.stdout b/tests/ui/unpretty/flattened-format-args.stdout
index 2de1cdd..a5d9432 100644
--- a/tests/ui/unpretty/flattened-format-args.stdout
+++ b/tests/ui/unpretty/flattened-format-args.stdout
@@ -4,6 +4,7 @@
extern crate std;
//@ compile-flags: -Zunpretty=hir -Zflatten-format-args=yes
//@ check-pass
+//@ edition: 2015
fn main() {
let x = 1;
diff --git a/tests/ui/unpretty/let-else-hir.rs b/tests/ui/unpretty/let-else-hir.rs
index 9c23118..786c84a 100644
--- a/tests/ui/unpretty/let-else-hir.rs
+++ b/tests/ui/unpretty/let-else-hir.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
diff --git a/tests/ui/unpretty/let-else-hir.stdout b/tests/ui/unpretty/let-else-hir.stdout
index a2ffa5d..a6dd943 100644
--- a/tests/ui/unpretty/let-else-hir.stdout
+++ b/tests/ui/unpretty/let-else-hir.stdout
@@ -4,6 +4,7 @@
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
diff --git a/tests/ui/unpretty/self-hir.rs b/tests/ui/unpretty/self-hir.rs
index 448d828..70e0ba5 100644
--- a/tests/ui/unpretty/self-hir.rs
+++ b/tests/ui/unpretty/self-hir.rs
@@ -1,5 +1,6 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
pub struct Bar {
a: String,
diff --git a/tests/ui/unpretty/self-hir.stdout b/tests/ui/unpretty/self-hir.stdout
index 4da080d..a9e80b1 100644
--- a/tests/ui/unpretty/self-hir.stdout
+++ b/tests/ui/unpretty/self-hir.stdout
@@ -4,6 +4,7 @@
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass
+//@ edition: 2015
struct Bar {
a: String,
diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.rs b/tests/ui/unpretty/unpretty-expr-fn-arg.rs
index 7f496e7..b2ab2e0 100644
--- a/tests/ui/unpretty/unpretty-expr-fn-arg.rs
+++ b/tests/ui/unpretty/unpretty-expr-fn-arg.rs
@@ -6,6 +6,7 @@
//@ check-pass
//@ compile-flags: -Zunpretty=hir,typed
+//@ edition: 2015
#![allow(dead_code)]
fn main() {}
diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
index 43aa93c..fd2e794 100644
--- a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
+++ b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
@@ -6,6 +6,7 @@
//@ check-pass
//@ compile-flags: -Zunpretty=hir,typed
+//@ edition: 2015
#![allow(dead_code)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
diff --git a/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs
index 18aa329..c21eea7 100644
--- a/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs
+++ b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs
@@ -1,3 +1,3 @@
-//@ compile-flags: --edition=2018
+//@ edition: 2018
pub use u32;
diff --git a/tests/ui/wasm/wasm-import-module.rs b/tests/ui/wasm/wasm-import-module.rs
index bff0884..2b3bca9 100644
--- a/tests/ui/wasm/wasm-import-module.rs
+++ b/tests/ui/wasm/wasm-import-module.rs
@@ -15,7 +15,7 @@
#[link(wasm_import_module = "foo", kind = "dylib")] //~ ERROR: `wasm_import_module` is incompatible with other arguments
extern "C" {}
-#[link(wasm_import_module = "foo", cfg(FALSE))] //~ ERROR: `wasm_import_module` is incompatible with other arguments
+#[link(wasm_import_module = "foo", cfg(false))] //~ ERROR: `wasm_import_module` is incompatible with other arguments
extern "C" {}
fn main() {}
diff --git a/tests/ui/wasm/wasm-import-module.stderr b/tests/ui/wasm/wasm-import-module.stderr
index e792c33..84f4379 100644
--- a/tests/ui/wasm/wasm-import-module.stderr
+++ b/tests/ui/wasm/wasm-import-module.stderr
@@ -31,7 +31,7 @@
error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
--> $DIR/wasm-import-module.rs:18:8
|
-LL | #[link(wasm_import_module = "foo", cfg(FALSE))]
+LL | #[link(wasm_import_module = "foo", cfg(false))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
diff --git a/triagebot.toml b/triagebot.toml
index 4b6af3a..226f024 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1126,6 +1126,7 @@
"fmease",
"jyn514",
"Noratrieb",
+ "spastorino",
]
[[assign.warn_non_default_branch.exceptions]]